blob: 743e4e70313510ca9799656e04a16cd6c8d2ec1f [file] [log] [blame]
Dan Talaycod2ca1032010-03-10 14:40:26 -08001import sys
Dan Talayco92c99122010-06-03 13:53:18 -07002import copy
Rich Lane6242d9f2013-01-06 17:35:39 -08003import logging
4import types
5import time
Rich Lane5a9a1922013-01-11 14:29:30 -08006import re
Rich Lanea68176f2013-08-09 17:41:05 -07007import packet as scapy
Dan Talayco41eae8b2010-03-10 13:57:06 -08008
Rich Lanecd97d3d2013-01-07 18:50:06 -08009import oftest
10import oftest.controller
11import oftest.dataplane
Rich Lanef6883512013-03-11 17:00:09 -070012import oftest.parse
Rich Lane4c504f32013-06-07 17:24:14 -070013import oftest.ofutils
Rich Lanee717c6e2013-03-12 10:25:50 -070014import ofp
Dan Talaycoc901f4d2010-03-07 21:55:45 -080015
Dan Talaycoba3745c2010-07-21 21:51:08 -070016global skipped_test_count
17skipped_test_count = 0
18
Rich Lane7744e112013-01-11 17:23:57 -080019_import_blacklist = set(locals().keys())
20
Dan Talayco551befa2010-07-15 17:05:32 -070021# Some useful defines
22IP_ETHERTYPE = 0x800
23TCP_PROTOCOL = 0x6
24UDP_PROTOCOL = 0x11
25
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000026MINSIZE = 0
27
Tony van der Peet80c5b202013-11-20 11:47:48 +130028def delete_all_flows(ctrl, send_barrier=True):
Dan Talayco41eae8b2010-03-10 13:57:06 -080029 """
30 Delete all flows on the switch
31 @param ctrl The controller object for the test
Tony van der Peet80c5b202013-11-20 11:47:48 +130032 @param send_barrier Whether or not to send a barrier message
Dan Talayco41eae8b2010-03-10 13:57:06 -080033 """
34
Rich Lane9a003812012-10-04 17:17:59 -070035 logging.info("Deleting all flows")
Rich Lanee717c6e2013-03-12 10:25:50 -070036 msg = ofp.message.flow_delete()
Rich Lanec717f442013-06-13 15:49:09 -070037 if ofp.OFP_VERSION in [1, 2]:
38 msg.match.wildcards = ofp.OFPFW_ALL
39 msg.out_port = ofp.OFPP_NONE
40 msg.buffer_id = 0xffffffff
41 elif ofp.OFP_VERSION >= 3:
42 msg.table_id = ofp.OFPTT_ALL
43 msg.buffer_id = ofp.OFP_NO_BUFFER
44 msg.out_port = ofp.OFPP_ANY
45 msg.out_group = ofp.OFPG_ANY
Rich Lane5c3151c2013-01-03 17:15:41 -080046 ctrl.message_send(msg)
Tony van der Peet80c5b202013-11-20 11:47:48 +130047 if send_barrier:
48 do_barrier(ctrl)
Rich Lane32bf9482013-01-03 17:26:30 -080049 return 0 # for backwards compatibility
Dan Talayco41eae8b2010-03-10 13:57:06 -080050
Rich Lane5f3c9b22013-10-10 17:20:30 -070051def delete_all_groups(ctrl):
52 """
53 Delete all groups on the switch
54 @param ctrl The controller object for the test
55 """
56
57 logging.info("Deleting all groups")
58 msg = ofp.message.group_mod(
59 command=ofp.OFPGC_DELETE, group_id=ofp.OFPG_ALL)
60 ctrl.message_send(msg)
61 do_barrier(ctrl)
62
Ed Swierk99a74de2012-08-22 06:40:54 -070063def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070064 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070065 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -070066 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
67 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -070068 else:
69 return 0
70
Dan Talayco41eae8b2010-03-10 13:57:06 -080071def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -070072 eth_dst='00:01:02:03:04:05',
73 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070074 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -070075 vlan_vid=0,
76 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -070077 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -080078 ip_src='192.168.0.1',
79 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070080 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -080081 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -080082 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070083 tcp_dport=80,
84 ip_ihl=None,
85 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -080086 ):
87 """
88 Return a simple dataplane TCP packet
89
90 Supports a few parameters:
91 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -070092 @param eth_dst Destinatino MAC
93 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -070094 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -070095 @param vlan_vid VLAN ID
96 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -080097 @param ip_src IP source
98 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -070099 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800100 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800101 @param tcp_dport TCP destination port
102 @param ip_sport TCP source port
103
104 Generates a simple TCP request. Users
105 shouldn't assume anything about this packet other than that
106 it is a valid ethernet/IP/TCP frame.
107 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000108
109 if MINSIZE > pktlen:
110 pktlen = MINSIZE
111
Dan Talayco551befa2010-07-15 17:05:32 -0700112 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800113 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700114 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
115 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800116 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700117 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
118 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700119 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700120 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800121 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700122 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
123 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700124 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800125 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700126 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700127
Dan Talayco41eae8b2010-03-10 13:57:06 -0800128 pkt = pkt/("D" * (pktlen - len(pkt)))
129
130 return pkt
131
Rich Lane86aceb02013-07-17 18:45:38 -0700132def simple_tcpv6_packet(pktlen=100,
133 eth_dst='00:01:02:03:04:05',
134 eth_src='00:06:07:08:09:0a',
135 dl_vlan_enable=False,
136 vlan_vid=0,
137 vlan_pcp=0,
138 ipv6_src='2001:db8:85a3::8a2e:370:7334',
139 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
140 ipv6_tc=0,
141 ipv6_hlim=64,
142 ipv6_fl=0,
143 tcp_sport=1234,
144 tcp_dport=80):
145 """
146 Return a simple IPv6/TCP packet
147
148 Supports a few parameters:
149 @param len Length of packet in bytes w/o CRC
150 @param eth_dst Destination MAC
151 @param eth_src Source MAC
152 @param dl_vlan_enable True if the packet is with vlan, False otherwise
153 @param vlan_vid VLAN ID
154 @param vlan_pcp VLAN priority
155 @param ipv6_src IPv6 source
156 @param ipv6_dst IPv6 destination
157 @param ipv6_tc IPv6 traffic class
158 @param ipv6_ttl IPv6 hop limit
159 @param ipv6_fl IPv6 flow label
160 @param tcp_dport TCP destination port
161 @param tcp_sport TCP source port
162
163 Generates a simple TCP request. Users shouldn't assume anything about this
164 packet other than that it is a valid ethernet/IPv6/TCP frame.
165 """
166
167 if MINSIZE > pktlen:
168 pktlen = MINSIZE
169
170 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
171 if dl_vlan_enable or vlan_vid or vlan_pcp:
172 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
173 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
174 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport)
175 pkt /= ("D" * (pktlen - len(pkt)))
176
177 return pkt
178
Rich Lane6ee7bea2012-10-26 16:19:29 -0700179def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700180 eth_dst='00:01:02:03:04:05',
181 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700182 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700183 vlan_vid=0,
184 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700185 dl_vlan_cfi=0,
186 ip_src='192.168.0.1',
187 ip_dst='192.168.0.2',
188 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800189 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700190 udp_sport=1234,
191 udp_dport=80,
192 ip_ihl=None,
193 ip_options=False
194 ):
195 """
196 Return a simple dataplane UDP packet
197
198 Supports a few parameters:
199 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700200 @param eth_dst Destination MAC
201 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700202 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700203 @param vlan_vid VLAN ID
204 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700205 @param ip_src IP source
206 @param ip_dst IP destination
207 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800208 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700209 @param udp_dport UDP destination port
210 @param udp_sport UDP source port
211
212 Generates a simple UDP packet. Users shouldn't assume anything about
213 this packet other than that it is a valid ethernet/IP/UDP frame.
214 """
215
216 if MINSIZE > pktlen:
217 pktlen = MINSIZE
218
219 # Note Dot1Q.id is really CFI
220 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700221 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
222 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800223 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700224 scapy.UDP(sport=udp_sport, dport=udp_dport)
225 else:
226 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700227 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800228 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700229 scapy.UDP(sport=udp_sport, dport=udp_dport)
230 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700231 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800232 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700233 scapy.UDP(sport=udp_sport, dport=udp_dport)
234
235 pkt = pkt/("D" * (pktlen - len(pkt)))
236
237 return pkt
238
Rich Lane86aceb02013-07-17 18:45:38 -0700239def simple_udpv6_packet(pktlen=100,
240 eth_dst='00:01:02:03:04:05',
241 eth_src='00:06:07:08:09:0a',
242 dl_vlan_enable=False,
243 vlan_vid=0,
244 vlan_pcp=0,
245 ipv6_src='2001:db8:85a3::8a2e:370:7334',
246 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
247 ipv6_tc=0,
248 ipv6_hlim=64,
249 ipv6_fl=0,
250 udp_sport=1234,
251 udp_dport=80):
252 """
253 Return a simple IPv6/UDP packet
254
255 Supports a few parameters:
256 @param len Length of packet in bytes w/o CRC
257 @param eth_dst Destination MAC
258 @param eth_src Source MAC
259 @param dl_vlan_enable True if the packet is with vlan, False otherwise
260 @param vlan_vid VLAN ID
261 @param vlan_pcp VLAN priority
262 @param ipv6_src IPv6 source
263 @param ipv6_dst IPv6 destination
264 @param ipv6_tc IPv6 traffic class
265 @param ipv6_ttl IPv6 hop limit
266 @param ipv6_fl IPv6 flow label
267 @param udp_dport UDP destination port
268 @param udp_sport UDP source port
269
270 Generates a simple UDP request. Users shouldn't assume anything about this
271 packet other than that it is a valid ethernet/IPv6/UDP frame.
272 """
273
274 if MINSIZE > pktlen:
275 pktlen = MINSIZE
276
277 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
278 if dl_vlan_enable or vlan_vid or vlan_pcp:
279 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
280 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
281 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
282 pkt /= ("D" * (pktlen - len(pkt)))
283
284 return pkt
285
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700286def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700287 eth_dst='00:01:02:03:04:05',
288 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700289 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700290 vlan_vid=0,
291 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700292 ip_src='192.168.0.1',
293 ip_dst='192.168.0.2',
294 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800295 ip_ttl=64,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700296 icmp_type=8,
297 icmp_code=0
298 ):
299 """
300 Return a simple ICMP packet
301
302 Supports a few parameters:
303 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700304 @param eth_dst Destinatino MAC
305 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700306 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700307 @param vlan_vid VLAN ID
308 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700309 @param ip_src IP source
310 @param ip_dst IP destination
311 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800312 @param ip_ttl IP TTL
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700313 @param icmp_type ICMP type
314 @param icmp_code ICMP code
315
316 Generates a simple ICMP ECHO REQUEST. Users
317 shouldn't assume anything about this packet other than that
318 it is a valid ethernet/ICMP frame.
319 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000320
321 if MINSIZE > pktlen:
322 pktlen = MINSIZE
323
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700324 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700325 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
326 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800327 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos)/ \
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700328 scapy.ICMP(type=icmp_type, code=icmp_code)
329 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700330 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800331 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos)/ \
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700332 scapy.ICMP(type=icmp_type, code=icmp_code)
333
334 pkt = pkt/("0" * (pktlen - len(pkt)))
335
336 return pkt
337
Rich Lane86aceb02013-07-17 18:45:38 -0700338def simple_icmpv6_packet(pktlen=100,
339 eth_dst='00:01:02:03:04:05',
340 eth_src='00:06:07:08:09:0a',
341 dl_vlan_enable=False,
342 vlan_vid=0,
343 vlan_pcp=0,
344 ipv6_src='2001:db8:85a3::8a2e:370:7334',
345 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
346 ipv6_tc=0,
347 ipv6_hlim=64,
348 ipv6_fl=0,
349 icmp_type=8,
350 icmp_code=0):
351 """
352 Return a simple ICMPv6 packet
353
354 Supports a few parameters:
355 @param len Length of packet in bytes w/o CRC
356 @param eth_dst Destination MAC
357 @param eth_src Source MAC
358 @param dl_vlan_enable True if the packet is with vlan, False otherwise
359 @param vlan_vid VLAN ID
360 @param vlan_pcp VLAN priority
361 @param ipv6_src IPv6 source
362 @param ipv6_dst IPv6 destination
363 @param ipv6_tc IPv6 traffic class
364 @param ipv6_ttl IPv6 hop limit
365 @param ipv6_fl IPv6 flow label
366 @param icmp_type ICMP type
367 @param icmp_code ICMP code
368
369 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
370 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
371 """
372
373 if MINSIZE > pktlen:
374 pktlen = MINSIZE
375
376 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
377 if dl_vlan_enable or vlan_vid or vlan_pcp:
378 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
379 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
380 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
381 pkt /= ("D" * (pktlen - len(pkt)))
382
383 return pkt
384
Shudong Zhouc7562b12013-02-06 01:12:18 -0800385def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700386 eth_dst='ff:ff:ff:ff:ff:ff',
387 eth_src='00:06:07:08:09:0a',
Shudong Zhouc7562b12013-02-06 01:12:18 -0800388 arp_op=1,
389 ip_snd='192.168.0.1',
390 ip_tgt='192.168.0.2',
391 hw_snd='00:06:07:08:09:0a',
392 hw_tgt='00:00:00:00:00:00',
393 ):
394 """
395 Return a simple ARP packet
396
397 Supports a few parameters:
398 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700399 @param eth_dst Destinatino MAC
400 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800401 @param arp_op Operation (1=request, 2=reply)
402 @param ip_snd Sender IP
403 @param ip_tgt Target IP
404 @param hw_snd Sender hardware address
405 @param hw_tgt Target hardware address
406
407 Generates a simple ARP REQUEST. Users
408 shouldn't assume anything about this packet other than that
409 it is a valid ethernet/ARP frame.
410 """
411
412 if MINSIZE > pktlen:
413 pktlen = MINSIZE
414
Rich Laned0478ff2013-03-11 12:46:58 -0700415 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhouc7562b12013-02-06 01:12:18 -0800416 scapy.ARP(hwsrc=hw_snd, hwdst=hw_tgt, pdst=ip_tgt, psrc=ip_snd, op=arp_op)
417
418 pkt = pkt/("0" * (pktlen - len(pkt)))
419
420 return pkt
421
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700422def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800423 eth_dst='00:01:02:03:04:05',
424 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700425 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000426
427 if MINSIZE > pktlen:
428 pktlen = MINSIZE
429
Rich Laned0478ff2013-03-11 12:46:58 -0700430 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700431
432 pkt = pkt/("0" * (pktlen - len(pkt)))
433
434 return pkt
435
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800436def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700437 eth_dst='00:01:02:03:04:05',
438 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800439 dl_vlan_outer=20,
440 dl_vlan_pcp_outer=0,
441 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700442 vlan_vid=10,
443 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800444 dl_vlan_cfi=0,
445 ip_src='192.168.0.1',
446 ip_dst='192.168.0.2',
447 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800448 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800449 tcp_sport=1234,
450 tcp_dport=80,
451 ip_ihl=None,
452 ip_options=False
453 ):
454 """
455 Return a doubly tagged dataplane TCP packet
456
457 Supports a few parameters:
458 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700459 @param eth_dst Destinatino MAC
460 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800461 @param dl_vlan_outer Outer VLAN ID
462 @param dl_vlan_pcp_outer Outer VLAN priority
463 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700464 @param vlan_vid Inner VLAN ID
465 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800466 @param dl_vlan_cfi VLAN cfi bit
467 @param ip_src IP source
468 @param ip_dst IP destination
469 @param ip_tos IP ToS
470 @param tcp_dport TCP destination port
471 @param ip_sport TCP source port
472
473 Generates a TCP request. Users
474 shouldn't assume anything about this packet other than that
475 it is a valid ethernet/IP/TCP frame.
476 """
477
478 if MINSIZE > pktlen:
479 pktlen = MINSIZE
480
481 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700482 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800483 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700484 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800485 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800486 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
487
488 pkt = pkt/("D" * (pktlen - len(pkt)))
489
490 return pkt
491
Shudong Zhoub7f12462012-11-20 13:01:12 -0800492def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700493 """
494 Do a barrier command
495 Return 0 on success, -1 on error
496 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700497 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800498 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800499 if resp is None:
500 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700501 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800502 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700503
Rich Lane9a003812012-10-04 17:17:59 -0700504def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700505 """
506 Get a port's configuration
507
508 Gets the switch feature configuration and grabs one port's
509 configuration
510
511 @returns (hwaddr, config, advert) The hwaddress, configuration and
512 advertised values
513 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700514
515 if ofp.OFP_VERSION <= 3:
516 request = ofp.message.features_request()
517 reply, _ = controller.transact(request)
518 if reply is None:
519 logging.warn("Get feature request failed")
520 return None, None, None
521 logging.debug(reply.show())
522 ports = reply.ports
523 else:
524 request = ofp.message.port_desc_stats_request()
525 # TODO do multipart correctly
526 reply, _ = controller.transact(request)
527 if reply is None:
528 logging.warn("Port desc stats request failed")
529 return None, None, None
530 logging.debug(reply.show())
531 ports = reply.entries
532
533 for port in ports:
534 if port.port_no == port_no:
535 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700536
Rich Lane9a003812012-10-04 17:17:59 -0700537 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700538 return None, None, None
539
Rich Lane9a003812012-10-04 17:17:59 -0700540def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700541 """
542 Set the port configuration according the given parameters
543
544 Gets the switch feature configuration and updates one port's
545 configuration value according to config and mask
546 """
Rich Lane9a003812012-10-04 17:17:59 -0700547 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700548
549 hw_addr, _, _ = port_config_get(controller, port_no)
550
Rich Lanee717c6e2013-03-12 10:25:50 -0700551 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700552 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700553 if hw_addr != None:
554 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700555 mod.config = config
556 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700557 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800558 controller.message_send(mod)
559 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700560
Rich Lane2014f9b2012-10-05 15:29:40 -0700561def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700562 """
563 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700564 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700565 @param pkt Expected packet; may be None if yes_ports is empty
566 @param yes_ports Set or list of ports that should recieve packet
567 @param no_ports Set or list of ports that should not receive packet
568 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700569
570 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700571 """
Rich Lane91765672012-12-06 16:33:04 -0800572
573 # Wait this long for packets that we don't expect to receive.
574 # 100ms is (rarely) too short for positive tests on slow
575 # switches but is definitely not too short for a negative test.
576 negative_timeout = 0.1
577
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700578 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800579 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700580 exp_pkt_arg = pkt
581
Dan Talayco92c99122010-06-03 13:53:18 -0700582 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700583 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700584 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700585 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700586 assert_if.assertTrue(rcv_pkt is not None,
587 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800588 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800589 logging.debug("Expected %s" % format_packet(pkt))
590 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800591 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800592 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700593 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700594 if len(no_ports) > 0:
Rich Lane91765672012-12-06 16:33:04 -0800595 time.sleep(negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700596 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700597 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700598 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800599 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700600 assert_if.assertTrue(rcv_pkt is None,
601 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700602
603
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700604def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700605 """
606 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700607 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700608
609 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700610
611 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700612 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700613 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800614 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700615 exp_pkt_arg = exp_pkt
616
Dan Talaycof6e76c02012-03-23 10:56:12 -0700617 if type(egr_ports) == type([]):
618 egr_port_list = egr_ports
619 else:
620 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700621
Dan Talaycof6e76c02012-03-23 10:56:12 -0700622 # Expect a packet from each port on egr port list
623 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700624 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -0700625 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700626 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700627 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700628 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700629
Dan Talaycof6e76c02012-03-23 10:56:12 -0700630 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700631 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700632 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700633
Dan Talaycof6e76c02012-03-23 10:56:12 -0700634 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700635 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700636 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700637 str(rcv_port))
638
639 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700640 logging.error("ERROR: Packet match failed.")
641 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700642 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700643 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700644 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700645 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
646 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700647 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700648 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700649
Dan Talayco551befa2010-07-15 17:05:32 -0700650def match_verify(parent, req_match, res_match):
651 """
652 Verify flow matches agree; if they disagree, report where
653
654 parent must implement assertEqual
655 Use str() to ensure content is compared and not pointers
656 """
657
658 parent.assertEqual(req_match.wildcards, res_match.wildcards,
659 'Match failed: wildcards: ' + hex(req_match.wildcards) +
660 " != " + hex(res_match.wildcards))
661 parent.assertEqual(req_match.in_port, res_match.in_port,
662 'Match failed: in_port: ' + str(req_match.in_port) +
663 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -0700664 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
665 'Match failed: eth_src: ' + str(req_match.eth_src) +
666 " != " + str(res_match.eth_src))
667 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
668 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
669 " != " + str(res_match.eth_dst))
670 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
671 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
672 " != " + str(res_match.vlan_vid))
673 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
674 'Match failed: vlan_pcp: ' +
675 str(req_match.vlan_pcp) + " != " +
676 str(res_match.vlan_pcp))
677 parent.assertEqual(req_match.eth_type, res_match.eth_type,
678 'Match failed: eth_type: ' + str(req_match.eth_type) +
679 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -0700680
Rich Lanee717c6e2013-03-12 10:25:50 -0700681 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -0700682 and (req_match.eth_type == IP_ETHERTYPE)):
683 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
684 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
685 " != " + str(res_match.ip_dscp))
686 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
687 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
688 " != " + str(res_match.ip_proto))
689 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
690 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
691 " != " + str(res_match.ipv4_src))
692 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
693 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
694 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700695
Rich Lanee717c6e2013-03-12 10:25:50 -0700696 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -0700697 and ((req_match.ip_proto == TCP_PROTOCOL)
698 or (req_match.ip_proto == UDP_PROTOCOL))):
699 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
700 'Match failed: tcp_src: ' +
701 str(req_match.tcp_src) +
702 " != " + str(res_match.tcp_src))
703 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
704 'Match failed: tcp_dst: ' +
705 str(req_match.tcp_dst) +
706 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700707
Ed Swierk99a74de2012-08-22 06:40:54 -0700708def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -0700709 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -0700710 if ofp.OFP_VERSION in [1, 2]:
711 match.wildcards |= required_wildcards(parent)
712 else:
713 # TODO remove incompatible OXM entries
714 pass
Ed Swierk99a74de2012-08-22 06:40:54 -0700715 return match
716
717def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700718 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700719 """
720 Create a flow message
721
722 Match on packet with given wildcards.
723 See flow_match_test for other parameter descriptoins
724 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -0700725 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700726 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700727 """
Rich Lanef6883512013-03-11 17:00:09 -0700728 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -0700729 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -0700730 if wildcards is None:
731 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -0700732 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -0700733 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -0700734 match.wildcards = wildcards
735 match.in_port = ing_port
736
Dan Talaycof6e76c02012-03-23 10:56:12 -0700737 if type(egr_ports) == type([]):
738 egr_port_list = egr_ports
739 else:
740 egr_port_list = [egr_ports]
741
Rich Lanee717c6e2013-03-12 10:25:50 -0700742 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -0700743 request.match = match
744 request.buffer_id = 0xffffffff
745 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -0700746 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -0700747 request.hard_timeout = 1
748
Rich Lane400fb9b2013-10-10 17:20:54 -0700749 if ofp.OFP_VERSION == 1:
750 actions = request.actions
751 else:
752 actions = []
753 request.instructions.append(ofp.instruction.apply_actions(actions))
754
Dan Talayco551befa2010-07-15 17:05:32 -0700755 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -0700756 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -0700757
758 # Set up output/enqueue action if directed
759 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -0700760 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -0700761 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -0700762 for egr_port in egr_port_list:
763 act.port = egr_port
764 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -0700765 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700766 elif egr_ports is not None:
767 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -0700768 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -0700769 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -0700770 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -0700771
Rich Lane9a003812012-10-04 17:17:59 -0700772 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -0700773
774 return request
775
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -0700776def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -0700777 """
778 Install a flow mod message in the switch
779
780 @param parent Must implement controller, assertEqual, assertTrue
781 @param request The request, all set to go
782 @param clear_table If true, clear the flow table before installing
783 """
Dan Talayco8a64e332012-03-28 14:53:20 -0700784
Rich Lane2014f9b2012-10-05 15:29:40 -0700785 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -0700786 if(clear_table_override != None):
787 clear_table = clear_table_override
788
789 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -0700790 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -0800791 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -0700792
Rich Lane9a003812012-10-04 17:17:59 -0700793 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800794 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -0800795
Rich Lane3a261d52013-01-03 17:45:08 -0800796 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -0700797
Ed Swierk99a74de2012-08-22 06:40:54 -0700798def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -0700799 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -0700800 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -0700801 """
802 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -0700803 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700804
805 Run test with packet through switch from ing_port to egr_port
806 See flow_match_test for parameter descriptions
807 """
808
Ed Swierk99a74de2012-08-22 06:40:54 -0700809 if wildcards is None:
810 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -0700811 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700812 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -0700813 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -0700814 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -0700815 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -0700816 if exp_pkt is None:
817 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -0700818
819 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700820 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -0700821 action_list=action_list)
822
823 flow_msg_install(parent, request)
824
Rich Lane9a003812012-10-04 17:17:59 -0700825 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700826 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -0700827 parent.dataplane.send(ing_port, str(pkt))
828
Rich Lane8f45e2d2013-10-01 16:06:54 -0700829 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -0700830 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -0700831
Rich Lane89725bb2012-12-03 16:23:27 -0800832def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -0700833 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -0800834 action_list=None):
835 """
836 Packet-out test on single TCP packet
837 @param egr_ports A single port or list of ports
838
839 Run test sending packet-out to egr_ports. The goal is to test the actions
840 taken on the packet, not the matching which is of course irrelevant.
841 See flow_match_test for parameter descriptions
842 """
843
844 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -0700845 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -0700846 if exp_pkt is None:
847 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -0800848
Rich Lanee717c6e2013-03-12 10:25:50 -0700849 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -0800850 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -0700851 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -0800852 msg.data = str(pkt)
853 if action_list is not None:
854 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -0800855 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -0800856
857 # Set up output action
858 if egr_ports is not None:
859 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -0700860 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -0800861 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800862 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -0800863
864 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -0800865 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -0800866
Rich Lane8f45e2d2013-10-01 16:06:54 -0700867 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -0700868 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -0800869
Dan Talaycof6e76c02012-03-23 10:56:12 -0700870def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
871 """
872 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -0700873 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -0700874 @param of_ports List of OF port numbers
875 @param how_many Number of ports to be added to the list
876 @param exclude_list List of ports not to be used
877 @returns An empty list if unable to find enough ports
878 """
879
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700880 if how_many == 0:
881 return []
882
Dan Talaycof6e76c02012-03-23 10:56:12 -0700883 count = 0
884 egr_ports = []
885 for egr_idx in range(len(of_ports)):
886 if of_ports[egr_idx] not in exclude_list:
887 egr_ports.append(of_ports[egr_idx])
888 count += 1
889 if count >= how_many:
890 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -0700891 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700892 return []
893
Rich Laned0478ff2013-03-11 12:46:58 -0700894def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -0700895 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700896 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700897 """
Rich Lane89725bb2012-12-03 16:23:27 -0800898 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -0700899
900 @param max_test If > 0 no more than this number of tests are executed.
901 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -0700902 and logging
Dan Talayco551befa2010-07-15 17:05:32 -0700903 @param pkt If not None, use this packet for ingress
904 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -0700905 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -0700906 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
907 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -0700908 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -0700909 """
Ed Swierk99a74de2012-08-22 06:40:54 -0700910 if wildcards is None:
911 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -0700912 of_ports = port_map.keys()
913 of_ports.sort()
914 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
915 test_count = 0
916
Dan Talaycocfa172f2012-03-23 12:03:00 -0700917 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -0700918 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -0700919
Dan Talayco551befa2010-07-15 17:05:32 -0700920 for ing_idx in range(len(of_ports)):
921 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -0700922 egr_ports = get_egr_list(parent, of_ports, egr_count,
923 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700924 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -0700925 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700926 if len(egr_ports) == 0:
927 parent.assertTrue(0, "Failed to generate egress port list")
928
929 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -0700930 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700931 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -0700932 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700933 test_count += 1
934 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -0700935 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -0800936 break
937
Ed Swierk38eea082013-01-02 19:46:20 -0800938 if not test_param_get('pktout_actions', default=True):
939 return
Rich Lane89725bb2012-12-03 16:23:27 -0800940
941 ingress_port = of_ports[0]
942 egr_ports = get_egr_list(parent, of_ports, egr_count,
943 exclude_list=[ingress_port])
944 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -0700945 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -0800946 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -0700947 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -0800948 pkt=pkt, exp_pkt=exp_pkt,
949 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -0700950
Rich Lane2014f9b2012-10-05 15:29:40 -0700951def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700952 """
953 Return value passed via test-params if present
954
Dan Talayco4b2bee62010-07-20 14:10:05 -0700955 @param key The lookup key
956 @param default Default value to use if not found
957
958 If the pair 'key=val' appeared in the string passed to --test-params
959 on the command line, return val (as interpreted by exec). Otherwise
960 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -0700961
962 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
963 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -0700964 """
965 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -0800966 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -0700967 except:
968 return default
969
Dan Talayco4b2bee62010-07-20 14:10:05 -0700970 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -0700971 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -0700972 except:
973 return default
974
975def action_generate(parent, field_to_mod, mod_field_vals):
976 """
977 Create an action to modify the field indicated in field_to_mod
978
979 @param parent Must implement, assertTrue
980 @param field_to_mod The field to modify as a string name
981 @param mod_field_vals Hash of values to use for modified values
982 """
983
984 act = None
985
986 if field_to_mod in ['pktlen']:
987 return None
988
Rich Laned0478ff2013-03-11 12:46:58 -0700989 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -0700990 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -0700991 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -0700992 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -0700993 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -0700994 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -0700995 elif field_to_mod == 'dl_vlan_enable':
996 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -0700997 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -0700998 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -0700999 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001000 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001001 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001002 act.vlan_vid = mod_field_vals['vlan_vid']
1003 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001004 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001005 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001006 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001007 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001008 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001009 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001010 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001011 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001012 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001013 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001014 act.nw_tos = mod_field_vals['ip_tos']
1015 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001016 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001017 act.tp_port = mod_field_vals['tcp_sport']
1018 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001019 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001020 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001021 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001022 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001023 act.tp_port = mod_field_vals['udp_sport']
1024 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001025 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001026 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001027 else:
1028 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1029
1030 return act
1031
1032def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001033 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001034 """
1035 Set up the ingress and expected packet and action list for a test
1036
Rich Lane2014f9b2012-10-05 15:29:40 -07001037 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001038 @param start_field_values Field values to use for ingress packet (optional)
1039 @param mod_field_values Field values to use for modified packet (optional)
1040 @param mod_fields The list of fields to be modified by the switch in the test.
1041 @params check_test_params If True, will check the parameters vid, add_vlan
1042 and strip_vlan from the command line.
1043
1044 Returns a triple: pkt-to-send, expected-pkt, action-list
1045 """
1046
1047 new_actions = []
1048
Dan Talayco4b2bee62010-07-20 14:10:05 -07001049 base_pkt_params = {}
1050 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001051 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1052 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001053 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001054 base_pkt_params['vlan_vid'] = 2
1055 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001056 base_pkt_params['ip_src'] = '192.168.0.1'
1057 base_pkt_params['ip_dst'] = '192.168.0.2'
1058 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001059 if tp == "tcp":
1060 base_pkt_params['tcp_sport'] = 1234
1061 base_pkt_params['tcp_dport'] = 80
1062 elif tp == "udp":
1063 base_pkt_params['udp_sport'] = 1234
1064 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001065 for keyname in start_field_vals.keys():
1066 base_pkt_params[keyname] = start_field_vals[keyname]
1067
1068 mod_pkt_params = {}
1069 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001070 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1071 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001072 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001073 mod_pkt_params['vlan_vid'] = 3
1074 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001075 mod_pkt_params['ip_src'] = '10.20.30.40'
1076 mod_pkt_params['ip_dst'] = '50.60.70.80'
1077 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001078 if tp == "tcp":
1079 mod_pkt_params['tcp_sport'] = 4321
1080 mod_pkt_params['tcp_dport'] = 8765
1081 elif tp == "udp":
1082 mod_pkt_params['udp_sport'] = 4321
1083 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001084 for keyname in mod_field_vals.keys():
1085 mod_pkt_params[keyname] = mod_field_vals[keyname]
1086
1087 # Check for test param modifications
1088 strip = False
1089 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001090 add_vlan = test_param_get('add_vlan')
1091 strip_vlan = test_param_get('strip_vlan')
1092 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001093
1094 if add_vlan and strip_vlan:
1095 parent.assertTrue(0, "Add and strip VLAN both specified")
1096
1097 if vid:
1098 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001099 base_pkt_params['vlan_vid'] = vid
1100 if 'vlan_vid' in mod_fields:
1101 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001102
1103 if add_vlan:
1104 base_pkt_params['dl_vlan_enable'] = False
1105 mod_pkt_params['dl_vlan_enable'] = True
1106 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1107 mod_fields.append('pktlen')
1108 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001109 if 'vlan_vid' not in mod_fields:
1110 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001111 elif strip_vlan:
1112 base_pkt_params['dl_vlan_enable'] = True
1113 mod_pkt_params['dl_vlan_enable'] = False
1114 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1115 mod_fields.append('dl_vlan_enable')
1116 mod_fields.append('pktlen')
1117
Rich Lane110e0e32012-10-26 16:21:46 -07001118 if tp == "tcp":
1119 packet_builder = simple_tcp_packet
1120 elif tp == "udp":
1121 packet_builder = simple_udp_packet
1122 else:
1123 raise NotImplementedError("unknown transport protocol %s" % tp)
1124
Dan Talayco4b2bee62010-07-20 14:10:05 -07001125 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001126 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001127
1128 # Build the expected packet, modifying the indicated fields
1129 for item in mod_fields:
1130 base_pkt_params[item] = mod_pkt_params[item]
1131 act = action_generate(parent, item, mod_pkt_params)
1132 if act:
1133 new_actions.append(act)
1134
Rich Lane110e0e32012-10-26 16:21:46 -07001135 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001136
1137 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001138
1139# Generate a simple "drop" flow mod
1140# If in_band is true, then only drop from first test port
1141def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001142 request = ofp.message.flow_add()
1143 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001144 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001145 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001146 for of_port, ifname in port_map.items(): # Grab first port
1147 break
1148 request.match.in_port = of_port
1149 request.buffer_id = 0xffffffff
1150 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001151
1152def skip_message_emit(parent, s):
1153 """
1154 Print out a 'skipped' message to stderr
1155
1156 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001157 """
1158 global skipped_test_count
1159
1160 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001161 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001162 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001163 sys.stderr.write("(skipped) ")
1164 else:
1165 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001166
Dan Talayco8a64e332012-03-28 14:53:20 -07001167
1168def all_stats_get(parent):
1169 """
1170 Get the aggregate stats for all flows in the table
1171 @param parent Test instance with controller connection and assert
1172 @returns dict with keys flows, packets, bytes, active (flows),
1173 lookups, matched
1174 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001175 stat_req = ofp.message.aggregate_stats_request()
1176 stat_req.match = ofp.match()
1177 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001178 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001179 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001180
1181 rv = {}
1182
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001183 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001184 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001185
Rich Lane5fd6faf2013-03-11 13:30:20 -07001186 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001187 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1188 obj.packet_count, obj.byte_count)
1189 break
1190
Rich Lanee717c6e2013-03-12 10:25:50 -07001191 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001192 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001193
1194
1195 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001196 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001197 rv["active"] += obj.active_count
1198 rv["lookups"] += obj.lookup_count
1199 rv["matched"] += obj.matched_count
1200
1201 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001202
Rich Lane7744e112013-01-11 17:23:57 -08001203_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001204FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1205 for x in range(256)])
1206
1207def hex_dump_buffer(src, length=16):
1208 """
1209 Convert src to a hex dump string and return the string
1210 @param src The source buffer
1211 @param length The number of bytes shown in each line
1212 @returns A string showing the hex dump
1213 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001214 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001215 for i in xrange(0, len(src), length):
1216 chars = src[i:i+length]
1217 hex = ' '.join(["%02x" % ord(x) for x in chars])
1218 printable = ''.join(["%s" % ((ord(x) <= 127 and
1219 FILTER[ord(x)]) or '.') for x in chars])
1220 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1221 return ''.join(result)
1222
1223def format_packet(pkt):
1224 return "Packet length %d \n%s" % (len(str(pkt)),
1225 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001226
1227def inspect_packet(pkt):
1228 """
1229 Wrapper around scapy's show() method.
1230 @returns A string showing the dissected packet.
1231 """
1232 from cStringIO import StringIO
1233 out = None
1234 backup = sys.stdout
1235 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001236 tmp = StringIO()
1237 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001238 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001239 out = tmp.getvalue()
1240 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001241 finally:
1242 sys.stdout = backup
1243 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001244
1245def nonstandard(cls):
1246 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001247 Testcase decorator that marks the test as being non-standard.
1248 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001249 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001250 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001251 return cls
1252
1253def disabled(cls):
1254 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001255 Testcase decorator that marks the test as being disabled.
1256 These tests are not automatically added to the "standard" group or
1257 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001258 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001259 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001260 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001261
1262def group(name):
1263 """
1264 Testcase decorator that adds the test to a group.
1265 """
1266 def fn(cls):
1267 if not hasattr(cls, "_groups"):
1268 cls._groups = []
1269 cls._groups.append(name)
1270 return cls
1271 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001272
1273def version(ver):
1274 """
1275 Testcase decorator that specifies which versions of OpenFlow the test
1276 supports. The default is 1.0+. This decorator may only be used once.
1277
1278 Supported syntax:
1279 1.0 -> 1.0
1280 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1281 1.0+ -> 1.0, 1.1, 1.2, 1.3
1282 """
1283 versions = parse_version(ver)
1284 def fn(cls):
1285 cls._versions = versions
1286 return cls
1287 return fn
1288
1289def parse_version(ver):
1290 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1291 if re.match("^1\.\d+$", ver):
1292 versions = set([ver])
1293 elif re.match("^(1\.\d+)\+$", ver):
1294 if not ver[:-1] in allowed_versions:
1295 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1296 versions = set()
1297 if ver != "1.1+": versions.add("1.0")
1298 if ver != "1.2+": versions.add("1.1")
1299 if ver != "1.3+": versions.add("1.2")
1300 versions.add("1.3")
1301 else:
1302 versions = set(ver.split(','))
1303
1304 for version in versions:
1305 if not version in allowed_versions:
1306 raise ValueError("invalid OpenFlow version %s" % version)
1307
1308 return versions
1309
1310assert(parse_version("1.0") == set(["1.0"]))
1311assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1312assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001313
Rich Laneae3428c2013-03-07 14:37:42 -08001314def get_stats(test, req):
1315 """
1316 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1317 """
Rich Lane609194f2013-10-21 06:17:37 -07001318 msgtype = ofp.OFPT_STATS_REPLY
1319 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001320 stats = []
1321 reply, _ = test.controller.transact(req)
1322 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001323 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001324 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001325 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001326 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001327 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001328 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001329 return stats
1330
Rich Lanebd56ed62013-07-10 15:49:44 -07001331def get_flow_stats(test, match, table_id=None,
1332 out_port=None, out_group=None,
1333 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001334 """
1335 Retrieve a list of flow stats entries.
1336 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001337
1338 if table_id == None:
1339 if ofp.OFP_VERSION <= 2:
1340 table_id = 0xff
1341 else:
1342 table_id = ofp.OFPTT_ALL
1343
Rich Lanef3bc48c2013-05-03 17:39:35 -07001344 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001345 if ofp.OFP_VERSION == 1:
1346 out_port = ofp.OFPP_NONE
1347 else:
1348 out_port = ofp.OFPP_ANY
1349
1350 if out_group == None:
1351 if ofp.OFP_VERSION > 1:
1352 out_group = ofp.OFPP_ANY
1353
Rich Lanee717c6e2013-03-12 10:25:50 -07001354 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001355 table_id=table_id,
1356 out_port=out_port)
1357 if ofp.OFP_VERSION > 1:
1358 req.out_group = out_group
1359 req.cookie = cookie
1360 req.cookie_mask = cookie_mask
1361
Rich Laneae3428c2013-03-07 14:37:42 -08001362 return get_stats(test, req)
1363
Rich Lane968b6192013-03-07 15:34:43 -08001364def get_port_stats(test, port_no):
1365 """
1366 Retrieve a list of port stats entries.
1367 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001368 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001369 return get_stats(test, req)
1370
Rich Lane6a334922013-03-07 16:14:52 -08001371def get_queue_stats(test, port_no, queue_id):
1372 """
1373 Retrieve a list of queue stats entries.
1374 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001375 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001376 return get_stats(test, req)
1377
Rich Laneae3428c2013-03-07 14:37:42 -08001378def verify_flow_stats(test, match, table_id=0xff,
Rich Lanef3bc48c2013-05-03 17:39:35 -07001379 out_port=None,
Rich Laneae3428c2013-03-07 14:37:42 -08001380 initial=[],
1381 pkts=None, bytes=None):
1382 """
1383 Verify that flow stats changed as expected.
1384
1385 Optionally takes an 'initial' list of stats entries, as returned by
1386 get_flow_stats(). If 'initial' is not given the counters are assumed to
1387 begin at 0.
1388 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001389 if out_port == None:
1390 out_port = ofp.OFPP_NONE
1391
Rich Laneae3428c2013-03-07 14:37:42 -08001392 def accumulate(stats):
1393 pkts_acc = bytes_acc = 0
1394 for stat in stats:
1395 pkts_acc += stat.packet_count
1396 bytes_acc += stat.byte_count
1397 return (pkts_acc, bytes_acc)
1398
1399 pkts_before, bytes_before = accumulate(initial)
1400
1401 # Wait 10s for counters to update
1402 pkt_diff = byte_diff = None
1403 for i in range(0, 100):
1404 stats = get_flow_stats(test, match, table_id=table_id, out_port=out_port)
1405 pkts_after, bytes_after = accumulate(stats)
1406 pkt_diff = pkts_after - pkts_before
1407 byte_diff = bytes_after - bytes_before
1408 if (pkts == None or pkt_diff >= pkts) and \
1409 (bytes == None or byte_diff >= bytes):
1410 break
Dan Talayco53724732013-03-08 23:54:02 -08001411 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001412
1413 if pkts != None:
1414 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1415
1416 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001417 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1418 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001419
Rich Lane968b6192013-03-07 15:34:43 -08001420def verify_port_stats(test, port,
1421 initial=[],
1422 tx_pkts=None, rx_pkts=None,
1423 tx_bytes=None, rx_bytes=None):
1424 """
1425 Verify that port stats changed as expected.
1426
1427 Optionally takes an 'initial' list of stats entries, as returned by
1428 get_port_stats(). If 'initial' is not given the counters are assumed to
1429 begin at 0.
1430 """
1431 def accumulate(stats):
1432 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1433 for stat in stats:
1434 tx_pkts_acc += stat.tx_packets
1435 rx_pkts_acc += stat.rx_packets
1436 tx_bytes_acc += stat.tx_bytes
1437 rx_bytes_acc += stat.rx_bytes
1438 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1439
1440 tx_pkts_before, rx_pkts_before, \
1441 tx_bytes_before, rx_bytes_before = accumulate(initial)
1442
1443 # Wait 10s for counters to update
1444 for i in range(0, 100):
1445 stats = get_port_stats(test, port)
1446 tx_pkts_after, rx_pkts_after, \
1447 tx_bytes_after, rx_bytes_after = accumulate(stats)
1448 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1449 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1450 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1451 rx_bytes_diff = rx_bytes_after - rx_bytes_before
1452 if (tx_pkts == None or tx_pkts == tx_pkts_diff) and \
1453 (rx_pkts == None or rx_pkts == rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001454 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1455 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001456 break
1457 time.sleep(0.1)
1458
1459 if (tx_pkts != None):
1460 test.assertEqual(tx_pkts,tx_pkts_diff,"Port TX packet counter is not updated correctly (expected increase of %d, got increase of %d)" % (tx_pkts, tx_pkts_diff))
1461 if (rx_pkts != None):
1462 test.assertEqual(rx_pkts,rx_pkts_diff,"Port RX packet counter is not updated correctly (expected increase of %d, got increase of %d)" % (rx_pkts, rx_pkts_diff))
1463 if (tx_bytes != None):
Rich Lane53b96812013-03-07 16:54:50 -08001464 test.assertTrue(tx_bytes_diff >= tx_bytes and tx_bytes_diff <= tx_bytes*1.1,
1465 "Port TX byte counter is not updated correctly (expected increase of %d, got increase of %d)" % (tx_bytes, tx_bytes_diff))
Rich Lane968b6192013-03-07 15:34:43 -08001466 if (rx_bytes != None):
Rich Lane53b96812013-03-07 16:54:50 -08001467 test.assertTrue(rx_bytes_diff >= rx_bytes and rx_bytes_diff <= rx_bytes*1.1,
1468 "Port RX byte counter is not updated correctly (expected increase of %d, got increase of %d)" % (rx_bytes, rx_bytes_diff))
Rich Lane968b6192013-03-07 15:34:43 -08001469
Rich Lane6a334922013-03-07 16:14:52 -08001470def verify_queue_stats(test, port_no, queue_id,
1471 initial=[],
1472 pkts=None, bytes=None):
1473 """
1474 Verify that queue stats changed as expected.
1475
1476 Optionally takes an 'initial' list of stats entries, as returned by
1477 get_queue_stats(). If 'initial' is not given the counters are assumed to
1478 begin at 0.
1479 """
1480 def accumulate(stats):
1481 pkts_acc = bytes_acc = 0
1482 for stat in stats:
1483 pkts_acc += stat.tx_packets
1484 bytes_acc += stat.tx_bytes
1485 return (pkts_acc, bytes_acc)
1486
1487 pkts_before, bytes_before = accumulate(initial)
1488
1489 # Wait 10s for counters to update
1490 pkt_diff = byte_diff = None
1491 for i in range(0, 100):
1492 stats = get_queue_stats(test, port_no, queue_id)
1493 pkts_after, bytes_after = accumulate(stats)
1494 pkt_diff = pkts_after - pkts_before
1495 byte_diff = bytes_after - bytes_before
1496 if (pkts == None or pkt_diff >= pkts) and \
1497 (bytes == None or byte_diff >= bytes):
1498 break
Dan Talayco53724732013-03-08 23:54:02 -08001499 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001500
1501 if pkts != None:
1502 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1503
1504 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001505 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1506 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001507
Rich Lane4c504f32013-06-07 17:24:14 -07001508def packet_in_match(msg, data, in_port=None, reason=None):
1509 """
1510 Check whether the packet_in message 'msg' has fields matching 'data',
1511 'in_port', and 'reason'.
1512
1513 This function handles truncated packet_in data. The 'in_port' and 'reason'
1514 parameters are optional.
1515
1516 @param msg packet_in message
1517 @param data Expected packet_in data
1518 @param in_port Expected packet_in in_port, or None
1519 @param reason Expected packet_in reason, or None
1520 """
1521
Rich Lanec0d26dd2013-07-10 12:46:03 -07001522 if ofp.OFP_VERSION <= 2:
1523 pkt_in_port = msg.in_port
1524 else:
1525 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1526 if ofp.oxm.in_port in oxms:
1527 pkt_in_port = oxms[ofp.oxm.in_port].value
1528 else:
1529 logging.warn("Missing in_port in packet-in message")
1530 pkt_in_port = None
1531
1532 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001533 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001534 return False
1535
Rich Lanec0d26dd2013-07-10 12:46:03 -07001536 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001537 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1538 return False
1539
1540 # Check that one of the packets is a prefix of the other.
1541 # The received packet may be either truncated or padded, but not both.
1542 # (Some of the padding may be truncated but that's irrelevant). We
1543 # need to check that the smaller packet is a prefix of the larger one.
1544 # Note that this check succeeds if the switch sends a zero-length
1545 # packet-in.
1546 compare_len = min(len(msg.data), len(data))
1547 if data[:compare_len] != msg.data[:compare_len]:
1548 logging.debug("Incorrect packet_in data")
1549 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1550 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1551 return False
1552
1553 return True
1554
1555def verify_packet_in(test, data, in_port, reason, controller=None):
1556 """
1557 Assert that the controller receives a packet_in message matching data 'data'
1558 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1559 itself, that's up to the test case.
1560
1561 @param test Instance of base_tests.SimpleProtocol
1562 @param pkt String to expect as the packet_in data
1563 @param in_port OpenFlow port number to expect as the packet_in in_port
1564 @param reason One of OFPR_* to expect as the packet_in reason
1565 @param controller Controller instance, defaults to test.controller
1566 @returns The received packet-in message
1567 """
1568
1569 if controller == None:
1570 controller = test.controller
1571
1572 end_time = time.time() + oftest.ofutils.default_timeout
1573
1574 while True:
1575 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1576 if not msg:
1577 # Timeout
1578 break
1579 elif packet_in_match(msg, data, in_port, reason):
1580 # Found a matching message
1581 break
1582
1583 test.assertTrue(msg is not None, 'Packet in message not received on port %d' % in_port)
1584 return msg
1585
1586def verify_no_packet_in(test, data, in_port, controller=None):
1587 """
1588 Assert that the controller does not receive a packet_in message matching
1589 data 'data' from port 'in_port'.
1590
1591 @param test Instance of base_tests.SimpleProtocol
1592 @param pkt String to expect as the packet_in data
1593 @param in_port OpenFlow port number to expect as the packet_in in_port
1594 @param controller Controller instance, defaults to test.controller
1595 """
1596
1597 if controller == None:
1598 controller = test.controller
1599
1600 # Negative test, need to wait a short amount of time before checking we
1601 # didn't receive the message.
1602 time.sleep(0.5)
1603
1604 # Check every packet_in queued in the controller
1605 while True:
1606 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1607 if msg == None:
1608 # No more queued packet_in messages
1609 break
1610 elif packet_in_match(msg, data, in_port, None):
1611 # Found a matching message
1612 break
1613
Rich Lane82c882d2013-08-09 17:13:52 -07001614 if in_port == None:
1615 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1616 else:
1617 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001618
Rich Lane045db072013-08-06 13:16:30 -07001619def openflow_ports(num=None):
1620 """
1621 Return a list of 'num' OpenFlow port numbers
1622
1623 If 'num' is None, return all available ports. Otherwise, limit the length
1624 of the result to 'num' and raise an exception if not enough ports are
1625 available.
1626 """
1627 ports = sorted(oftest.config["port_map"].keys())
1628 if num != None and len(ports) < num:
1629 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
1630 return ports[:num]
1631
Rich Lanee4b384d2013-09-13 14:33:40 -07001632def verify_packet(test, pkt, ofport):
1633 """
1634 Check that an expected packet is received
1635 """
1636 logging.debug("Checking for pkt on port %r", ofport)
1637 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
1638 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
1639
1640def verify_no_packet(test, pkt, ofport):
1641 """
1642 Check that a particular packet is not received
1643 """
1644 logging.debug("Negative check for pkt on port %r", ofport)
1645 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt), timeout=0.01)
1646 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
1647
1648def verify_no_other_packets(test):
1649 """
1650 Check that no unexpected packets are received
1651
1652 This is a no-op if the --relax option is in effect.
1653 """
1654 if oftest.config["relax"]:
1655 return
1656 logging.debug("Checking for unexpected packets on all ports")
1657 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=0.01)
1658 if rcv_pkt != None:
1659 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
1660 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
1661
1662def verify_packets(test, pkt, ofports):
1663 """
1664 Check that a packet is received on certain ports
1665
1666 Also verifies that the packet is not received on any other ports, and that no
1667 other packets are received (unless --relax is in effect).
1668
1669 This covers the common and simplest cases for checking dataplane outputs.
1670 For more complex usage, like multiple different packets being output, or
1671 multiple packets on the same port, use the primitive verify_packet,
1672 verify_no_packet, and verify_no_other_packets functions directly.
1673 """
1674 pkt = str(pkt)
1675 for ofport in openflow_ports():
1676 if ofport in ofports:
1677 verify_packet(test, pkt, ofport)
1678 else:
1679 verify_no_packet(test, pkt, ofport)
1680 verify_no_other_packets(test)
1681
Rich Lane12d04592013-10-10 17:21:07 -07001682def verify_no_errors(ctrl):
1683 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
1684 if error:
1685 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07001686
Rich Lane7744e112013-01-11 17:23:57 -08001687__all__ = list(set(locals()) - _import_blacklist)