blob: 323119a714dd5237e873e50cbbff4ff5d62af544 [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()):
72 msg = ofp.message.group_delete(group_id=group_queue.get())
73 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
453def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
454 eth_src='00:06:07:08:09:0a',
455 dl_vlan_enable=False,
456 vlan_vid=0,
457 vlan_pcp=0,
458 dl_vlan_cfi=0,
459 label=None,
460 inner_payload=None
461 ):
462 """
463 Return a simple dataplane MPLS packet
464
465 Supports a few parameters:
466 @param len Length of packet in bytes w/o CRC
467 @param eth_dst Destination MAC
468 @param eth_src Source MAC
469 @param dl_vlan_enable True if the packet is with vlan, False otherwise
470 @param vlan_vid VLAN ID
471 @param vlan_pcp VLAN priority
472 @param inner_pyload inner pacekt content
473 Generates a simple MPLS packet. Users shouldn't assume anything about
474 this packet other than that it is a valid ethernet/IP/UDP frame.
475 """
476
477 # Note Dot1Q.id is really CFI
478 if (dl_vlan_enable):
479 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
480 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
481 else:
482 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
483
484 #add MPLS header
485 for i in range(len(label)):
486 l,c,s,t=label[i]
487 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
488
489 #add innder payload
490 if inner_payload!=None:
491 pkt=pkt/inner_payload
492
493 return pkt
494
Rich Lane86aceb02013-07-17 18:45:38 -0700495def simple_udpv6_packet(pktlen=100,
496 eth_dst='00:01:02:03:04:05',
497 eth_src='00:06:07:08:09:0a',
498 dl_vlan_enable=False,
499 vlan_vid=0,
500 vlan_pcp=0,
501 ipv6_src='2001:db8:85a3::8a2e:370:7334',
502 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
503 ipv6_tc=0,
504 ipv6_hlim=64,
505 ipv6_fl=0,
506 udp_sport=1234,
507 udp_dport=80):
508 """
509 Return a simple IPv6/UDP packet
510
511 Supports a few parameters:
512 @param len Length of packet in bytes w/o CRC
513 @param eth_dst Destination MAC
514 @param eth_src Source MAC
515 @param dl_vlan_enable True if the packet is with vlan, False otherwise
516 @param vlan_vid VLAN ID
517 @param vlan_pcp VLAN priority
518 @param ipv6_src IPv6 source
519 @param ipv6_dst IPv6 destination
520 @param ipv6_tc IPv6 traffic class
521 @param ipv6_ttl IPv6 hop limit
522 @param ipv6_fl IPv6 flow label
523 @param udp_dport UDP destination port
524 @param udp_sport UDP source port
525
526 Generates a simple UDP request. Users shouldn't assume anything about this
527 packet other than that it is a valid ethernet/IPv6/UDP frame.
528 """
529
530 if MINSIZE > pktlen:
531 pktlen = MINSIZE
532
533 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
534 if dl_vlan_enable or vlan_vid or vlan_pcp:
535 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
536 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
537 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
538 pkt /= ("D" * (pktlen - len(pkt)))
539
540 return pkt
541
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700542def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700543 eth_dst='00:01:02:03:04:05',
544 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700545 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700546 vlan_vid=0,
547 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700548 ip_src='192.168.0.1',
549 ip_dst='192.168.0.2',
550 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800551 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600552 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700553 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600554 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600555 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700556 """
557 Return a simple ICMP packet
558
559 Supports a few parameters:
560 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700561 @param eth_dst Destinatino MAC
562 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700563 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700564 @param vlan_vid VLAN ID
565 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700566 @param ip_src IP source
567 @param ip_dst IP destination
568 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800569 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600570 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700571 @param icmp_type ICMP type
572 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600573 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700574
575 Generates a simple ICMP ECHO REQUEST. Users
576 shouldn't assume anything about this packet other than that
577 it is a valid ethernet/ICMP frame.
578 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000579
580 if MINSIZE > pktlen:
581 pktlen = MINSIZE
582
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700583 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700584 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
585 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600586 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600587 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700588 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700589 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600590 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600591 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700592
593 pkt = pkt/("0" * (pktlen - len(pkt)))
594
595 return pkt
596
Rich Lane86aceb02013-07-17 18:45:38 -0700597def simple_icmpv6_packet(pktlen=100,
598 eth_dst='00:01:02:03:04:05',
599 eth_src='00:06:07:08:09:0a',
600 dl_vlan_enable=False,
601 vlan_vid=0,
602 vlan_pcp=0,
603 ipv6_src='2001:db8:85a3::8a2e:370:7334',
604 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
605 ipv6_tc=0,
606 ipv6_hlim=64,
607 ipv6_fl=0,
608 icmp_type=8,
609 icmp_code=0):
610 """
611 Return a simple ICMPv6 packet
612
613 Supports a few parameters:
614 @param len Length of packet in bytes w/o CRC
615 @param eth_dst Destination MAC
616 @param eth_src Source MAC
617 @param dl_vlan_enable True if the packet is with vlan, False otherwise
618 @param vlan_vid VLAN ID
619 @param vlan_pcp VLAN priority
620 @param ipv6_src IPv6 source
621 @param ipv6_dst IPv6 destination
622 @param ipv6_tc IPv6 traffic class
623 @param ipv6_ttl IPv6 hop limit
624 @param ipv6_fl IPv6 flow label
625 @param icmp_type ICMP type
626 @param icmp_code ICMP code
627
628 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
629 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
630 """
631
632 if MINSIZE > pktlen:
633 pktlen = MINSIZE
634
635 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
636 if dl_vlan_enable or vlan_vid or vlan_pcp:
637 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
638 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
639 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
640 pkt /= ("D" * (pktlen - len(pkt)))
641
642 return pkt
643
Shudong Zhouc7562b12013-02-06 01:12:18 -0800644def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700645 eth_dst='ff:ff:ff:ff:ff:ff',
646 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800647 vlan_vid=0,
648 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800649 arp_op=1,
650 ip_snd='192.168.0.1',
651 ip_tgt='192.168.0.2',
652 hw_snd='00:06:07:08:09:0a',
653 hw_tgt='00:00:00:00:00:00',
654 ):
655 """
656 Return a simple ARP packet
657
658 Supports a few parameters:
659 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700660 @param eth_dst Destinatino MAC
661 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800662 @param arp_op Operation (1=request, 2=reply)
663 @param ip_snd Sender IP
664 @param ip_tgt Target IP
665 @param hw_snd Sender hardware address
666 @param hw_tgt Target hardware address
667
668 Generates a simple ARP REQUEST. Users
669 shouldn't assume anything about this packet other than that
670 it is a valid ethernet/ARP frame.
671 """
672
673 if MINSIZE > pktlen:
674 pktlen = MINSIZE
675
Rich Lanee01611f2014-01-15 14:55:11 -0800676 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
677 if vlan_vid or vlan_pcp:
678 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
679 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 -0800680
Rich Laned459ce52014-01-24 12:09:54 -0800681 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800682
683 return pkt
684
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700685def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800686 eth_dst='00:01:02:03:04:05',
687 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700688 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000689
690 if MINSIZE > pktlen:
691 pktlen = MINSIZE
692
Rich Laned0478ff2013-03-11 12:46:58 -0700693 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700694
695 pkt = pkt/("0" * (pktlen - len(pkt)))
696
697 return pkt
698
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800699def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700700 eth_dst='00:01:02:03:04:05',
701 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800702 dl_vlan_outer=20,
703 dl_vlan_pcp_outer=0,
704 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700705 vlan_vid=10,
706 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800707 dl_vlan_cfi=0,
708 ip_src='192.168.0.1',
709 ip_dst='192.168.0.2',
710 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800711 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800712 tcp_sport=1234,
713 tcp_dport=80,
714 ip_ihl=None,
715 ip_options=False
716 ):
717 """
718 Return a doubly tagged dataplane TCP packet
719
720 Supports a few parameters:
721 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700722 @param eth_dst Destinatino MAC
723 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800724 @param dl_vlan_outer Outer VLAN ID
725 @param dl_vlan_pcp_outer Outer VLAN priority
726 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700727 @param vlan_vid Inner VLAN ID
728 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800729 @param dl_vlan_cfi VLAN cfi bit
730 @param ip_src IP source
731 @param ip_dst IP destination
732 @param ip_tos IP ToS
733 @param tcp_dport TCP destination port
734 @param ip_sport TCP source port
735
736 Generates a TCP request. Users
737 shouldn't assume anything about this packet other than that
738 it is a valid ethernet/IP/TCP frame.
739 """
740
741 if MINSIZE > pktlen:
742 pktlen = MINSIZE
743
744 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700745 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800746 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700747 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800748 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800749 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
750
751 pkt = pkt/("D" * (pktlen - len(pkt)))
752
753 return pkt
754
Shudong Zhoub7f12462012-11-20 13:01:12 -0800755def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700756 """
757 Do a barrier command
758 Return 0 on success, -1 on error
759 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700760 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800761 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800762 if resp is None:
763 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700764 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800765 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700766
Rich Lane9a003812012-10-04 17:17:59 -0700767def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700768 """
769 Get a port's configuration
770
771 Gets the switch feature configuration and grabs one port's
772 configuration
773
774 @returns (hwaddr, config, advert) The hwaddress, configuration and
775 advertised values
776 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700777
778 if ofp.OFP_VERSION <= 3:
779 request = ofp.message.features_request()
780 reply, _ = controller.transact(request)
781 if reply is None:
782 logging.warn("Get feature request failed")
783 return None, None, None
784 logging.debug(reply.show())
785 ports = reply.ports
786 else:
787 request = ofp.message.port_desc_stats_request()
788 # TODO do multipart correctly
789 reply, _ = controller.transact(request)
790 if reply is None:
791 logging.warn("Port desc stats request failed")
792 return None, None, None
793 logging.debug(reply.show())
794 ports = reply.entries
795
796 for port in ports:
797 if port.port_no == port_no:
798 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700799
Rich Lane9a003812012-10-04 17:17:59 -0700800 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700801 return None, None, None
802
Rich Lane9a003812012-10-04 17:17:59 -0700803def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700804 """
805 Set the port configuration according the given parameters
806
807 Gets the switch feature configuration and updates one port's
808 configuration value according to config and mask
809 """
Rich Lane9a003812012-10-04 17:17:59 -0700810 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700811
812 hw_addr, _, _ = port_config_get(controller, port_no)
813
Rich Lanee717c6e2013-03-12 10:25:50 -0700814 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700815 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700816 if hw_addr != None:
817 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700818 mod.config = config
819 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700820 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800821 controller.message_send(mod)
822 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700823
Rich Lane2014f9b2012-10-05 15:29:40 -0700824def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700825 """
826 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700827 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700828 @param pkt Expected packet; may be None if yes_ports is empty
829 @param yes_ports Set or list of ports that should recieve packet
830 @param no_ports Set or list of ports that should not receive packet
831 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700832
833 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700834 """
Rich Lane91765672012-12-06 16:33:04 -0800835
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700836 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800837 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700838 exp_pkt_arg = pkt
839
Dan Talayco92c99122010-06-03 13:53:18 -0700840 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700841 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700842 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800843 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700844 assert_if.assertTrue(rcv_pkt is not None,
845 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800846 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800847 logging.debug("Expected %s" % format_packet(pkt))
848 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800849 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800850 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700851 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700852 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700853 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700854 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700855 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700856 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800857 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700858 assert_if.assertTrue(rcv_pkt is None,
859 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700860
861
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700862def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700863 """
864 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700865 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700866
867 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700868
869 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700870 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700871 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800872 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700873 exp_pkt_arg = exp_pkt
874
Dan Talaycof6e76c02012-03-23 10:56:12 -0700875 if type(egr_ports) == type([]):
876 egr_port_list = egr_ports
877 else:
878 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700879
Dan Talaycof6e76c02012-03-23 10:56:12 -0700880 # Expect a packet from each port on egr port list
881 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700882 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -0700883 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700884 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700885 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700886 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700887
Dan Talaycof6e76c02012-03-23 10:56:12 -0700888 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700889 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700890 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700891
Dan Talaycof6e76c02012-03-23 10:56:12 -0700892 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700893 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700894 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700895 str(rcv_port))
896
897 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700898 logging.error("ERROR: Packet match failed.")
899 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700900 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700901 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700902 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700903 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
904 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700905 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700906 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700907
Dan Talayco551befa2010-07-15 17:05:32 -0700908def match_verify(parent, req_match, res_match):
909 """
910 Verify flow matches agree; if they disagree, report where
911
912 parent must implement assertEqual
913 Use str() to ensure content is compared and not pointers
914 """
915
916 parent.assertEqual(req_match.wildcards, res_match.wildcards,
917 'Match failed: wildcards: ' + hex(req_match.wildcards) +
918 " != " + hex(res_match.wildcards))
919 parent.assertEqual(req_match.in_port, res_match.in_port,
920 'Match failed: in_port: ' + str(req_match.in_port) +
921 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -0700922 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
923 'Match failed: eth_src: ' + str(req_match.eth_src) +
924 " != " + str(res_match.eth_src))
925 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
926 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
927 " != " + str(res_match.eth_dst))
928 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
929 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
930 " != " + str(res_match.vlan_vid))
931 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
932 'Match failed: vlan_pcp: ' +
933 str(req_match.vlan_pcp) + " != " +
934 str(res_match.vlan_pcp))
935 parent.assertEqual(req_match.eth_type, res_match.eth_type,
936 'Match failed: eth_type: ' + str(req_match.eth_type) +
937 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -0700938
Rich Lanee717c6e2013-03-12 10:25:50 -0700939 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -0700940 and (req_match.eth_type == IP_ETHERTYPE)):
941 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
942 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
943 " != " + str(res_match.ip_dscp))
944 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
945 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
946 " != " + str(res_match.ip_proto))
947 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
948 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
949 " != " + str(res_match.ipv4_src))
950 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
951 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
952 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700953
Rich Lanee717c6e2013-03-12 10:25:50 -0700954 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -0700955 and ((req_match.ip_proto == TCP_PROTOCOL)
956 or (req_match.ip_proto == UDP_PROTOCOL))):
957 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
958 'Match failed: tcp_src: ' +
959 str(req_match.tcp_src) +
960 " != " + str(res_match.tcp_src))
961 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
962 'Match failed: tcp_dst: ' +
963 str(req_match.tcp_dst) +
964 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700965
Ed Swierk99a74de2012-08-22 06:40:54 -0700966def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -0700967 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -0700968 if ofp.OFP_VERSION in [1, 2]:
969 match.wildcards |= required_wildcards(parent)
970 else:
971 # TODO remove incompatible OXM entries
972 pass
Ed Swierk99a74de2012-08-22 06:40:54 -0700973 return match
974
975def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700976 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700977 """
978 Create a flow message
979
980 Match on packet with given wildcards.
981 See flow_match_test for other parameter descriptoins
982 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -0700983 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700984 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700985 """
Rich Lanef6883512013-03-11 17:00:09 -0700986 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -0700987 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -0700988 if wildcards is None:
989 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -0700990 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -0700991 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -0700992 match.wildcards = wildcards
993 match.in_port = ing_port
994
Dan Talaycof6e76c02012-03-23 10:56:12 -0700995 if type(egr_ports) == type([]):
996 egr_port_list = egr_ports
997 else:
998 egr_port_list = [egr_ports]
999
Rich Lanee717c6e2013-03-12 10:25:50 -07001000 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001001 request.match = match
1002 request.buffer_id = 0xffffffff
1003 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001004 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001005 request.hard_timeout = 1
1006
Rich Lane400fb9b2013-10-10 17:20:54 -07001007 if ofp.OFP_VERSION == 1:
1008 actions = request.actions
1009 else:
1010 actions = []
1011 request.instructions.append(ofp.instruction.apply_actions(actions))
1012
Dan Talayco551befa2010-07-15 17:05:32 -07001013 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001014 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001015
1016 # Set up output/enqueue action if directed
1017 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001018 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001019 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001020 for egr_port in egr_port_list:
1021 act.port = egr_port
1022 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001023 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001024 elif egr_ports is not None:
1025 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001026 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001027 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001028 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001029
Rich Lane9a003812012-10-04 17:17:59 -07001030 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001031
1032 return request
1033
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001034def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001035 """
1036 Install a flow mod message in the switch
1037
1038 @param parent Must implement controller, assertEqual, assertTrue
1039 @param request The request, all set to go
1040 @param clear_table If true, clear the flow table before installing
1041 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001042
Rich Lane2014f9b2012-10-05 15:29:40 -07001043 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001044 if(clear_table_override != None):
1045 clear_table = clear_table_override
1046
1047 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001048 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001049 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001050
Rich Lane9a003812012-10-04 17:17:59 -07001051 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001052 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001053
Rich Lane3a261d52013-01-03 17:45:08 -08001054 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001055
Ed Swierk99a74de2012-08-22 06:40:54 -07001056def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001057 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001058 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001059 """
1060 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001061 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001062
1063 Run test with packet through switch from ing_port to egr_port
1064 See flow_match_test for parameter descriptions
1065 """
1066
Ed Swierk99a74de2012-08-22 06:40:54 -07001067 if wildcards is None:
1068 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001069 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001070 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001071 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001072 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001073 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001074 if exp_pkt is None:
1075 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001076
1077 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001078 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001079 action_list=action_list)
1080
1081 flow_msg_install(parent, request)
1082
Rich Lane9a003812012-10-04 17:17:59 -07001083 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001084 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001085 parent.dataplane.send(ing_port, str(pkt))
1086
Rich Lane8f45e2d2013-10-01 16:06:54 -07001087 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001088 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001089
Rich Lane89725bb2012-12-03 16:23:27 -08001090def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001091 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001092 action_list=None):
1093 """
1094 Packet-out test on single TCP packet
1095 @param egr_ports A single port or list of ports
1096
1097 Run test sending packet-out to egr_ports. The goal is to test the actions
1098 taken on the packet, not the matching which is of course irrelevant.
1099 See flow_match_test for parameter descriptions
1100 """
1101
1102 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001103 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001104 if exp_pkt is None:
1105 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001106
Rich Lanee717c6e2013-03-12 10:25:50 -07001107 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001108 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001109 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001110 msg.data = str(pkt)
1111 if action_list is not None:
1112 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001113 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001114
1115 # Set up output action
1116 if egr_ports is not None:
1117 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001118 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001119 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001120 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001121
1122 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001123 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001124
Rich Lane8f45e2d2013-10-01 16:06:54 -07001125 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001126 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001127
Dan Talaycof6e76c02012-03-23 10:56:12 -07001128def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1129 """
1130 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001131 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001132 @param of_ports List of OF port numbers
1133 @param how_many Number of ports to be added to the list
1134 @param exclude_list List of ports not to be used
1135 @returns An empty list if unable to find enough ports
1136 """
1137
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001138 if how_many == 0:
1139 return []
1140
Dan Talaycof6e76c02012-03-23 10:56:12 -07001141 count = 0
1142 egr_ports = []
1143 for egr_idx in range(len(of_ports)):
1144 if of_ports[egr_idx] not in exclude_list:
1145 egr_ports.append(of_ports[egr_idx])
1146 count += 1
1147 if count >= how_many:
1148 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001149 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001150 return []
1151
Rich Laned0478ff2013-03-11 12:46:58 -07001152def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001153 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001154 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001155 """
Rich Lane89725bb2012-12-03 16:23:27 -08001156 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001157
1158 @param max_test If > 0 no more than this number of tests are executed.
1159 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001160 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001161 @param pkt If not None, use this packet for ingress
1162 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001163 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001164 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1165 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001166 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001167 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001168 if wildcards is None:
1169 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001170 of_ports = port_map.keys()
1171 of_ports.sort()
1172 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1173 test_count = 0
1174
Dan Talaycocfa172f2012-03-23 12:03:00 -07001175 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001176 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001177
Dan Talayco551befa2010-07-15 17:05:32 -07001178 for ing_idx in range(len(of_ports)):
1179 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001180 egr_ports = get_egr_list(parent, of_ports, egr_count,
1181 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001182 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001183 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001184 if len(egr_ports) == 0:
1185 parent.assertTrue(0, "Failed to generate egress port list")
1186
1187 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001188 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001189 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001190 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001191 test_count += 1
1192 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001193 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001194 break
1195
Ed Swierk38eea082013-01-02 19:46:20 -08001196 if not test_param_get('pktout_actions', default=True):
1197 return
Rich Lane89725bb2012-12-03 16:23:27 -08001198
1199 ingress_port = of_ports[0]
1200 egr_ports = get_egr_list(parent, of_ports, egr_count,
1201 exclude_list=[ingress_port])
1202 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001203 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001204 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001205 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001206 pkt=pkt, exp_pkt=exp_pkt,
1207 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001208
Rich Lane2014f9b2012-10-05 15:29:40 -07001209def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001210 """
1211 Return value passed via test-params if present
1212
Dan Talayco4b2bee62010-07-20 14:10:05 -07001213 @param key The lookup key
1214 @param default Default value to use if not found
1215
1216 If the pair 'key=val' appeared in the string passed to --test-params
1217 on the command line, return val (as interpreted by exec). Otherwise
1218 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001219
1220 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1221 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001222 """
1223 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001224 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001225 except:
1226 return default
1227
Dan Talayco4b2bee62010-07-20 14:10:05 -07001228 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001229 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001230 except:
1231 return default
1232
1233def action_generate(parent, field_to_mod, mod_field_vals):
1234 """
1235 Create an action to modify the field indicated in field_to_mod
1236
1237 @param parent Must implement, assertTrue
1238 @param field_to_mod The field to modify as a string name
1239 @param mod_field_vals Hash of values to use for modified values
1240 """
1241
1242 act = None
1243
1244 if field_to_mod in ['pktlen']:
1245 return None
1246
Rich Laned0478ff2013-03-11 12:46:58 -07001247 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001248 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001249 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001250 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001251 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001252 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001253 elif field_to_mod == 'dl_vlan_enable':
1254 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001255 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001256 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001257 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001258 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001259 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001260 act.vlan_vid = mod_field_vals['vlan_vid']
1261 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001262 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001263 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001264 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001265 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001266 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001267 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001268 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001269 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001270 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001271 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001272 act.nw_tos = mod_field_vals['ip_tos']
1273 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001274 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001275 act.tp_port = mod_field_vals['tcp_sport']
1276 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001277 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001278 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001279 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001280 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001281 act.tp_port = mod_field_vals['udp_sport']
1282 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001283 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001284 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001285 else:
1286 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1287
1288 return act
1289
1290def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001291 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001292 """
1293 Set up the ingress and expected packet and action list for a test
1294
Rich Lane2014f9b2012-10-05 15:29:40 -07001295 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001296 @param start_field_values Field values to use for ingress packet (optional)
1297 @param mod_field_values Field values to use for modified packet (optional)
1298 @param mod_fields The list of fields to be modified by the switch in the test.
1299 @params check_test_params If True, will check the parameters vid, add_vlan
1300 and strip_vlan from the command line.
1301
1302 Returns a triple: pkt-to-send, expected-pkt, action-list
1303 """
1304
1305 new_actions = []
1306
Dan Talayco4b2bee62010-07-20 14:10:05 -07001307 base_pkt_params = {}
1308 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001309 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1310 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001311 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001312 base_pkt_params['vlan_vid'] = 2
1313 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001314 base_pkt_params['ip_src'] = '192.168.0.1'
1315 base_pkt_params['ip_dst'] = '192.168.0.2'
1316 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001317 if tp == "tcp":
1318 base_pkt_params['tcp_sport'] = 1234
1319 base_pkt_params['tcp_dport'] = 80
1320 elif tp == "udp":
1321 base_pkt_params['udp_sport'] = 1234
1322 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001323 for keyname in start_field_vals.keys():
1324 base_pkt_params[keyname] = start_field_vals[keyname]
1325
1326 mod_pkt_params = {}
1327 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001328 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1329 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001330 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001331 mod_pkt_params['vlan_vid'] = 3
1332 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001333 mod_pkt_params['ip_src'] = '10.20.30.40'
1334 mod_pkt_params['ip_dst'] = '50.60.70.80'
1335 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001336 if tp == "tcp":
1337 mod_pkt_params['tcp_sport'] = 4321
1338 mod_pkt_params['tcp_dport'] = 8765
1339 elif tp == "udp":
1340 mod_pkt_params['udp_sport'] = 4321
1341 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001342 for keyname in mod_field_vals.keys():
1343 mod_pkt_params[keyname] = mod_field_vals[keyname]
1344
1345 # Check for test param modifications
1346 strip = False
1347 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001348 add_vlan = test_param_get('add_vlan')
1349 strip_vlan = test_param_get('strip_vlan')
1350 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001351
1352 if add_vlan and strip_vlan:
1353 parent.assertTrue(0, "Add and strip VLAN both specified")
1354
1355 if vid:
1356 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001357 base_pkt_params['vlan_vid'] = vid
1358 if 'vlan_vid' in mod_fields:
1359 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001360
1361 if add_vlan:
1362 base_pkt_params['dl_vlan_enable'] = False
1363 mod_pkt_params['dl_vlan_enable'] = True
1364 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1365 mod_fields.append('pktlen')
1366 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001367 if 'vlan_vid' not in mod_fields:
1368 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001369 elif strip_vlan:
1370 base_pkt_params['dl_vlan_enable'] = True
1371 mod_pkt_params['dl_vlan_enable'] = False
1372 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1373 mod_fields.append('dl_vlan_enable')
1374 mod_fields.append('pktlen')
1375
Rich Lane110e0e32012-10-26 16:21:46 -07001376 if tp == "tcp":
1377 packet_builder = simple_tcp_packet
1378 elif tp == "udp":
1379 packet_builder = simple_udp_packet
1380 else:
1381 raise NotImplementedError("unknown transport protocol %s" % tp)
1382
Dan Talayco4b2bee62010-07-20 14:10:05 -07001383 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001384 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001385
1386 # Build the expected packet, modifying the indicated fields
1387 for item in mod_fields:
1388 base_pkt_params[item] = mod_pkt_params[item]
1389 act = action_generate(parent, item, mod_pkt_params)
1390 if act:
1391 new_actions.append(act)
1392
Rich Lane110e0e32012-10-26 16:21:46 -07001393 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001394
1395 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001396
1397# Generate a simple "drop" flow mod
1398# If in_band is true, then only drop from first test port
1399def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001400 request = ofp.message.flow_add()
1401 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001402 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001403 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001404 for of_port, ifname in port_map.items(): # Grab first port
1405 break
1406 request.match.in_port = of_port
1407 request.buffer_id = 0xffffffff
1408 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001409
1410def skip_message_emit(parent, s):
1411 """
1412 Print out a 'skipped' message to stderr
1413
1414 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001415 """
1416 global skipped_test_count
1417
1418 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001419 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001420 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001421 sys.stderr.write("(skipped) ")
1422 else:
1423 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001424
Dan Talayco8a64e332012-03-28 14:53:20 -07001425
1426def all_stats_get(parent):
1427 """
1428 Get the aggregate stats for all flows in the table
1429 @param parent Test instance with controller connection and assert
1430 @returns dict with keys flows, packets, bytes, active (flows),
1431 lookups, matched
1432 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001433 stat_req = ofp.message.aggregate_stats_request()
1434 stat_req.match = ofp.match()
1435 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001436 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001437 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001438
1439 rv = {}
1440
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001441 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001442 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001443
Rich Lane5fd6faf2013-03-11 13:30:20 -07001444 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001445 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1446 obj.packet_count, obj.byte_count)
1447 break
1448
Rich Lanee717c6e2013-03-12 10:25:50 -07001449 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001450 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001451
1452
1453 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001454 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001455 rv["active"] += obj.active_count
1456 rv["lookups"] += obj.lookup_count
1457 rv["matched"] += obj.matched_count
1458
1459 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001460
Rich Lane7744e112013-01-11 17:23:57 -08001461_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001462FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1463 for x in range(256)])
1464
1465def hex_dump_buffer(src, length=16):
1466 """
1467 Convert src to a hex dump string and return the string
1468 @param src The source buffer
1469 @param length The number of bytes shown in each line
1470 @returns A string showing the hex dump
1471 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001472 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001473 for i in xrange(0, len(src), length):
1474 chars = src[i:i+length]
1475 hex = ' '.join(["%02x" % ord(x) for x in chars])
1476 printable = ''.join(["%s" % ((ord(x) <= 127 and
1477 FILTER[ord(x)]) or '.') for x in chars])
1478 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1479 return ''.join(result)
1480
1481def format_packet(pkt):
1482 return "Packet length %d \n%s" % (len(str(pkt)),
1483 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001484
1485def inspect_packet(pkt):
1486 """
1487 Wrapper around scapy's show() method.
1488 @returns A string showing the dissected packet.
1489 """
1490 from cStringIO import StringIO
1491 out = None
1492 backup = sys.stdout
1493 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001494 tmp = StringIO()
1495 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001496 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001497 out = tmp.getvalue()
1498 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001499 finally:
1500 sys.stdout = backup
1501 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001502
1503def nonstandard(cls):
1504 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001505 Testcase decorator that marks the test as being non-standard.
1506 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001507 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001508 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001509 return cls
1510
1511def disabled(cls):
1512 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001513 Testcase decorator that marks the test as being disabled.
1514 These tests are not automatically added to the "standard" group or
1515 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001516 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001517 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001518 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001519
1520def group(name):
1521 """
1522 Testcase decorator that adds the test to a group.
1523 """
1524 def fn(cls):
1525 if not hasattr(cls, "_groups"):
1526 cls._groups = []
1527 cls._groups.append(name)
1528 return cls
1529 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001530
1531def version(ver):
1532 """
1533 Testcase decorator that specifies which versions of OpenFlow the test
1534 supports. The default is 1.0+. This decorator may only be used once.
1535
1536 Supported syntax:
1537 1.0 -> 1.0
1538 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1539 1.0+ -> 1.0, 1.1, 1.2, 1.3
1540 """
1541 versions = parse_version(ver)
1542 def fn(cls):
1543 cls._versions = versions
1544 return cls
1545 return fn
1546
1547def parse_version(ver):
1548 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1549 if re.match("^1\.\d+$", ver):
1550 versions = set([ver])
1551 elif re.match("^(1\.\d+)\+$", ver):
1552 if not ver[:-1] in allowed_versions:
1553 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1554 versions = set()
1555 if ver != "1.1+": versions.add("1.0")
1556 if ver != "1.2+": versions.add("1.1")
1557 if ver != "1.3+": versions.add("1.2")
1558 versions.add("1.3")
1559 else:
1560 versions = set(ver.split(','))
1561
1562 for version in versions:
1563 if not version in allowed_versions:
1564 raise ValueError("invalid OpenFlow version %s" % version)
1565
1566 return versions
1567
1568assert(parse_version("1.0") == set(["1.0"]))
1569assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1570assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001571
Rich Laneae3428c2013-03-07 14:37:42 -08001572def get_stats(test, req):
1573 """
1574 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1575 """
Rich Lane609194f2013-10-21 06:17:37 -07001576 msgtype = ofp.OFPT_STATS_REPLY
1577 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001578 stats = []
1579 reply, _ = test.controller.transact(req)
1580 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001581 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001582 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001583 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001584 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001585 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001586 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001587 return stats
1588
Rich Lanebd56ed62013-07-10 15:49:44 -07001589def get_flow_stats(test, match, table_id=None,
1590 out_port=None, out_group=None,
1591 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001592 """
1593 Retrieve a list of flow stats entries.
1594 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001595
1596 if table_id == None:
1597 if ofp.OFP_VERSION <= 2:
1598 table_id = 0xff
1599 else:
1600 table_id = ofp.OFPTT_ALL
1601
Rich Lanef3bc48c2013-05-03 17:39:35 -07001602 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001603 if ofp.OFP_VERSION == 1:
1604 out_port = ofp.OFPP_NONE
1605 else:
1606 out_port = ofp.OFPP_ANY
1607
1608 if out_group == None:
1609 if ofp.OFP_VERSION > 1:
1610 out_group = ofp.OFPP_ANY
1611
Rich Lanee717c6e2013-03-12 10:25:50 -07001612 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001613 table_id=table_id,
1614 out_port=out_port)
1615 if ofp.OFP_VERSION > 1:
1616 req.out_group = out_group
1617 req.cookie = cookie
1618 req.cookie_mask = cookie_mask
1619
Rich Laneae3428c2013-03-07 14:37:42 -08001620 return get_stats(test, req)
1621
Rich Lane968b6192013-03-07 15:34:43 -08001622def get_port_stats(test, port_no):
1623 """
1624 Retrieve a list of port stats entries.
1625 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001626 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001627 return get_stats(test, req)
1628
Rich Lane6a334922013-03-07 16:14:52 -08001629def get_queue_stats(test, port_no, queue_id):
1630 """
1631 Retrieve a list of queue stats entries.
1632 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001633 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001634 return get_stats(test, req)
1635
Rich Laneae3428c2013-03-07 14:37:42 -08001636def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001637 initial=[],
1638 pkts=None, bytes=None):
1639 """
1640 Verify that flow stats changed as expected.
1641
1642 Optionally takes an 'initial' list of stats entries, as returned by
1643 get_flow_stats(). If 'initial' is not given the counters are assumed to
1644 begin at 0.
1645 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001646
Rich Laneae3428c2013-03-07 14:37:42 -08001647 def accumulate(stats):
1648 pkts_acc = bytes_acc = 0
1649 for stat in stats:
1650 pkts_acc += stat.packet_count
1651 bytes_acc += stat.byte_count
1652 return (pkts_acc, bytes_acc)
1653
1654 pkts_before, bytes_before = accumulate(initial)
1655
1656 # Wait 10s for counters to update
1657 pkt_diff = byte_diff = None
1658 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001659 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001660 pkts_after, bytes_after = accumulate(stats)
1661 pkt_diff = pkts_after - pkts_before
1662 byte_diff = bytes_after - bytes_before
1663 if (pkts == None or pkt_diff >= pkts) and \
1664 (bytes == None or byte_diff >= bytes):
1665 break
Dan Talayco53724732013-03-08 23:54:02 -08001666 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001667
1668 if pkts != None:
1669 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1670
1671 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001672 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1673 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001674
Rich Lane968b6192013-03-07 15:34:43 -08001675def verify_port_stats(test, port,
1676 initial=[],
1677 tx_pkts=None, rx_pkts=None,
1678 tx_bytes=None, rx_bytes=None):
1679 """
1680 Verify that port stats changed as expected.
1681
1682 Optionally takes an 'initial' list of stats entries, as returned by
1683 get_port_stats(). If 'initial' is not given the counters are assumed to
1684 begin at 0.
1685 """
1686 def accumulate(stats):
1687 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1688 for stat in stats:
1689 tx_pkts_acc += stat.tx_packets
1690 rx_pkts_acc += stat.rx_packets
1691 tx_bytes_acc += stat.tx_bytes
1692 rx_bytes_acc += stat.rx_bytes
1693 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1694
1695 tx_pkts_before, rx_pkts_before, \
1696 tx_bytes_before, rx_bytes_before = accumulate(initial)
1697
1698 # Wait 10s for counters to update
1699 for i in range(0, 100):
1700 stats = get_port_stats(test, port)
1701 tx_pkts_after, rx_pkts_after, \
1702 tx_bytes_after, rx_bytes_after = accumulate(stats)
1703 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1704 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1705 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1706 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001707 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1708 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001709 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1710 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001711 break
1712 time.sleep(0.1)
1713
1714 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001715 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1716 "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 -08001717 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001718 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1719 "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 -08001720 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001721 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1722 "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 -08001723 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001724 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1725 "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 -08001726
Rich Lane6a334922013-03-07 16:14:52 -08001727def verify_queue_stats(test, port_no, queue_id,
1728 initial=[],
1729 pkts=None, bytes=None):
1730 """
1731 Verify that queue stats changed as expected.
1732
1733 Optionally takes an 'initial' list of stats entries, as returned by
1734 get_queue_stats(). If 'initial' is not given the counters are assumed to
1735 begin at 0.
1736 """
1737 def accumulate(stats):
1738 pkts_acc = bytes_acc = 0
1739 for stat in stats:
1740 pkts_acc += stat.tx_packets
1741 bytes_acc += stat.tx_bytes
1742 return (pkts_acc, bytes_acc)
1743
1744 pkts_before, bytes_before = accumulate(initial)
1745
1746 # Wait 10s for counters to update
1747 pkt_diff = byte_diff = None
1748 for i in range(0, 100):
1749 stats = get_queue_stats(test, port_no, queue_id)
1750 pkts_after, bytes_after = accumulate(stats)
1751 pkt_diff = pkts_after - pkts_before
1752 byte_diff = bytes_after - bytes_before
1753 if (pkts == None or pkt_diff >= pkts) and \
1754 (bytes == None or byte_diff >= bytes):
1755 break
Dan Talayco53724732013-03-08 23:54:02 -08001756 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001757
1758 if pkts != None:
1759 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1760
1761 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001762 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1763 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001764
Rich Lane4c504f32013-06-07 17:24:14 -07001765def packet_in_match(msg, data, in_port=None, reason=None):
1766 """
1767 Check whether the packet_in message 'msg' has fields matching 'data',
1768 'in_port', and 'reason'.
1769
1770 This function handles truncated packet_in data. The 'in_port' and 'reason'
1771 parameters are optional.
1772
1773 @param msg packet_in message
1774 @param data Expected packet_in data
1775 @param in_port Expected packet_in in_port, or None
1776 @param reason Expected packet_in reason, or None
1777 """
1778
Rich Lanec0d26dd2013-07-10 12:46:03 -07001779 if ofp.OFP_VERSION <= 2:
1780 pkt_in_port = msg.in_port
1781 else:
1782 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1783 if ofp.oxm.in_port in oxms:
1784 pkt_in_port = oxms[ofp.oxm.in_port].value
1785 else:
1786 logging.warn("Missing in_port in packet-in message")
1787 pkt_in_port = None
1788
1789 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001790 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001791 return False
1792
Rich Lanec0d26dd2013-07-10 12:46:03 -07001793 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001794 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1795 return False
1796
1797 # Check that one of the packets is a prefix of the other.
1798 # The received packet may be either truncated or padded, but not both.
1799 # (Some of the padding may be truncated but that's irrelevant). We
1800 # need to check that the smaller packet is a prefix of the larger one.
1801 # Note that this check succeeds if the switch sends a zero-length
1802 # packet-in.
1803 compare_len = min(len(msg.data), len(data))
1804 if data[:compare_len] != msg.data[:compare_len]:
1805 logging.debug("Incorrect packet_in data")
1806 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1807 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1808 return False
1809
1810 return True
1811
1812def verify_packet_in(test, data, in_port, reason, controller=None):
1813 """
1814 Assert that the controller receives a packet_in message matching data 'data'
1815 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1816 itself, that's up to the test case.
1817
1818 @param test Instance of base_tests.SimpleProtocol
1819 @param pkt String to expect as the packet_in data
1820 @param in_port OpenFlow port number to expect as the packet_in in_port
1821 @param reason One of OFPR_* to expect as the packet_in reason
1822 @param controller Controller instance, defaults to test.controller
1823 @returns The received packet-in message
1824 """
1825
1826 if controller == None:
1827 controller = test.controller
1828
1829 end_time = time.time() + oftest.ofutils.default_timeout
1830
1831 while True:
1832 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1833 if not msg:
1834 # Timeout
1835 break
1836 elif packet_in_match(msg, data, in_port, reason):
1837 # Found a matching message
1838 break
1839
Kiran Poola58c5c042014-05-15 15:11:06 -07001840 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001841 return msg
1842
1843def verify_no_packet_in(test, data, in_port, controller=None):
1844 """
1845 Assert that the controller does not receive a packet_in message matching
1846 data 'data' from port 'in_port'.
1847
1848 @param test Instance of base_tests.SimpleProtocol
1849 @param pkt String to expect as the packet_in data
1850 @param in_port OpenFlow port number to expect as the packet_in in_port
1851 @param controller Controller instance, defaults to test.controller
1852 """
1853
1854 if controller == None:
1855 controller = test.controller
1856
1857 # Negative test, need to wait a short amount of time before checking we
1858 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001859 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001860
1861 # Check every packet_in queued in the controller
1862 while True:
1863 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1864 if msg == None:
1865 # No more queued packet_in messages
1866 break
1867 elif packet_in_match(msg, data, in_port, None):
1868 # Found a matching message
1869 break
1870
Rich Lane82c882d2013-08-09 17:13:52 -07001871 if in_port == None:
1872 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1873 else:
1874 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001875
Rich Lane045db072013-08-06 13:16:30 -07001876def openflow_ports(num=None):
1877 """
1878 Return a list of 'num' OpenFlow port numbers
1879
1880 If 'num' is None, return all available ports. Otherwise, limit the length
1881 of the result to 'num' and raise an exception if not enough ports are
1882 available.
1883 """
1884 ports = sorted(oftest.config["port_map"].keys())
1885 if num != None and len(ports) < num:
1886 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
1887 return ports[:num]
1888
Rich Lanee4b384d2013-09-13 14:33:40 -07001889def verify_packet(test, pkt, ofport):
1890 """
1891 Check that an expected packet is received
1892 """
1893 logging.debug("Checking for pkt on port %r", ofport)
1894 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
1895 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08001896 return (rcv_port, rcv_pkt, pkt_time)
1897
Rich Lanee4b384d2013-09-13 14:33:40 -07001898def verify_no_packet(test, pkt, ofport):
1899 """
1900 Check that a particular packet is not received
1901 """
1902 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07001903 (rcv_port, rcv_pkt, pkt_time) = \
1904 test.dataplane.poll(
1905 port_number=ofport, exp_pkt=str(pkt),
1906 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001907 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
1908
1909def verify_no_other_packets(test):
1910 """
1911 Check that no unexpected packets are received
1912
1913 This is a no-op if the --relax option is in effect.
1914 """
1915 if oftest.config["relax"]:
1916 return
1917 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07001918 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001919 if rcv_pkt != None:
1920 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
1921 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
1922
1923def verify_packets(test, pkt, ofports):
1924 """
1925 Check that a packet is received on certain ports
1926
1927 Also verifies that the packet is not received on any other ports, and that no
1928 other packets are received (unless --relax is in effect).
1929
1930 This covers the common and simplest cases for checking dataplane outputs.
1931 For more complex usage, like multiple different packets being output, or
1932 multiple packets on the same port, use the primitive verify_packet,
1933 verify_no_packet, and verify_no_other_packets functions directly.
1934 """
1935 pkt = str(pkt)
1936 for ofport in openflow_ports():
1937 if ofport in ofports:
1938 verify_packet(test, pkt, ofport)
1939 else:
1940 verify_no_packet(test, pkt, ofport)
1941 verify_no_other_packets(test)
1942
Rich Lane12d04592013-10-10 17:21:07 -07001943def verify_no_errors(ctrl):
1944 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
1945 if error:
1946 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07001947
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001948def verify_capability(test, capability):
1949 """
Jonathan Stout073642d2014-02-04 13:41:48 -05001950 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001951
1952 @param test Instance of base_tests.SimpleProtocol
1953 @param capability One of ofp_capabilities.
1954 """
1955 logging.info("Verifing that capability code is valid.")
1956 test.assertIn(capability, ofp.const.ofp_capabilities_map,
1957 "Capability code %d does not exist." % capability)
1958 capability_str = ofp.const.ofp_capabilities_map[capability]
1959
1960 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05001961 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001962 req = ofp.message.features_request()
1963 res, raw = test.controller.transact(req)
1964 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
1965 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
1966 ("Unexpected packet type %d received in response to "
1967 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05001968 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001969
Jonathan Stout641167f2014-02-04 12:07:10 -05001970 if (res.capabilities & capability) > 0:
1971 logging.info("Switch capabilities bitmask claims to support %s",
1972 capability_str)
1973 return True, res.capabilities
1974 else:
1975 logging.info("Capabilities bitmask does not support %s.",
1976 capability_str)
1977 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001978
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001979def verify_configuration_flag(test, flag):
1980 """
1981 Return True if DUT supports specified configuration flag.
1982
1983 @param test Instance of base_tests.SimpleProtocol
1984 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05001985 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001986 """
1987 logging.info("Verifing that flag is valid.")
1988 test.assertIn(flag, ofp.const.ofp_config_flags_map,
1989 "flag %s does not exist." % flag)
1990 flag_str = ofp.const.ofp_config_flags_map[flag]
1991
1992 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
1993 req = ofp.message.get_config_request()
1994 rv = test.controller.message_send(req)
1995 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
1996
1997 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
1998 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
1999 timeout=2)
2000 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2001 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2002
2003 if res.flags == flag:
2004 logging.info("%s flag is set.", flag_str)
2005 return True, res.flags
2006 else:
2007 logging.info("%s flag is not set.", flag_str)
2008 return False, res.flags
2009
Rich Lane7744e112013-01-11 17:23:57 -08002010__all__ = list(set(locals()) - _import_blacklist)