blob: cd501ac9c8e28a3bc408e511f90d3cfdeb605c7e [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
Flavio Castro1c9b1252016-02-04 18:42:58 -05007from Queue import Queue
8
Rich Lanea68176f2013-08-09 17:41:05 -07009import packet as scapy
Dan Talayco41eae8b2010-03-10 13:57:06 -080010
Rich Lanecd97d3d2013-01-07 18:50:06 -080011import oftest
12import oftest.controller
13import oftest.dataplane
Rich Lanef6883512013-03-11 17:00:09 -070014import oftest.parse
Rich Lane4c504f32013-06-07 17:24:14 -070015import oftest.ofutils
Rich Lanee717c6e2013-03-12 10:25:50 -070016import ofp
Dan Talaycoc901f4d2010-03-07 21:55:45 -080017
Dan Talaycoba3745c2010-07-21 21:51:08 -070018global skipped_test_count
19skipped_test_count = 0
20
Rich Lane7744e112013-01-11 17:23:57 -080021_import_blacklist = set(locals().keys())
22
Dan Talayco551befa2010-07-15 17:05:32 -070023# Some useful defines
24IP_ETHERTYPE = 0x800
25TCP_PROTOCOL = 0x6
26UDP_PROTOCOL = 0x11
27
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000028MINSIZE = 0
29
Tony van der Peet80c5b202013-11-20 11:47:48 +130030def delete_all_flows(ctrl, send_barrier=True):
Dan Talayco41eae8b2010-03-10 13:57:06 -080031 """
32 Delete all flows on the switch
33 @param ctrl The controller object for the test
Tony van der Peet80c5b202013-11-20 11:47:48 +130034 @param send_barrier Whether or not to send a barrier message
Dan Talayco41eae8b2010-03-10 13:57:06 -080035 """
36
Rich Lane9a003812012-10-04 17:17:59 -070037 logging.info("Deleting all flows")
Rich Lanee717c6e2013-03-12 10:25:50 -070038 msg = ofp.message.flow_delete()
Rich Lanec717f442013-06-13 15:49:09 -070039 if ofp.OFP_VERSION in [1, 2]:
40 msg.match.wildcards = ofp.OFPFW_ALL
41 msg.out_port = ofp.OFPP_NONE
42 msg.buffer_id = 0xffffffff
43 elif ofp.OFP_VERSION >= 3:
44 msg.table_id = ofp.OFPTT_ALL
45 msg.buffer_id = ofp.OFP_NO_BUFFER
46 msg.out_port = ofp.OFPP_ANY
47 msg.out_group = ofp.OFPG_ANY
Rich Lane5c3151c2013-01-03 17:15:41 -080048 ctrl.message_send(msg)
Tony van der Peet80c5b202013-11-20 11:47:48 +130049 if send_barrier:
50 do_barrier(ctrl)
Rich Lane32bf9482013-01-03 17:26:30 -080051 return 0 # for backwards compatibility
Dan Talayco41eae8b2010-03-10 13:57:06 -080052
Rich Lane5f3c9b22013-10-10 17:20:30 -070053def delete_all_groups(ctrl):
54 """
55 Delete all groups on the switch
56 @param ctrl The controller object for the test
57 """
58
59 logging.info("Deleting all groups")
Rich Lane5de5e632013-11-24 10:15:25 -080060 msg = ofp.message.group_delete(group_id=ofp.OFPG_ALL)
Rich Lane5f3c9b22013-10-10 17:20:30 -070061 ctrl.message_send(msg)
62 do_barrier(ctrl)
63
Flavio Castro1c9b1252016-02-04 18:42:58 -050064def delete_groups(ctrl, group_queue=Queue()):
65 """
66 Delete all groups on list
67 @param ctrl The controller object for the test
68 :param group_queue:
69 """
70 logging.info("Deleting groups")
71 while (not group_queue.empty()):
Pier1e4e98e2016-10-26 14:36:05 -070072 msg = ofp.message.group_delete(group_id=group_queue.get())
Flavio Castro1c9b1252016-02-04 18:42:58 -050073 ctrl.message_send(msg)
74 do_barrier(ctrl)
75
Ed Swierk99a74de2012-08-22 06:40:54 -070076def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070077 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070078 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -070079 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
80 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -070081 else:
82 return 0
83
macauley_cheng0a0a7f62015-11-06 11:36:50 +080084def simple_packet(content='00 00 00 11 33 55 00 00 00 11 22 33 81 00 00 03 '
85 '08 00 45 00 00 2e 04 d2 00 00 7f 00 b2 47 c0 a8 '
86 '01 64 c0 a8 02 02 00 00 00 00 00 00 00 00 00 00 '
87 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'):
macauley_cheng739f54b2015-11-09 13:52:59 +080088
89 pkt = ''.join(content.split(" ")).decode('hex')
macauley_chengc80249d2015-11-09 14:11:18 +080090 pkt = scapy.Ether(pkt)
macauley_cheng739f54b2015-11-09 13:52:59 +080091 if len(pkt) < 64:
92 pkt = pkt/("D" * (64 - len(pkt)))
macauley_chengc80249d2015-11-09 14:11:18 +080093 #scapy.hexdump(pkt)
macauley_cheng0a0a7f62015-11-06 11:36:50 +080094 return pkt
95
Dan Talayco41eae8b2010-03-10 13:57:06 -080096def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -070097 eth_dst='00:01:02:03:04:05',
98 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070099 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700100 vlan_vid=0,
101 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700102 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800103 ip_src='192.168.0.1',
104 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700105 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800106 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800107 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700108 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700109 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700110 ip_ihl=None,
111 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800112 ):
113 """
114 Return a simple dataplane TCP packet
115
116 Supports a few parameters:
117 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700118 @param eth_dst Destinatino MAC
119 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700120 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700121 @param vlan_vid VLAN ID
122 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800123 @param ip_src IP source
124 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700125 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800126 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800127 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700128 @param tcp_sport TCP source port
129 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800130
131 Generates a simple TCP request. Users
132 shouldn't assume anything about this packet other than that
133 it is a valid ethernet/IP/TCP frame.
134 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000135
136 if MINSIZE > pktlen:
137 pktlen = MINSIZE
138
Dan Talayco551befa2010-07-15 17:05:32 -0700139 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800140 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700141 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
142 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800143 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700144 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700145 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700146 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700147 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800148 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700149 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700150 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700151 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800152 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700153 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700154
Dan Talayco41eae8b2010-03-10 13:57:06 -0800155 pkt = pkt/("D" * (pktlen - len(pkt)))
156
157 return pkt
158
Rich Lane86aceb02013-07-17 18:45:38 -0700159def simple_tcpv6_packet(pktlen=100,
160 eth_dst='00:01:02:03:04:05',
161 eth_src='00:06:07:08:09:0a',
162 dl_vlan_enable=False,
163 vlan_vid=0,
164 vlan_pcp=0,
165 ipv6_src='2001:db8:85a3::8a2e:370:7334',
166 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
167 ipv6_tc=0,
168 ipv6_hlim=64,
169 ipv6_fl=0,
170 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700171 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700172 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700173 """
174 Return a simple IPv6/TCP packet
175
176 Supports a few parameters:
177 @param len Length of packet in bytes w/o CRC
178 @param eth_dst Destination MAC
179 @param eth_src Source MAC
180 @param dl_vlan_enable True if the packet is with vlan, False otherwise
181 @param vlan_vid VLAN ID
182 @param vlan_pcp VLAN priority
183 @param ipv6_src IPv6 source
184 @param ipv6_dst IPv6 destination
185 @param ipv6_tc IPv6 traffic class
186 @param ipv6_ttl IPv6 hop limit
187 @param ipv6_fl IPv6 flow label
188 @param tcp_dport TCP destination port
189 @param tcp_sport TCP source port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700190 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700191
192 Generates a simple TCP request. Users shouldn't assume anything about this
193 packet other than that it is a valid ethernet/IPv6/TCP frame.
194 """
195
196 if MINSIZE > pktlen:
197 pktlen = MINSIZE
198
199 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
200 if dl_vlan_enable or vlan_vid or vlan_pcp:
201 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
202 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700203 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700204 pkt /= ("D" * (pktlen - len(pkt)))
205
206 return pkt
207
Rich Lane6ee7bea2012-10-26 16:19:29 -0700208def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700209 eth_dst='00:01:02:03:04:05',
210 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700211 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700212 vlan_vid=0,
213 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700214 dl_vlan_cfi=0,
215 ip_src='192.168.0.1',
216 ip_dst='192.168.0.2',
217 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800218 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700219 udp_sport=1234,
220 udp_dport=80,
221 ip_ihl=None,
222 ip_options=False
223 ):
224 """
225 Return a simple dataplane UDP packet
226
227 Supports a few parameters:
228 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700229 @param eth_dst Destination MAC
230 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700231 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700232 @param vlan_vid VLAN ID
233 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700234 @param ip_src IP source
235 @param ip_dst IP destination
236 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800237 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700238 @param udp_dport UDP destination port
239 @param udp_sport UDP source port
240
241 Generates a simple UDP packet. Users shouldn't assume anything about
242 this packet other than that it is a valid ethernet/IP/UDP frame.
243 """
244
245 if MINSIZE > pktlen:
246 pktlen = MINSIZE
247
248 # Note Dot1Q.id is really CFI
249 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700250 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
251 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800252 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700253 scapy.UDP(sport=udp_sport, dport=udp_dport)
254 else:
255 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700256 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800257 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700258 scapy.UDP(sport=udp_sport, dport=udp_dport)
259 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700260 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800261 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 -0700262 scapy.UDP(sport=udp_sport, dport=udp_dport)
263
264 pkt = pkt/("D" * (pktlen - len(pkt)))
265
266 return pkt
267
macauley_chengb0ec33d2015-09-04 11:32:44 +0800268
269def simple_tcp_packet_two_vlan(pktlen=100,
270 eth_dst='00:01:02:03:04:05',
271 eth_src='00:06:07:08:09:0a',
272 out_dl_vlan_enable=False,
273 in_dl_vlan_enable=False,
274 out_vlan_vid=0,
275 out_vlan_pcp=0,
276 out_dl_vlan_cfi=0,
277 in_vlan_vid=0,
278 in_vlan_pcp=0,
279 in_dl_vlan_cfi=0,
280 ip_src='192.168.0.1',
281 ip_dst='192.168.0.2',
282 ip_tos=0,
283 ip_ttl=64,
284 tcp_sport=1234,
285 tcp_dport=80,
286 tcp_flags="S",
287 ip_ihl=None,
288 ip_options=False
289 ):
290 """
291 Return a simple dataplane TCP packet
292
293 Supports a few parameters:
294 @param len Length of packet in bytes w/o CRC
295 @param eth_dst Destinatino MAC
296 @param eth_src Source MAC
297 @param dl_vlan_enable True if the packet is with vlan, False otherwise
298 @param vlan_vid VLAN ID
299 @param vlan_pcp VLAN priority
300 @param ip_src IP source
301 @param ip_dst IP destination
302 @param ip_tos IP ToS
303 @param ip_ttl IP TTL
304 @param tcp_dport TCP destination port
305 @param tcp_sport TCP source port
306 @param tcp_flags TCP Control flags
307
308 Generates a simple TCP request. Users
309 shouldn't assume anything about this packet other than that
310 it is a valid ethernet/IP/TCP frame.
311 """
312
313 if MINSIZE > pktlen:
314 pktlen = MINSIZE
315
316 # Note Dot1Q.id is really CFI
317 if (out_dl_vlan_enable and in_dl_vlan_enable):
318 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
319 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
320
321 if in_dl_vlan_enable:
322 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
323
324 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
325 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
326 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
327 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
328 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
329 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
330 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
331 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
332 assert(0) #shall not have this caes
333 else:
334 if not ip_options:
335 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
336 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
337 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
338 else:
339 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
340 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
341 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
342
343 pkt = pkt/("D" * (pktlen - len(pkt)))
344
345 return pkt
346
macauley17cd60d2015-07-27 17:41:18 +0800347def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
348 eth_src='00:06:07:08:09:0a',
349 dl_vlan_enable=False,
350 vlan_vid=0,
351 vlan_pcp=0,
352 dl_vlan_cfi=0,
353 ip_src='192.168.0.1',
354 ip_dst='192.168.0.2',
355 ip_tos=0,
356 ip_ttl=64,
357 udp_sport=1234,
358 udp_dport=4789,
359 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800360 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800361 ip_ihl=None,
362 ip_options=False
363 ):
364 """
365 Return a simple dataplane UDP packet
366
367 Supports a few parameters:
368 @param len Length of packet in bytes w/o CRC
369 @param eth_dst Destination MAC
370 @param eth_src Source MAC
371 @param dl_vlan_enable True if the packet is with vlan, False otherwise
372 @param vlan_vid VLAN ID
373 @param vlan_pcp VLAN priority
374 @param ip_src IP source
375 @param ip_dst IP destination
376 @param ip_tos IP ToS
377 @param ip_ttl IP TTL
378 @param udp_dport UDP destination port
379 @param udp_sport UDP source port
380 @param inner_pyload inner pacekt content
381 Generates a simple UDP packet. Users shouldn't assume anything about
382 this packet other than that it is a valid ethernet/IP/UDP frame.
383 """
384
385 # Note Dot1Q.id is really CFI
386 if (dl_vlan_enable):
387 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
388 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
389 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
390 scapy.UDP(sport=udp_sport, dport=udp_dport)
391 else:
392 if not ip_options:
393 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
394 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
395 scapy.UDP(sport=udp_sport, dport=udp_dport)
396 else:
397 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
398 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
399 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800400
macauley17cd60d2015-07-27 17:41:18 +0800401 #add vxlan header
402 pkt = pkt/scapy.VXLAN(vni=vnid)
403 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800404 if inner_payload!=None:
405 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800406
407 return pkt
408
Flavio Castro72a45d52015-12-02 16:37:05 -0500409def mpls_packet(pktlen=100,
410 eth_dst='00:01:02:03:04:05',
411 eth_src='00:06:07:08:09:0a',
412 dl_vlan_enable=False,
413 vlan_vid=0,
414 vlan_pcp=0,
415 dl_vlan_cfi=0,
416 ip_src='192.168.0.1',
417 ip_dst='192.168.0.2',
418 ip_tos=0,
419 ip_ttl=64,
420 tcp_sport=1234,
421 tcp_dport=80,
422 tcp_flags="S",
423 ip_ihl=None,
424 ip_options=False,
425 label=None,
Flavio Castro167f5bd2015-12-02 19:33:53 -0500426 inner_payload=True
Flavio Castro72a45d52015-12-02 16:37:05 -0500427 ):
428 if MINSIZE > pktlen:
429 pktlen = MINSIZE
430
431 # Note Dot1Q.id is really CFI
432 if (dl_vlan_enable):
433 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
434 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
435 else:
436 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
437
438 #add MPLS header
439 for i in range(len(label)):
440 l,c,s,t=label[i]
441 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
442
443 #add innder payload
444 if inner_payload!=None:
445 pkt=pkt / \
446 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
447 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Flavio Castro167f5bd2015-12-02 19:33:53 -0500448
449 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500450
451 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800452
Pier23784aa2016-09-19 20:08:21 -0700453def pw_packet(pktlen=100,
454 out_eth_dst='00:01:02:03:04:05',
455 out_eth_src='00:06:07:08:09:0a',
456 label=None,
457 cw=None,
458 in_eth_dst='00:01:02:03:04:05',
459 in_eth_src='00:06:07:08:09:0a',
460 out_dl_vlan_enable=False,
461 in_dl_vlan_enable=False,
462 out_vlan_vid=0,
463 out_vlan_pcp=0,
464 out_dl_vlan_cfi=0,
465 in_vlan_vid=0,
466 in_vlan_pcp=0,
467 in_dl_vlan_cfi=0,
468 ip_src='192.168.0.1',
469 ip_dst='192.168.0.2',
470 ip_tos=0,
471 ip_ttl=64,
472 tcp_sport=1234,
473 tcp_dport=80,
474 tcp_flags="S",
475 ip_ihl=None,
476 ip_options=False
477 ):
478 """
479 Return a simple dataplane TCP packet encapsulated
480 in a pw packet
481 """
482
483 # Add the outer ethernet header
484 if MINSIZE > pktlen:
485 pktlen = MINSIZE
486
487 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
488
489 #add MPLS header
490 for i in range(len(label)):
491 l,c,s,t=label[i]
492 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
493
494 #add the PW CW
495 l,c,s,t=cw
496 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
497
498 # Note Dot1Q.id is really CFI
499 if (out_dl_vlan_enable and in_dl_vlan_enable):
500
501 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
502 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
503
504 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
505
506 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
507 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
508
509 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
510
511 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
512 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
513 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
514 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
515
516 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
517
518 assert(0) #shall not have this caes
519
520 else:
521 if not ip_options:
522 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
523 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
524 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
525 else:
526 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
527 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
528 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
529
530 pkt = pkt/("D" * (pktlen - len(pkt)))
531
532 return pkt
533
Pier1e4e98e2016-10-26 14:36:05 -0700534def mplsv6_packet(pktlen=100,
535 eth_dst='00:01:02:03:04:05',
536 eth_src='00:06:07:08:09:0a',
537 dl_vlan_enable=False,
538 vlan_vid=0,
539 vlan_pcp=0,
540 dl_vlan_cfi=0,
541 ipv6_src='2001:db8:85a3::8a2e:370:7334',
542 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
543 ipv6_tc=0,
544 ipv6_hlim=64,
545 ipv6_fl=0,
546 tcp_sport=1234,
547 tcp_dport=80,
548 tcp_flags="S",
549 label=None,
550 inner_payload=True
551 ):
552 if MINSIZE > pktlen:
553 pktlen = MINSIZE
554
555 # Note Dot1Q.id is really CFI
556 if (dl_vlan_enable):
557 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
558 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
559 else:
560 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
561
562 #add MPLS header
563 for i in range(len(label)):
564 l,c,s,t=label[i]
565 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
566
567 #add innder payload
568 if inner_payload!=None:
569 pkt=pkt / \
570 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
571 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
572
573 pkt = pkt/("D" * (pktlen - len(pkt)))
574
575 return pkt
576
macauley_cheng45833df2015-08-31 15:19:07 +0800577def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
578 eth_src='00:06:07:08:09:0a',
579 dl_vlan_enable=False,
580 vlan_vid=0,
581 vlan_pcp=0,
582 dl_vlan_cfi=0,
583 label=None,
584 inner_payload=None
585 ):
586 """
587 Return a simple dataplane MPLS packet
588
589 Supports a few parameters:
590 @param len Length of packet in bytes w/o CRC
591 @param eth_dst Destination MAC
592 @param eth_src Source MAC
593 @param dl_vlan_enable True if the packet is with vlan, False otherwise
594 @param vlan_vid VLAN ID
595 @param vlan_pcp VLAN priority
596 @param inner_pyload inner pacekt content
597 Generates a simple MPLS packet. Users shouldn't assume anything about
598 this packet other than that it is a valid ethernet/IP/UDP frame.
599 """
600
601 # Note Dot1Q.id is really CFI
602 if (dl_vlan_enable):
603 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
604 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
605 else:
606 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
607
608 #add MPLS header
609 for i in range(len(label)):
610 l,c,s,t=label[i]
611 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
612
613 #add innder payload
614 if inner_payload!=None:
615 pkt=pkt/inner_payload
616
617 return pkt
618
Rich Lane86aceb02013-07-17 18:45:38 -0700619def simple_udpv6_packet(pktlen=100,
620 eth_dst='00:01:02:03:04:05',
621 eth_src='00:06:07:08:09:0a',
622 dl_vlan_enable=False,
623 vlan_vid=0,
624 vlan_pcp=0,
625 ipv6_src='2001:db8:85a3::8a2e:370:7334',
626 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
627 ipv6_tc=0,
628 ipv6_hlim=64,
629 ipv6_fl=0,
630 udp_sport=1234,
631 udp_dport=80):
632 """
633 Return a simple IPv6/UDP packet
634
635 Supports a few parameters:
636 @param len Length of packet in bytes w/o CRC
637 @param eth_dst Destination MAC
638 @param eth_src Source MAC
639 @param dl_vlan_enable True if the packet is with vlan, False otherwise
640 @param vlan_vid VLAN ID
641 @param vlan_pcp VLAN priority
642 @param ipv6_src IPv6 source
643 @param ipv6_dst IPv6 destination
644 @param ipv6_tc IPv6 traffic class
645 @param ipv6_ttl IPv6 hop limit
646 @param ipv6_fl IPv6 flow label
647 @param udp_dport UDP destination port
648 @param udp_sport UDP source port
649
650 Generates a simple UDP request. Users shouldn't assume anything about this
651 packet other than that it is a valid ethernet/IPv6/UDP frame.
652 """
653
654 if MINSIZE > pktlen:
655 pktlen = MINSIZE
656
657 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
658 if dl_vlan_enable or vlan_vid or vlan_pcp:
659 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
660 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
661 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
662 pkt /= ("D" * (pktlen - len(pkt)))
663
664 return pkt
665
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700666def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700667 eth_dst='00:01:02:03:04:05',
668 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700669 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700670 vlan_vid=0,
671 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700672 ip_src='192.168.0.1',
673 ip_dst='192.168.0.2',
674 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800675 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600676 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700677 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600678 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600679 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700680 """
681 Return a simple ICMP packet
682
683 Supports a few parameters:
684 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700685 @param eth_dst Destinatino MAC
686 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700687 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700688 @param vlan_vid VLAN ID
689 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700690 @param ip_src IP source
691 @param ip_dst IP destination
692 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800693 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600694 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700695 @param icmp_type ICMP type
696 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600697 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700698
699 Generates a simple ICMP ECHO REQUEST. Users
700 shouldn't assume anything about this packet other than that
701 it is a valid ethernet/ICMP frame.
702 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000703
704 if MINSIZE > pktlen:
705 pktlen = MINSIZE
706
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700707 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700708 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
709 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600710 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600711 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700712 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700713 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600714 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600715 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700716
717 pkt = pkt/("0" * (pktlen - len(pkt)))
718
719 return pkt
720
Rich Lane86aceb02013-07-17 18:45:38 -0700721def simple_icmpv6_packet(pktlen=100,
722 eth_dst='00:01:02:03:04:05',
723 eth_src='00:06:07:08:09:0a',
724 dl_vlan_enable=False,
725 vlan_vid=0,
726 vlan_pcp=0,
727 ipv6_src='2001:db8:85a3::8a2e:370:7334',
728 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
729 ipv6_tc=0,
730 ipv6_hlim=64,
731 ipv6_fl=0,
732 icmp_type=8,
733 icmp_code=0):
734 """
735 Return a simple ICMPv6 packet
736
737 Supports a few parameters:
738 @param len Length of packet in bytes w/o CRC
739 @param eth_dst Destination MAC
740 @param eth_src Source MAC
741 @param dl_vlan_enable True if the packet is with vlan, False otherwise
742 @param vlan_vid VLAN ID
743 @param vlan_pcp VLAN priority
744 @param ipv6_src IPv6 source
745 @param ipv6_dst IPv6 destination
746 @param ipv6_tc IPv6 traffic class
747 @param ipv6_ttl IPv6 hop limit
748 @param ipv6_fl IPv6 flow label
749 @param icmp_type ICMP type
750 @param icmp_code ICMP code
751
752 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
753 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
754 """
755
756 if MINSIZE > pktlen:
757 pktlen = MINSIZE
758
759 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
760 if dl_vlan_enable or vlan_vid or vlan_pcp:
761 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
762 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
763 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
764 pkt /= ("D" * (pktlen - len(pkt)))
765
766 return pkt
767
Shudong Zhouc7562b12013-02-06 01:12:18 -0800768def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700769 eth_dst='ff:ff:ff:ff:ff:ff',
770 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800771 vlan_vid=0,
772 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800773 arp_op=1,
774 ip_snd='192.168.0.1',
775 ip_tgt='192.168.0.2',
776 hw_snd='00:06:07:08:09:0a',
777 hw_tgt='00:00:00:00:00:00',
778 ):
779 """
780 Return a simple ARP packet
781
782 Supports a few parameters:
783 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700784 @param eth_dst Destinatino MAC
785 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800786 @param arp_op Operation (1=request, 2=reply)
787 @param ip_snd Sender IP
788 @param ip_tgt Target IP
789 @param hw_snd Sender hardware address
790 @param hw_tgt Target hardware address
791
792 Generates a simple ARP REQUEST. Users
793 shouldn't assume anything about this packet other than that
794 it is a valid ethernet/ARP frame.
795 """
796
797 if MINSIZE > pktlen:
798 pktlen = MINSIZE
799
Rich Lanee01611f2014-01-15 14:55:11 -0800800 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
801 if vlan_vid or vlan_pcp:
802 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
803 pkt /= scapy.ARP(hwsrc=hw_snd, hwdst=hw_tgt, pdst=ip_tgt, psrc=ip_snd, op=arp_op)
Shudong Zhouc7562b12013-02-06 01:12:18 -0800804
Rich Laned459ce52014-01-24 12:09:54 -0800805 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800806
807 return pkt
808
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700809def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800810 eth_dst='00:01:02:03:04:05',
811 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700812 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000813
814 if MINSIZE > pktlen:
815 pktlen = MINSIZE
816
Rich Laned0478ff2013-03-11 12:46:58 -0700817 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700818
819 pkt = pkt/("0" * (pktlen - len(pkt)))
820
821 return pkt
822
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800823def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700824 eth_dst='00:01:02:03:04:05',
825 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800826 dl_vlan_outer=20,
827 dl_vlan_pcp_outer=0,
828 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700829 vlan_vid=10,
830 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800831 dl_vlan_cfi=0,
832 ip_src='192.168.0.1',
833 ip_dst='192.168.0.2',
834 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800835 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800836 tcp_sport=1234,
837 tcp_dport=80,
838 ip_ihl=None,
839 ip_options=False
840 ):
841 """
842 Return a doubly tagged dataplane TCP packet
843
844 Supports a few parameters:
845 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700846 @param eth_dst Destinatino MAC
847 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800848 @param dl_vlan_outer Outer VLAN ID
849 @param dl_vlan_pcp_outer Outer VLAN priority
850 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700851 @param vlan_vid Inner VLAN ID
852 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800853 @param dl_vlan_cfi VLAN cfi bit
854 @param ip_src IP source
855 @param ip_dst IP destination
856 @param ip_tos IP ToS
857 @param tcp_dport TCP destination port
858 @param ip_sport TCP source port
859
860 Generates a TCP request. Users
861 shouldn't assume anything about this packet other than that
862 it is a valid ethernet/IP/TCP frame.
863 """
864
865 if MINSIZE > pktlen:
866 pktlen = MINSIZE
867
868 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700869 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800870 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700871 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800872 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800873 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
874
875 pkt = pkt/("D" * (pktlen - len(pkt)))
876
877 return pkt
878
Shudong Zhoub7f12462012-11-20 13:01:12 -0800879def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700880 """
881 Do a barrier command
882 Return 0 on success, -1 on error
883 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700884 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800885 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800886 if resp is None:
887 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700888 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800889 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700890
Rich Lane9a003812012-10-04 17:17:59 -0700891def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700892 """
893 Get a port's configuration
894
895 Gets the switch feature configuration and grabs one port's
896 configuration
897
898 @returns (hwaddr, config, advert) The hwaddress, configuration and
899 advertised values
900 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700901
902 if ofp.OFP_VERSION <= 3:
903 request = ofp.message.features_request()
904 reply, _ = controller.transact(request)
905 if reply is None:
906 logging.warn("Get feature request failed")
907 return None, None, None
908 logging.debug(reply.show())
909 ports = reply.ports
910 else:
911 request = ofp.message.port_desc_stats_request()
912 # TODO do multipart correctly
913 reply, _ = controller.transact(request)
914 if reply is None:
915 logging.warn("Port desc stats request failed")
916 return None, None, None
917 logging.debug(reply.show())
918 ports = reply.entries
919
920 for port in ports:
921 if port.port_no == port_no:
922 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700923
Rich Lane9a003812012-10-04 17:17:59 -0700924 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700925 return None, None, None
926
Rich Lane9a003812012-10-04 17:17:59 -0700927def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700928 """
929 Set the port configuration according the given parameters
930
931 Gets the switch feature configuration and updates one port's
932 configuration value according to config and mask
933 """
Rich Lane9a003812012-10-04 17:17:59 -0700934 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700935
936 hw_addr, _, _ = port_config_get(controller, port_no)
937
Rich Lanee717c6e2013-03-12 10:25:50 -0700938 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700939 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700940 if hw_addr != None:
941 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700942 mod.config = config
943 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700944 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800945 controller.message_send(mod)
946 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700947
Rich Lane2014f9b2012-10-05 15:29:40 -0700948def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700949 """
950 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700951 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700952 @param pkt Expected packet; may be None if yes_ports is empty
953 @param yes_ports Set or list of ports that should recieve packet
954 @param no_ports Set or list of ports that should not receive packet
955 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700956
957 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700958 """
Rich Lane91765672012-12-06 16:33:04 -0800959
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700960 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800961 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700962 exp_pkt_arg = pkt
963
Dan Talayco92c99122010-06-03 13:53:18 -0700964 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700965 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700966 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800967 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700968 assert_if.assertTrue(rcv_pkt is not None,
969 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800970 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800971 logging.debug("Expected %s" % format_packet(pkt))
972 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800973 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800974 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700975 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700976 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700977 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700978 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700979 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700980 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800981 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700982 assert_if.assertTrue(rcv_pkt is None,
983 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700984
985
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700986def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700987 """
988 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700989 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700990
991 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700992
993 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700994 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700995 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800996 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700997 exp_pkt_arg = exp_pkt
998
Dan Talaycof6e76c02012-03-23 10:56:12 -0700999 if type(egr_ports) == type([]):
1000 egr_port_list = egr_ports
1001 else:
1002 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001003
Dan Talaycof6e76c02012-03-23 10:56:12 -07001004 # Expect a packet from each port on egr port list
1005 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001006 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001007 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001008 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001009 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001010 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001011
Dan Talaycof6e76c02012-03-23 10:56:12 -07001012 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -07001013 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001014 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001015
Dan Talaycof6e76c02012-03-23 10:56:12 -07001016 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001017 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -07001018 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001019 str(rcv_port))
1020
1021 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001022 logging.error("ERROR: Packet match failed.")
1023 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001024 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001025 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001026 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001027 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1028 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001029 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001030 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001031
Dan Talayco551befa2010-07-15 17:05:32 -07001032def match_verify(parent, req_match, res_match):
1033 """
1034 Verify flow matches agree; if they disagree, report where
1035
1036 parent must implement assertEqual
1037 Use str() to ensure content is compared and not pointers
1038 """
1039
1040 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1041 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1042 " != " + hex(res_match.wildcards))
1043 parent.assertEqual(req_match.in_port, res_match.in_port,
1044 'Match failed: in_port: ' + str(req_match.in_port) +
1045 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001046 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1047 'Match failed: eth_src: ' + str(req_match.eth_src) +
1048 " != " + str(res_match.eth_src))
1049 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1050 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1051 " != " + str(res_match.eth_dst))
1052 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1053 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1054 " != " + str(res_match.vlan_vid))
1055 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
1056 'Match failed: vlan_pcp: ' +
1057 str(req_match.vlan_pcp) + " != " +
1058 str(res_match.vlan_pcp))
1059 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1060 'Match failed: eth_type: ' + str(req_match.eth_type) +
1061 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001062
Rich Lanee717c6e2013-03-12 10:25:50 -07001063 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001064 and (req_match.eth_type == IP_ETHERTYPE)):
1065 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1066 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1067 " != " + str(res_match.ip_dscp))
1068 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1069 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1070 " != " + str(res_match.ip_proto))
1071 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1072 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1073 " != " + str(res_match.ipv4_src))
1074 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1075 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1076 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001077
Rich Lanee717c6e2013-03-12 10:25:50 -07001078 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001079 and ((req_match.ip_proto == TCP_PROTOCOL)
1080 or (req_match.ip_proto == UDP_PROTOCOL))):
1081 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
1082 'Match failed: tcp_src: ' +
1083 str(req_match.tcp_src) +
1084 " != " + str(res_match.tcp_src))
1085 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
1086 'Match failed: tcp_dst: ' +
1087 str(req_match.tcp_dst) +
1088 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001089
Ed Swierk99a74de2012-08-22 06:40:54 -07001090def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001091 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001092 if ofp.OFP_VERSION in [1, 2]:
1093 match.wildcards |= required_wildcards(parent)
1094 else:
1095 # TODO remove incompatible OXM entries
1096 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001097 return match
1098
1099def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001100 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001101 """
1102 Create a flow message
1103
1104 Match on packet with given wildcards.
1105 See flow_match_test for other parameter descriptoins
1106 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001107 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001108 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001109 """
Rich Lanef6883512013-03-11 17:00:09 -07001110 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001111 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001112 if wildcards is None:
1113 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001114 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001115 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001116 match.wildcards = wildcards
1117 match.in_port = ing_port
1118
Dan Talaycof6e76c02012-03-23 10:56:12 -07001119 if type(egr_ports) == type([]):
1120 egr_port_list = egr_ports
1121 else:
1122 egr_port_list = [egr_ports]
1123
Rich Lanee717c6e2013-03-12 10:25:50 -07001124 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001125 request.match = match
1126 request.buffer_id = 0xffffffff
1127 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001128 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001129 request.hard_timeout = 1
1130
Rich Lane400fb9b2013-10-10 17:20:54 -07001131 if ofp.OFP_VERSION == 1:
1132 actions = request.actions
1133 else:
1134 actions = []
1135 request.instructions.append(ofp.instruction.apply_actions(actions))
1136
Dan Talayco551befa2010-07-15 17:05:32 -07001137 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001138 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001139
1140 # Set up output/enqueue action if directed
1141 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001142 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001143 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001144 for egr_port in egr_port_list:
1145 act.port = egr_port
1146 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001147 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001148 elif egr_ports is not None:
1149 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001150 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001151 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001152 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001153
Rich Lane9a003812012-10-04 17:17:59 -07001154 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001155
1156 return request
1157
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001158def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001159 """
1160 Install a flow mod message in the switch
1161
1162 @param parent Must implement controller, assertEqual, assertTrue
1163 @param request The request, all set to go
1164 @param clear_table If true, clear the flow table before installing
1165 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001166
Rich Lane2014f9b2012-10-05 15:29:40 -07001167 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001168 if(clear_table_override != None):
1169 clear_table = clear_table_override
1170
1171 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001172 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001173 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001174
Rich Lane9a003812012-10-04 17:17:59 -07001175 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001176 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001177
Rich Lane3a261d52013-01-03 17:45:08 -08001178 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001179
Ed Swierk99a74de2012-08-22 06:40:54 -07001180def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001181 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001182 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001183 """
1184 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001185 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001186
1187 Run test with packet through switch from ing_port to egr_port
1188 See flow_match_test for parameter descriptions
1189 """
1190
Ed Swierk99a74de2012-08-22 06:40:54 -07001191 if wildcards is None:
1192 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001193 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001194 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001195 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001196 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001197 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001198 if exp_pkt is None:
1199 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001200
1201 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001202 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001203 action_list=action_list)
1204
1205 flow_msg_install(parent, request)
1206
Rich Lane9a003812012-10-04 17:17:59 -07001207 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001208 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001209 parent.dataplane.send(ing_port, str(pkt))
1210
Rich Lane8f45e2d2013-10-01 16:06:54 -07001211 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001212 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001213
Rich Lane89725bb2012-12-03 16:23:27 -08001214def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001215 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001216 action_list=None):
1217 """
1218 Packet-out test on single TCP packet
1219 @param egr_ports A single port or list of ports
1220
1221 Run test sending packet-out to egr_ports. The goal is to test the actions
1222 taken on the packet, not the matching which is of course irrelevant.
1223 See flow_match_test for parameter descriptions
1224 """
1225
1226 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001227 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001228 if exp_pkt is None:
1229 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001230
Rich Lanee717c6e2013-03-12 10:25:50 -07001231 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001232 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001233 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001234 msg.data = str(pkt)
1235 if action_list is not None:
1236 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001237 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001238
1239 # Set up output action
1240 if egr_ports is not None:
1241 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001242 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001243 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001244 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001245
1246 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001247 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001248
Rich Lane8f45e2d2013-10-01 16:06:54 -07001249 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001250 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001251
Dan Talaycof6e76c02012-03-23 10:56:12 -07001252def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1253 """
1254 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001255 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001256 @param of_ports List of OF port numbers
1257 @param how_many Number of ports to be added to the list
1258 @param exclude_list List of ports not to be used
1259 @returns An empty list if unable to find enough ports
1260 """
1261
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001262 if how_many == 0:
1263 return []
1264
Dan Talaycof6e76c02012-03-23 10:56:12 -07001265 count = 0
1266 egr_ports = []
1267 for egr_idx in range(len(of_ports)):
1268 if of_ports[egr_idx] not in exclude_list:
1269 egr_ports.append(of_ports[egr_idx])
1270 count += 1
1271 if count >= how_many:
1272 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001273 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001274 return []
1275
Rich Laned0478ff2013-03-11 12:46:58 -07001276def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001277 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001278 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001279 """
Rich Lane89725bb2012-12-03 16:23:27 -08001280 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001281
1282 @param max_test If > 0 no more than this number of tests are executed.
1283 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001284 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001285 @param pkt If not None, use this packet for ingress
1286 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001287 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001288 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1289 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001290 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001291 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001292 if wildcards is None:
1293 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001294 of_ports = port_map.keys()
1295 of_ports.sort()
1296 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1297 test_count = 0
1298
Dan Talaycocfa172f2012-03-23 12:03:00 -07001299 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001300 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001301
Dan Talayco551befa2010-07-15 17:05:32 -07001302 for ing_idx in range(len(of_ports)):
1303 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001304 egr_ports = get_egr_list(parent, of_ports, egr_count,
1305 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001306 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001307 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001308 if len(egr_ports) == 0:
1309 parent.assertTrue(0, "Failed to generate egress port list")
1310
1311 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001312 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001313 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001314 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001315 test_count += 1
1316 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001317 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001318 break
1319
Ed Swierk38eea082013-01-02 19:46:20 -08001320 if not test_param_get('pktout_actions', default=True):
1321 return
Rich Lane89725bb2012-12-03 16:23:27 -08001322
1323 ingress_port = of_ports[0]
1324 egr_ports = get_egr_list(parent, of_ports, egr_count,
1325 exclude_list=[ingress_port])
1326 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001327 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001328 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001329 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001330 pkt=pkt, exp_pkt=exp_pkt,
1331 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001332
Rich Lane2014f9b2012-10-05 15:29:40 -07001333def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001334 """
1335 Return value passed via test-params if present
1336
Dan Talayco4b2bee62010-07-20 14:10:05 -07001337 @param key The lookup key
1338 @param default Default value to use if not found
1339
1340 If the pair 'key=val' appeared in the string passed to --test-params
1341 on the command line, return val (as interpreted by exec). Otherwise
1342 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001343
1344 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1345 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001346 """
1347 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001348 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001349 except:
1350 return default
1351
Dan Talayco4b2bee62010-07-20 14:10:05 -07001352 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001353 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001354 except:
1355 return default
1356
1357def action_generate(parent, field_to_mod, mod_field_vals):
1358 """
1359 Create an action to modify the field indicated in field_to_mod
1360
1361 @param parent Must implement, assertTrue
1362 @param field_to_mod The field to modify as a string name
1363 @param mod_field_vals Hash of values to use for modified values
1364 """
1365
1366 act = None
1367
1368 if field_to_mod in ['pktlen']:
1369 return None
1370
Rich Laned0478ff2013-03-11 12:46:58 -07001371 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001372 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001373 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001374 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001375 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001376 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001377 elif field_to_mod == 'dl_vlan_enable':
1378 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001379 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001380 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001381 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001382 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001383 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001384 act.vlan_vid = mod_field_vals['vlan_vid']
1385 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001386 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001387 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001388 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001389 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001390 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001391 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001392 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001393 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001394 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001395 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001396 act.nw_tos = mod_field_vals['ip_tos']
1397 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001398 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001399 act.tp_port = mod_field_vals['tcp_sport']
1400 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001401 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001402 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001403 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001404 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001405 act.tp_port = mod_field_vals['udp_sport']
1406 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001407 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001408 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001409 else:
1410 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1411
1412 return act
1413
1414def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001415 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001416 """
1417 Set up the ingress and expected packet and action list for a test
1418
Rich Lane2014f9b2012-10-05 15:29:40 -07001419 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001420 @param start_field_values Field values to use for ingress packet (optional)
1421 @param mod_field_values Field values to use for modified packet (optional)
1422 @param mod_fields The list of fields to be modified by the switch in the test.
1423 @params check_test_params If True, will check the parameters vid, add_vlan
1424 and strip_vlan from the command line.
1425
1426 Returns a triple: pkt-to-send, expected-pkt, action-list
1427 """
1428
1429 new_actions = []
1430
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 base_pkt_params = {}
1432 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001433 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1434 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001435 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001436 base_pkt_params['vlan_vid'] = 2
1437 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001438 base_pkt_params['ip_src'] = '192.168.0.1'
1439 base_pkt_params['ip_dst'] = '192.168.0.2'
1440 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001441 if tp == "tcp":
1442 base_pkt_params['tcp_sport'] = 1234
1443 base_pkt_params['tcp_dport'] = 80
1444 elif tp == "udp":
1445 base_pkt_params['udp_sport'] = 1234
1446 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001447 for keyname in start_field_vals.keys():
1448 base_pkt_params[keyname] = start_field_vals[keyname]
1449
1450 mod_pkt_params = {}
1451 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001452 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1453 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001454 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001455 mod_pkt_params['vlan_vid'] = 3
1456 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001457 mod_pkt_params['ip_src'] = '10.20.30.40'
1458 mod_pkt_params['ip_dst'] = '50.60.70.80'
1459 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001460 if tp == "tcp":
1461 mod_pkt_params['tcp_sport'] = 4321
1462 mod_pkt_params['tcp_dport'] = 8765
1463 elif tp == "udp":
1464 mod_pkt_params['udp_sport'] = 4321
1465 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001466 for keyname in mod_field_vals.keys():
1467 mod_pkt_params[keyname] = mod_field_vals[keyname]
1468
1469 # Check for test param modifications
1470 strip = False
1471 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001472 add_vlan = test_param_get('add_vlan')
1473 strip_vlan = test_param_get('strip_vlan')
1474 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475
1476 if add_vlan and strip_vlan:
1477 parent.assertTrue(0, "Add and strip VLAN both specified")
1478
1479 if vid:
1480 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001481 base_pkt_params['vlan_vid'] = vid
1482 if 'vlan_vid' in mod_fields:
1483 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484
1485 if add_vlan:
1486 base_pkt_params['dl_vlan_enable'] = False
1487 mod_pkt_params['dl_vlan_enable'] = True
1488 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1489 mod_fields.append('pktlen')
1490 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001491 if 'vlan_vid' not in mod_fields:
1492 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493 elif strip_vlan:
1494 base_pkt_params['dl_vlan_enable'] = True
1495 mod_pkt_params['dl_vlan_enable'] = False
1496 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1497 mod_fields.append('dl_vlan_enable')
1498 mod_fields.append('pktlen')
1499
Rich Lane110e0e32012-10-26 16:21:46 -07001500 if tp == "tcp":
1501 packet_builder = simple_tcp_packet
1502 elif tp == "udp":
1503 packet_builder = simple_udp_packet
1504 else:
1505 raise NotImplementedError("unknown transport protocol %s" % tp)
1506
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001508 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001509
1510 # Build the expected packet, modifying the indicated fields
1511 for item in mod_fields:
1512 base_pkt_params[item] = mod_pkt_params[item]
1513 act = action_generate(parent, item, mod_pkt_params)
1514 if act:
1515 new_actions.append(act)
1516
Rich Lane110e0e32012-10-26 16:21:46 -07001517 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518
1519 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001520
1521# Generate a simple "drop" flow mod
1522# If in_band is true, then only drop from first test port
1523def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001524 request = ofp.message.flow_add()
1525 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001526 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001527 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001528 for of_port, ifname in port_map.items(): # Grab first port
1529 break
1530 request.match.in_port = of_port
1531 request.buffer_id = 0xffffffff
1532 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001533
1534def skip_message_emit(parent, s):
1535 """
1536 Print out a 'skipped' message to stderr
1537
1538 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001539 """
1540 global skipped_test_count
1541
1542 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001543 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001544 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001545 sys.stderr.write("(skipped) ")
1546 else:
1547 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001548
Dan Talayco8a64e332012-03-28 14:53:20 -07001549
1550def all_stats_get(parent):
1551 """
1552 Get the aggregate stats for all flows in the table
1553 @param parent Test instance with controller connection and assert
1554 @returns dict with keys flows, packets, bytes, active (flows),
1555 lookups, matched
1556 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001557 stat_req = ofp.message.aggregate_stats_request()
1558 stat_req.match = ofp.match()
1559 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001560 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001561 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001562
1563 rv = {}
1564
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001565 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001566 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001567
Rich Lane5fd6faf2013-03-11 13:30:20 -07001568 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001569 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1570 obj.packet_count, obj.byte_count)
1571 break
1572
Rich Lanee717c6e2013-03-12 10:25:50 -07001573 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001574 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001575
1576
1577 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001578 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001579 rv["active"] += obj.active_count
1580 rv["lookups"] += obj.lookup_count
1581 rv["matched"] += obj.matched_count
1582
1583 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001584
Rich Lane7744e112013-01-11 17:23:57 -08001585_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001586FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1587 for x in range(256)])
1588
1589def hex_dump_buffer(src, length=16):
1590 """
1591 Convert src to a hex dump string and return the string
1592 @param src The source buffer
1593 @param length The number of bytes shown in each line
1594 @returns A string showing the hex dump
1595 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001596 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001597 for i in xrange(0, len(src), length):
1598 chars = src[i:i+length]
1599 hex = ' '.join(["%02x" % ord(x) for x in chars])
1600 printable = ''.join(["%s" % ((ord(x) <= 127 and
1601 FILTER[ord(x)]) or '.') for x in chars])
1602 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1603 return ''.join(result)
1604
1605def format_packet(pkt):
1606 return "Packet length %d \n%s" % (len(str(pkt)),
1607 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001608
1609def inspect_packet(pkt):
1610 """
1611 Wrapper around scapy's show() method.
1612 @returns A string showing the dissected packet.
1613 """
1614 from cStringIO import StringIO
1615 out = None
1616 backup = sys.stdout
1617 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001618 tmp = StringIO()
1619 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001620 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001621 out = tmp.getvalue()
1622 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001623 finally:
1624 sys.stdout = backup
1625 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001626
1627def nonstandard(cls):
1628 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001629 Testcase decorator that marks the test as being non-standard.
1630 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001631 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001632 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001633 return cls
1634
1635def disabled(cls):
1636 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001637 Testcase decorator that marks the test as being disabled.
1638 These tests are not automatically added to the "standard" group or
1639 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001640 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001641 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001642 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001643
1644def group(name):
1645 """
1646 Testcase decorator that adds the test to a group.
1647 """
1648 def fn(cls):
1649 if not hasattr(cls, "_groups"):
1650 cls._groups = []
1651 cls._groups.append(name)
1652 return cls
1653 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001654
1655def version(ver):
1656 """
1657 Testcase decorator that specifies which versions of OpenFlow the test
1658 supports. The default is 1.0+. This decorator may only be used once.
1659
1660 Supported syntax:
1661 1.0 -> 1.0
1662 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1663 1.0+ -> 1.0, 1.1, 1.2, 1.3
1664 """
1665 versions = parse_version(ver)
1666 def fn(cls):
1667 cls._versions = versions
1668 return cls
1669 return fn
1670
1671def parse_version(ver):
1672 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1673 if re.match("^1\.\d+$", ver):
1674 versions = set([ver])
1675 elif re.match("^(1\.\d+)\+$", ver):
1676 if not ver[:-1] in allowed_versions:
1677 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1678 versions = set()
1679 if ver != "1.1+": versions.add("1.0")
1680 if ver != "1.2+": versions.add("1.1")
1681 if ver != "1.3+": versions.add("1.2")
1682 versions.add("1.3")
1683 else:
1684 versions = set(ver.split(','))
1685
1686 for version in versions:
1687 if not version in allowed_versions:
1688 raise ValueError("invalid OpenFlow version %s" % version)
1689
1690 return versions
1691
1692assert(parse_version("1.0") == set(["1.0"]))
1693assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1694assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001695
Rich Laneae3428c2013-03-07 14:37:42 -08001696def get_stats(test, req):
1697 """
1698 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1699 """
Rich Lane609194f2013-10-21 06:17:37 -07001700 msgtype = ofp.OFPT_STATS_REPLY
1701 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001702 stats = []
1703 reply, _ = test.controller.transact(req)
1704 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001705 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001706 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001707 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001708 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001709 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001710 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001711 return stats
1712
Rich Lanebd56ed62013-07-10 15:49:44 -07001713def get_flow_stats(test, match, table_id=None,
1714 out_port=None, out_group=None,
1715 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001716 """
1717 Retrieve a list of flow stats entries.
1718 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001719
1720 if table_id == None:
1721 if ofp.OFP_VERSION <= 2:
1722 table_id = 0xff
1723 else:
1724 table_id = ofp.OFPTT_ALL
1725
Rich Lanef3bc48c2013-05-03 17:39:35 -07001726 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001727 if ofp.OFP_VERSION == 1:
1728 out_port = ofp.OFPP_NONE
1729 else:
1730 out_port = ofp.OFPP_ANY
1731
1732 if out_group == None:
1733 if ofp.OFP_VERSION > 1:
1734 out_group = ofp.OFPP_ANY
1735
Rich Lanee717c6e2013-03-12 10:25:50 -07001736 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001737 table_id=table_id,
1738 out_port=out_port)
1739 if ofp.OFP_VERSION > 1:
1740 req.out_group = out_group
1741 req.cookie = cookie
1742 req.cookie_mask = cookie_mask
1743
Rich Laneae3428c2013-03-07 14:37:42 -08001744 return get_stats(test, req)
1745
Rich Lane968b6192013-03-07 15:34:43 -08001746def get_port_stats(test, port_no):
1747 """
1748 Retrieve a list of port stats entries.
1749 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001750 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001751 return get_stats(test, req)
1752
Rich Lane6a334922013-03-07 16:14:52 -08001753def get_queue_stats(test, port_no, queue_id):
1754 """
1755 Retrieve a list of queue stats entries.
1756 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001757 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001758 return get_stats(test, req)
1759
Rich Laneae3428c2013-03-07 14:37:42 -08001760def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001761 initial=[],
1762 pkts=None, bytes=None):
1763 """
1764 Verify that flow stats changed as expected.
1765
1766 Optionally takes an 'initial' list of stats entries, as returned by
1767 get_flow_stats(). If 'initial' is not given the counters are assumed to
1768 begin at 0.
1769 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001770
Rich Laneae3428c2013-03-07 14:37:42 -08001771 def accumulate(stats):
1772 pkts_acc = bytes_acc = 0
1773 for stat in stats:
1774 pkts_acc += stat.packet_count
1775 bytes_acc += stat.byte_count
1776 return (pkts_acc, bytes_acc)
1777
1778 pkts_before, bytes_before = accumulate(initial)
1779
1780 # Wait 10s for counters to update
1781 pkt_diff = byte_diff = None
1782 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001783 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001784 pkts_after, bytes_after = accumulate(stats)
1785 pkt_diff = pkts_after - pkts_before
1786 byte_diff = bytes_after - bytes_before
1787 if (pkts == None or pkt_diff >= pkts) and \
1788 (bytes == None or byte_diff >= bytes):
1789 break
Dan Talayco53724732013-03-08 23:54:02 -08001790 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001791
1792 if pkts != None:
1793 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1794
1795 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001796 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1797 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001798
Rich Lane968b6192013-03-07 15:34:43 -08001799def verify_port_stats(test, port,
1800 initial=[],
1801 tx_pkts=None, rx_pkts=None,
1802 tx_bytes=None, rx_bytes=None):
1803 """
1804 Verify that port stats changed as expected.
1805
1806 Optionally takes an 'initial' list of stats entries, as returned by
1807 get_port_stats(). If 'initial' is not given the counters are assumed to
1808 begin at 0.
1809 """
1810 def accumulate(stats):
1811 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1812 for stat in stats:
1813 tx_pkts_acc += stat.tx_packets
1814 rx_pkts_acc += stat.rx_packets
1815 tx_bytes_acc += stat.tx_bytes
1816 rx_bytes_acc += stat.rx_bytes
1817 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1818
1819 tx_pkts_before, rx_pkts_before, \
1820 tx_bytes_before, rx_bytes_before = accumulate(initial)
1821
1822 # Wait 10s for counters to update
1823 for i in range(0, 100):
1824 stats = get_port_stats(test, port)
1825 tx_pkts_after, rx_pkts_after, \
1826 tx_bytes_after, rx_bytes_after = accumulate(stats)
1827 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1828 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1829 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1830 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001831 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1832 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001833 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1834 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001835 break
1836 time.sleep(0.1)
1837
1838 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001839 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1840 "Port TX packet counter is not updated correctly (expected increase of %d, got increase of %d)" % (tx_pkts, tx_pkts_diff))
Rich Lane968b6192013-03-07 15:34:43 -08001841 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001842 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1843 "Port RX packet counter is not updated correctly (expected increase of %d, got increase of %d)" % (rx_pkts, rx_pkts_diff))
Rich Lane968b6192013-03-07 15:34:43 -08001844 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001845 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1846 "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 -08001847 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001848 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1849 "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 -08001850
Rich Lane6a334922013-03-07 16:14:52 -08001851def verify_queue_stats(test, port_no, queue_id,
1852 initial=[],
1853 pkts=None, bytes=None):
1854 """
1855 Verify that queue stats changed as expected.
1856
1857 Optionally takes an 'initial' list of stats entries, as returned by
1858 get_queue_stats(). If 'initial' is not given the counters are assumed to
1859 begin at 0.
1860 """
1861 def accumulate(stats):
1862 pkts_acc = bytes_acc = 0
1863 for stat in stats:
1864 pkts_acc += stat.tx_packets
1865 bytes_acc += stat.tx_bytes
1866 return (pkts_acc, bytes_acc)
1867
1868 pkts_before, bytes_before = accumulate(initial)
1869
1870 # Wait 10s for counters to update
1871 pkt_diff = byte_diff = None
1872 for i in range(0, 100):
1873 stats = get_queue_stats(test, port_no, queue_id)
1874 pkts_after, bytes_after = accumulate(stats)
1875 pkt_diff = pkts_after - pkts_before
1876 byte_diff = bytes_after - bytes_before
1877 if (pkts == None or pkt_diff >= pkts) and \
1878 (bytes == None or byte_diff >= bytes):
1879 break
Dan Talayco53724732013-03-08 23:54:02 -08001880 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001881
1882 if pkts != None:
1883 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1884
1885 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001886 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1887 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001888
Rich Lane4c504f32013-06-07 17:24:14 -07001889def packet_in_match(msg, data, in_port=None, reason=None):
1890 """
1891 Check whether the packet_in message 'msg' has fields matching 'data',
1892 'in_port', and 'reason'.
1893
1894 This function handles truncated packet_in data. The 'in_port' and 'reason'
1895 parameters are optional.
1896
1897 @param msg packet_in message
1898 @param data Expected packet_in data
1899 @param in_port Expected packet_in in_port, or None
1900 @param reason Expected packet_in reason, or None
1901 """
1902
Rich Lanec0d26dd2013-07-10 12:46:03 -07001903 if ofp.OFP_VERSION <= 2:
1904 pkt_in_port = msg.in_port
1905 else:
1906 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1907 if ofp.oxm.in_port in oxms:
1908 pkt_in_port = oxms[ofp.oxm.in_port].value
1909 else:
1910 logging.warn("Missing in_port in packet-in message")
1911 pkt_in_port = None
1912
1913 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001914 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001915 return False
1916
Rich Lanec0d26dd2013-07-10 12:46:03 -07001917 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001918 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1919 return False
1920
1921 # Check that one of the packets is a prefix of the other.
1922 # The received packet may be either truncated or padded, but not both.
1923 # (Some of the padding may be truncated but that's irrelevant). We
1924 # need to check that the smaller packet is a prefix of the larger one.
1925 # Note that this check succeeds if the switch sends a zero-length
1926 # packet-in.
1927 compare_len = min(len(msg.data), len(data))
1928 if data[:compare_len] != msg.data[:compare_len]:
1929 logging.debug("Incorrect packet_in data")
1930 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1931 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1932 return False
1933
1934 return True
1935
1936def verify_packet_in(test, data, in_port, reason, controller=None):
1937 """
1938 Assert that the controller receives a packet_in message matching data 'data'
1939 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1940 itself, that's up to the test case.
1941
1942 @param test Instance of base_tests.SimpleProtocol
1943 @param pkt String to expect as the packet_in data
1944 @param in_port OpenFlow port number to expect as the packet_in in_port
1945 @param reason One of OFPR_* to expect as the packet_in reason
1946 @param controller Controller instance, defaults to test.controller
1947 @returns The received packet-in message
1948 """
1949
1950 if controller == None:
1951 controller = test.controller
1952
1953 end_time = time.time() + oftest.ofutils.default_timeout
1954
1955 while True:
1956 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1957 if not msg:
1958 # Timeout
1959 break
1960 elif packet_in_match(msg, data, in_port, reason):
1961 # Found a matching message
1962 break
1963
Kiran Poola58c5c042014-05-15 15:11:06 -07001964 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001965 return msg
1966
1967def verify_no_packet_in(test, data, in_port, controller=None):
1968 """
1969 Assert that the controller does not receive a packet_in message matching
1970 data 'data' from port 'in_port'.
1971
1972 @param test Instance of base_tests.SimpleProtocol
1973 @param pkt String to expect as the packet_in data
1974 @param in_port OpenFlow port number to expect as the packet_in in_port
1975 @param controller Controller instance, defaults to test.controller
1976 """
1977
1978 if controller == None:
1979 controller = test.controller
1980
1981 # Negative test, need to wait a short amount of time before checking we
1982 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001983 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001984
1985 # Check every packet_in queued in the controller
1986 while True:
1987 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1988 if msg == None:
1989 # No more queued packet_in messages
1990 break
1991 elif packet_in_match(msg, data, in_port, None):
1992 # Found a matching message
1993 break
1994
Rich Lane82c882d2013-08-09 17:13:52 -07001995 if in_port == None:
1996 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1997 else:
1998 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001999
Rich Lane045db072013-08-06 13:16:30 -07002000def openflow_ports(num=None):
2001 """
2002 Return a list of 'num' OpenFlow port numbers
2003
2004 If 'num' is None, return all available ports. Otherwise, limit the length
2005 of the result to 'num' and raise an exception if not enough ports are
2006 available.
2007 """
2008 ports = sorted(oftest.config["port_map"].keys())
2009 if num != None and len(ports) < num:
2010 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2011 return ports[:num]
2012
Rich Lanee4b384d2013-09-13 14:33:40 -07002013def verify_packet(test, pkt, ofport):
2014 """
2015 Check that an expected packet is received
2016 """
2017 logging.debug("Checking for pkt on port %r", ofport)
2018 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2019 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002020 return (rcv_port, rcv_pkt, pkt_time)
2021
Rich Lanee4b384d2013-09-13 14:33:40 -07002022def verify_no_packet(test, pkt, ofport):
2023 """
2024 Check that a particular packet is not received
2025 """
2026 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002027 (rcv_port, rcv_pkt, pkt_time) = \
2028 test.dataplane.poll(
2029 port_number=ofport, exp_pkt=str(pkt),
2030 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002031 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2032
2033def verify_no_other_packets(test):
2034 """
2035 Check that no unexpected packets are received
2036
2037 This is a no-op if the --relax option is in effect.
2038 """
2039 if oftest.config["relax"]:
2040 return
2041 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002042 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002043 if rcv_pkt != None:
2044 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2045 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2046
2047def verify_packets(test, pkt, ofports):
2048 """
2049 Check that a packet is received on certain ports
2050
2051 Also verifies that the packet is not received on any other ports, and that no
2052 other packets are received (unless --relax is in effect).
2053
2054 This covers the common and simplest cases for checking dataplane outputs.
2055 For more complex usage, like multiple different packets being output, or
2056 multiple packets on the same port, use the primitive verify_packet,
2057 verify_no_packet, and verify_no_other_packets functions directly.
2058 """
2059 pkt = str(pkt)
2060 for ofport in openflow_ports():
2061 if ofport in ofports:
2062 verify_packet(test, pkt, ofport)
2063 else:
2064 verify_no_packet(test, pkt, ofport)
2065 verify_no_other_packets(test)
2066
Rich Lane12d04592013-10-10 17:21:07 -07002067def verify_no_errors(ctrl):
2068 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2069 if error:
2070 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002071
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002072def verify_capability(test, capability):
2073 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002074 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002075
2076 @param test Instance of base_tests.SimpleProtocol
2077 @param capability One of ofp_capabilities.
2078 """
2079 logging.info("Verifing that capability code is valid.")
2080 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2081 "Capability code %d does not exist." % capability)
2082 capability_str = ofp.const.ofp_capabilities_map[capability]
2083
2084 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002085 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002086 req = ofp.message.features_request()
2087 res, raw = test.controller.transact(req)
2088 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2089 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2090 ("Unexpected packet type %d received in response to "
2091 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002092 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002093
Jonathan Stout641167f2014-02-04 12:07:10 -05002094 if (res.capabilities & capability) > 0:
2095 logging.info("Switch capabilities bitmask claims to support %s",
2096 capability_str)
2097 return True, res.capabilities
2098 else:
2099 logging.info("Capabilities bitmask does not support %s.",
2100 capability_str)
2101 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002102
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002103def verify_configuration_flag(test, flag):
2104 """
2105 Return True if DUT supports specified configuration flag.
2106
2107 @param test Instance of base_tests.SimpleProtocol
2108 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002109 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002110 """
2111 logging.info("Verifing that flag is valid.")
2112 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2113 "flag %s does not exist." % flag)
2114 flag_str = ofp.const.ofp_config_flags_map[flag]
2115
2116 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
2117 req = ofp.message.get_config_request()
2118 rv = test.controller.message_send(req)
2119 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2120
2121 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2122 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2123 timeout=2)
2124 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2125 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2126
2127 if res.flags == flag:
2128 logging.info("%s flag is set.", flag_str)
2129 return True, res.flags
2130 else:
2131 logging.info("%s flag is not set.", flag_str)
2132 return False, res.flags
2133
Rich Lane7744e112013-01-11 17:23:57 -08002134__all__ = list(set(locals()) - _import_blacklist)