blob: 1d48c60595815d51ccb173d3945cf3460b6a146a [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()):
Pier23784aa2016-09-19 20:08:21 -070072 group_id = group_queue.get()
73 print "0x%x" % group_id
74 msg = ofp.message.group_delete(group_id=group_id)
Flavio Castro1c9b1252016-02-04 18:42:58 -050075 ctrl.message_send(msg)
76 do_barrier(ctrl)
77
Ed Swierk99a74de2012-08-22 06:40:54 -070078def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070079 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070080 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -070081 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
82 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -070083 else:
84 return 0
85
macauley_cheng0a0a7f62015-11-06 11:36:50 +080086def simple_packet(content='00 00 00 11 33 55 00 00 00 11 22 33 81 00 00 03 '
87 '08 00 45 00 00 2e 04 d2 00 00 7f 00 b2 47 c0 a8 '
88 '01 64 c0 a8 02 02 00 00 00 00 00 00 00 00 00 00 '
89 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'):
macauley_cheng739f54b2015-11-09 13:52:59 +080090
91 pkt = ''.join(content.split(" ")).decode('hex')
macauley_chengc80249d2015-11-09 14:11:18 +080092 pkt = scapy.Ether(pkt)
macauley_cheng739f54b2015-11-09 13:52:59 +080093 if len(pkt) < 64:
94 pkt = pkt/("D" * (64 - len(pkt)))
macauley_chengc80249d2015-11-09 14:11:18 +080095 #scapy.hexdump(pkt)
macauley_cheng0a0a7f62015-11-06 11:36:50 +080096 return pkt
97
Dan Talayco41eae8b2010-03-10 13:57:06 -080098def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -070099 eth_dst='00:01:02:03:04:05',
100 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700101 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700102 vlan_vid=0,
103 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700104 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800105 ip_src='192.168.0.1',
106 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700107 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800108 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800109 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700110 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700111 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700112 ip_ihl=None,
113 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800114 ):
115 """
116 Return a simple dataplane TCP packet
117
118 Supports a few parameters:
119 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700120 @param eth_dst Destinatino MAC
121 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700122 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700123 @param vlan_vid VLAN ID
124 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800125 @param ip_src IP source
126 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700127 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800128 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800129 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700130 @param tcp_sport TCP source port
131 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800132
133 Generates a simple TCP request. Users
134 shouldn't assume anything about this packet other than that
135 it is a valid ethernet/IP/TCP frame.
136 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000137
138 if MINSIZE > pktlen:
139 pktlen = MINSIZE
140
Dan Talayco551befa2010-07-15 17:05:32 -0700141 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800142 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700143 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
144 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800145 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700146 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700147 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700148 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700149 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800150 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700151 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700152 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700153 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800154 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 -0700155 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700156
Dan Talayco41eae8b2010-03-10 13:57:06 -0800157 pkt = pkt/("D" * (pktlen - len(pkt)))
158
159 return pkt
160
Rich Lane86aceb02013-07-17 18:45:38 -0700161def simple_tcpv6_packet(pktlen=100,
162 eth_dst='00:01:02:03:04:05',
163 eth_src='00:06:07:08:09:0a',
164 dl_vlan_enable=False,
165 vlan_vid=0,
166 vlan_pcp=0,
167 ipv6_src='2001:db8:85a3::8a2e:370:7334',
168 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
169 ipv6_tc=0,
170 ipv6_hlim=64,
171 ipv6_fl=0,
172 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700173 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700174 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700175 """
176 Return a simple IPv6/TCP packet
177
178 Supports a few parameters:
179 @param len Length of packet in bytes w/o CRC
180 @param eth_dst Destination MAC
181 @param eth_src Source MAC
182 @param dl_vlan_enable True if the packet is with vlan, False otherwise
183 @param vlan_vid VLAN ID
184 @param vlan_pcp VLAN priority
185 @param ipv6_src IPv6 source
186 @param ipv6_dst IPv6 destination
187 @param ipv6_tc IPv6 traffic class
188 @param ipv6_ttl IPv6 hop limit
189 @param ipv6_fl IPv6 flow label
190 @param tcp_dport TCP destination port
191 @param tcp_sport TCP source port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700192 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700193
194 Generates a simple TCP request. Users shouldn't assume anything about this
195 packet other than that it is a valid ethernet/IPv6/TCP frame.
196 """
197
198 if MINSIZE > pktlen:
199 pktlen = MINSIZE
200
201 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
202 if dl_vlan_enable or vlan_vid or vlan_pcp:
203 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
204 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 -0700205 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700206 pkt /= ("D" * (pktlen - len(pkt)))
207
208 return pkt
209
Rich Lane6ee7bea2012-10-26 16:19:29 -0700210def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700211 eth_dst='00:01:02:03:04:05',
212 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700213 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700214 vlan_vid=0,
215 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700216 dl_vlan_cfi=0,
217 ip_src='192.168.0.1',
218 ip_dst='192.168.0.2',
219 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800220 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700221 udp_sport=1234,
222 udp_dport=80,
223 ip_ihl=None,
224 ip_options=False
225 ):
226 """
227 Return a simple dataplane UDP packet
228
229 Supports a few parameters:
230 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700231 @param eth_dst Destination MAC
232 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700233 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700234 @param vlan_vid VLAN ID
235 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700236 @param ip_src IP source
237 @param ip_dst IP destination
238 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800239 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700240 @param udp_dport UDP destination port
241 @param udp_sport UDP source port
242
243 Generates a simple UDP packet. Users shouldn't assume anything about
244 this packet other than that it is a valid ethernet/IP/UDP frame.
245 """
246
247 if MINSIZE > pktlen:
248 pktlen = MINSIZE
249
250 # Note Dot1Q.id is really CFI
251 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700252 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
253 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800254 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700255 scapy.UDP(sport=udp_sport, dport=udp_dport)
256 else:
257 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700258 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800259 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700260 scapy.UDP(sport=udp_sport, dport=udp_dport)
261 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700262 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800263 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 -0700264 scapy.UDP(sport=udp_sport, dport=udp_dport)
265
266 pkt = pkt/("D" * (pktlen - len(pkt)))
267
268 return pkt
269
macauley_chengb0ec33d2015-09-04 11:32:44 +0800270
271def simple_tcp_packet_two_vlan(pktlen=100,
272 eth_dst='00:01:02:03:04:05',
273 eth_src='00:06:07:08:09:0a',
274 out_dl_vlan_enable=False,
275 in_dl_vlan_enable=False,
276 out_vlan_vid=0,
277 out_vlan_pcp=0,
278 out_dl_vlan_cfi=0,
279 in_vlan_vid=0,
280 in_vlan_pcp=0,
281 in_dl_vlan_cfi=0,
282 ip_src='192.168.0.1',
283 ip_dst='192.168.0.2',
284 ip_tos=0,
285 ip_ttl=64,
286 tcp_sport=1234,
287 tcp_dport=80,
288 tcp_flags="S",
289 ip_ihl=None,
290 ip_options=False
291 ):
292 """
293 Return a simple dataplane TCP packet
294
295 Supports a few parameters:
296 @param len Length of packet in bytes w/o CRC
297 @param eth_dst Destinatino MAC
298 @param eth_src Source MAC
299 @param dl_vlan_enable True if the packet is with vlan, False otherwise
300 @param vlan_vid VLAN ID
301 @param vlan_pcp VLAN priority
302 @param ip_src IP source
303 @param ip_dst IP destination
304 @param ip_tos IP ToS
305 @param ip_ttl IP TTL
306 @param tcp_dport TCP destination port
307 @param tcp_sport TCP source port
308 @param tcp_flags TCP Control flags
309
310 Generates a simple TCP request. Users
311 shouldn't assume anything about this packet other than that
312 it is a valid ethernet/IP/TCP frame.
313 """
314
315 if MINSIZE > pktlen:
316 pktlen = MINSIZE
317
318 # Note Dot1Q.id is really CFI
319 if (out_dl_vlan_enable and in_dl_vlan_enable):
320 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
321 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
322
323 if in_dl_vlan_enable:
324 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
325
326 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
327 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
328 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
329 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
330 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
331 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
332 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
333 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
334 assert(0) #shall not have this caes
335 else:
336 if not ip_options:
337 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
338 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
339 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
340 else:
341 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
342 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
343 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
344
345 pkt = pkt/("D" * (pktlen - len(pkt)))
346
347 return pkt
348
macauley17cd60d2015-07-27 17:41:18 +0800349def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
350 eth_src='00:06:07:08:09:0a',
351 dl_vlan_enable=False,
352 vlan_vid=0,
353 vlan_pcp=0,
354 dl_vlan_cfi=0,
355 ip_src='192.168.0.1',
356 ip_dst='192.168.0.2',
357 ip_tos=0,
358 ip_ttl=64,
359 udp_sport=1234,
360 udp_dport=4789,
361 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800362 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800363 ip_ihl=None,
364 ip_options=False
365 ):
366 """
367 Return a simple dataplane UDP packet
368
369 Supports a few parameters:
370 @param len Length of packet in bytes w/o CRC
371 @param eth_dst Destination MAC
372 @param eth_src Source MAC
373 @param dl_vlan_enable True if the packet is with vlan, False otherwise
374 @param vlan_vid VLAN ID
375 @param vlan_pcp VLAN priority
376 @param ip_src IP source
377 @param ip_dst IP destination
378 @param ip_tos IP ToS
379 @param ip_ttl IP TTL
380 @param udp_dport UDP destination port
381 @param udp_sport UDP source port
382 @param inner_pyload inner pacekt content
383 Generates a simple UDP packet. Users shouldn't assume anything about
384 this packet other than that it is a valid ethernet/IP/UDP frame.
385 """
386
387 # Note Dot1Q.id is really CFI
388 if (dl_vlan_enable):
389 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
390 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
391 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
392 scapy.UDP(sport=udp_sport, dport=udp_dport)
393 else:
394 if not ip_options:
395 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
396 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
397 scapy.UDP(sport=udp_sport, dport=udp_dport)
398 else:
399 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
400 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
401 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800402
macauley17cd60d2015-07-27 17:41:18 +0800403 #add vxlan header
404 pkt = pkt/scapy.VXLAN(vni=vnid)
405 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800406 if inner_payload!=None:
407 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800408
409 return pkt
410
Flavio Castro72a45d52015-12-02 16:37:05 -0500411def mpls_packet(pktlen=100,
412 eth_dst='00:01:02:03:04:05',
413 eth_src='00:06:07:08:09:0a',
414 dl_vlan_enable=False,
415 vlan_vid=0,
416 vlan_pcp=0,
417 dl_vlan_cfi=0,
418 ip_src='192.168.0.1',
419 ip_dst='192.168.0.2',
420 ip_tos=0,
421 ip_ttl=64,
422 tcp_sport=1234,
423 tcp_dport=80,
424 tcp_flags="S",
425 ip_ihl=None,
426 ip_options=False,
427 label=None,
Flavio Castro167f5bd2015-12-02 19:33:53 -0500428 inner_payload=True
Flavio Castro72a45d52015-12-02 16:37:05 -0500429 ):
430 if MINSIZE > pktlen:
431 pktlen = MINSIZE
432
433 # Note Dot1Q.id is really CFI
434 if (dl_vlan_enable):
435 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
436 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
437 else:
438 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
439
440 #add MPLS header
441 for i in range(len(label)):
442 l,c,s,t=label[i]
443 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
444
445 #add innder payload
446 if inner_payload!=None:
447 pkt=pkt / \
448 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
449 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Flavio Castro167f5bd2015-12-02 19:33:53 -0500450
451 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500452
453 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800454
Pier23784aa2016-09-19 20:08:21 -0700455def pw_packet(pktlen=100,
456 out_eth_dst='00:01:02:03:04:05',
457 out_eth_src='00:06:07:08:09:0a',
458 label=None,
459 cw=None,
460 in_eth_dst='00:01:02:03:04:05',
461 in_eth_src='00:06:07:08:09:0a',
462 out_dl_vlan_enable=False,
463 in_dl_vlan_enable=False,
464 out_vlan_vid=0,
465 out_vlan_pcp=0,
466 out_dl_vlan_cfi=0,
467 in_vlan_vid=0,
468 in_vlan_pcp=0,
469 in_dl_vlan_cfi=0,
470 ip_src='192.168.0.1',
471 ip_dst='192.168.0.2',
472 ip_tos=0,
473 ip_ttl=64,
474 tcp_sport=1234,
475 tcp_dport=80,
476 tcp_flags="S",
477 ip_ihl=None,
478 ip_options=False
479 ):
480 """
481 Return a simple dataplane TCP packet encapsulated
482 in a pw packet
483 """
484
485 # Add the outer ethernet header
486 if MINSIZE > pktlen:
487 pktlen = MINSIZE
488
489 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
490
491 #add MPLS header
492 for i in range(len(label)):
493 l,c,s,t=label[i]
494 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
495
496 #add the PW CW
497 l,c,s,t=cw
498 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
499
500 # Note Dot1Q.id is really CFI
501 if (out_dl_vlan_enable and in_dl_vlan_enable):
502
503 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
504 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
505
506 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
507
508 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
509 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
510
511 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
512
513 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
514 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
515 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
516 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
517
518 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
519
520 assert(0) #shall not have this caes
521
522 else:
523 if not ip_options:
524 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
525 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
526 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
527 else:
528 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
529 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
530 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
531
532 pkt = pkt/("D" * (pktlen - len(pkt)))
533
534 return pkt
535
macauley_cheng45833df2015-08-31 15:19:07 +0800536def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
537 eth_src='00:06:07:08:09:0a',
538 dl_vlan_enable=False,
539 vlan_vid=0,
540 vlan_pcp=0,
541 dl_vlan_cfi=0,
542 label=None,
543 inner_payload=None
544 ):
545 """
546 Return a simple dataplane MPLS packet
547
548 Supports a few parameters:
549 @param len Length of packet in bytes w/o CRC
550 @param eth_dst Destination MAC
551 @param eth_src Source MAC
552 @param dl_vlan_enable True if the packet is with vlan, False otherwise
553 @param vlan_vid VLAN ID
554 @param vlan_pcp VLAN priority
555 @param inner_pyload inner pacekt content
556 Generates a simple MPLS packet. Users shouldn't assume anything about
557 this packet other than that it is a valid ethernet/IP/UDP frame.
558 """
559
560 # Note Dot1Q.id is really CFI
561 if (dl_vlan_enable):
562 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
563 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
564 else:
565 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
566
567 #add MPLS header
568 for i in range(len(label)):
569 l,c,s,t=label[i]
570 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
571
572 #add innder payload
573 if inner_payload!=None:
574 pkt=pkt/inner_payload
575
576 return pkt
577
Rich Lane86aceb02013-07-17 18:45:38 -0700578def simple_udpv6_packet(pktlen=100,
579 eth_dst='00:01:02:03:04:05',
580 eth_src='00:06:07:08:09:0a',
581 dl_vlan_enable=False,
582 vlan_vid=0,
583 vlan_pcp=0,
584 ipv6_src='2001:db8:85a3::8a2e:370:7334',
585 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
586 ipv6_tc=0,
587 ipv6_hlim=64,
588 ipv6_fl=0,
589 udp_sport=1234,
590 udp_dport=80):
591 """
592 Return a simple IPv6/UDP packet
593
594 Supports a few parameters:
595 @param len Length of packet in bytes w/o CRC
596 @param eth_dst Destination MAC
597 @param eth_src Source MAC
598 @param dl_vlan_enable True if the packet is with vlan, False otherwise
599 @param vlan_vid VLAN ID
600 @param vlan_pcp VLAN priority
601 @param ipv6_src IPv6 source
602 @param ipv6_dst IPv6 destination
603 @param ipv6_tc IPv6 traffic class
604 @param ipv6_ttl IPv6 hop limit
605 @param ipv6_fl IPv6 flow label
606 @param udp_dport UDP destination port
607 @param udp_sport UDP source port
608
609 Generates a simple UDP request. Users shouldn't assume anything about this
610 packet other than that it is a valid ethernet/IPv6/UDP frame.
611 """
612
613 if MINSIZE > pktlen:
614 pktlen = MINSIZE
615
616 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
617 if dl_vlan_enable or vlan_vid or vlan_pcp:
618 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
619 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
620 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
621 pkt /= ("D" * (pktlen - len(pkt)))
622
623 return pkt
624
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700625def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700626 eth_dst='00:01:02:03:04:05',
627 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700628 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700629 vlan_vid=0,
630 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700631 ip_src='192.168.0.1',
632 ip_dst='192.168.0.2',
633 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800634 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600635 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700636 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600637 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600638 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700639 """
640 Return a simple ICMP packet
641
642 Supports a few parameters:
643 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700644 @param eth_dst Destinatino MAC
645 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700646 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700647 @param vlan_vid VLAN ID
648 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700649 @param ip_src IP source
650 @param ip_dst IP destination
651 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800652 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600653 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700654 @param icmp_type ICMP type
655 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600656 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700657
658 Generates a simple ICMP ECHO REQUEST. Users
659 shouldn't assume anything about this packet other than that
660 it is a valid ethernet/ICMP frame.
661 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000662
663 if MINSIZE > pktlen:
664 pktlen = MINSIZE
665
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700666 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700667 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
668 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600669 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600670 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700671 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700672 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600673 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600674 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700675
676 pkt = pkt/("0" * (pktlen - len(pkt)))
677
678 return pkt
679
Rich Lane86aceb02013-07-17 18:45:38 -0700680def simple_icmpv6_packet(pktlen=100,
681 eth_dst='00:01:02:03:04:05',
682 eth_src='00:06:07:08:09:0a',
683 dl_vlan_enable=False,
684 vlan_vid=0,
685 vlan_pcp=0,
686 ipv6_src='2001:db8:85a3::8a2e:370:7334',
687 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
688 ipv6_tc=0,
689 ipv6_hlim=64,
690 ipv6_fl=0,
691 icmp_type=8,
692 icmp_code=0):
693 """
694 Return a simple ICMPv6 packet
695
696 Supports a few parameters:
697 @param len Length of packet in bytes w/o CRC
698 @param eth_dst Destination MAC
699 @param eth_src Source MAC
700 @param dl_vlan_enable True if the packet is with vlan, False otherwise
701 @param vlan_vid VLAN ID
702 @param vlan_pcp VLAN priority
703 @param ipv6_src IPv6 source
704 @param ipv6_dst IPv6 destination
705 @param ipv6_tc IPv6 traffic class
706 @param ipv6_ttl IPv6 hop limit
707 @param ipv6_fl IPv6 flow label
708 @param icmp_type ICMP type
709 @param icmp_code ICMP code
710
711 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
712 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
713 """
714
715 if MINSIZE > pktlen:
716 pktlen = MINSIZE
717
718 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
719 if dl_vlan_enable or vlan_vid or vlan_pcp:
720 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
721 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
722 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
723 pkt /= ("D" * (pktlen - len(pkt)))
724
725 return pkt
726
Shudong Zhouc7562b12013-02-06 01:12:18 -0800727def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700728 eth_dst='ff:ff:ff:ff:ff:ff',
729 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800730 vlan_vid=0,
731 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800732 arp_op=1,
733 ip_snd='192.168.0.1',
734 ip_tgt='192.168.0.2',
735 hw_snd='00:06:07:08:09:0a',
736 hw_tgt='00:00:00:00:00:00',
737 ):
738 """
739 Return a simple ARP packet
740
741 Supports a few parameters:
742 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700743 @param eth_dst Destinatino MAC
744 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800745 @param arp_op Operation (1=request, 2=reply)
746 @param ip_snd Sender IP
747 @param ip_tgt Target IP
748 @param hw_snd Sender hardware address
749 @param hw_tgt Target hardware address
750
751 Generates a simple ARP REQUEST. Users
752 shouldn't assume anything about this packet other than that
753 it is a valid ethernet/ARP frame.
754 """
755
756 if MINSIZE > pktlen:
757 pktlen = MINSIZE
758
Rich Lanee01611f2014-01-15 14:55:11 -0800759 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
760 if vlan_vid or vlan_pcp:
761 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
762 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 -0800763
Rich Laned459ce52014-01-24 12:09:54 -0800764 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800765
766 return pkt
767
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700768def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800769 eth_dst='00:01:02:03:04:05',
770 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700771 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000772
773 if MINSIZE > pktlen:
774 pktlen = MINSIZE
775
Rich Laned0478ff2013-03-11 12:46:58 -0700776 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700777
778 pkt = pkt/("0" * (pktlen - len(pkt)))
779
780 return pkt
781
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800782def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700783 eth_dst='00:01:02:03:04:05',
784 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800785 dl_vlan_outer=20,
786 dl_vlan_pcp_outer=0,
787 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700788 vlan_vid=10,
789 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800790 dl_vlan_cfi=0,
791 ip_src='192.168.0.1',
792 ip_dst='192.168.0.2',
793 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800794 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800795 tcp_sport=1234,
796 tcp_dport=80,
797 ip_ihl=None,
798 ip_options=False
799 ):
800 """
801 Return a doubly tagged dataplane TCP packet
802
803 Supports a few parameters:
804 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700805 @param eth_dst Destinatino MAC
806 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800807 @param dl_vlan_outer Outer VLAN ID
808 @param dl_vlan_pcp_outer Outer VLAN priority
809 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700810 @param vlan_vid Inner VLAN ID
811 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800812 @param dl_vlan_cfi VLAN cfi bit
813 @param ip_src IP source
814 @param ip_dst IP destination
815 @param ip_tos IP ToS
816 @param tcp_dport TCP destination port
817 @param ip_sport TCP source port
818
819 Generates a TCP request. Users
820 shouldn't assume anything about this packet other than that
821 it is a valid ethernet/IP/TCP frame.
822 """
823
824 if MINSIZE > pktlen:
825 pktlen = MINSIZE
826
827 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700828 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800829 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700830 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800831 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800832 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
833
834 pkt = pkt/("D" * (pktlen - len(pkt)))
835
836 return pkt
837
Shudong Zhoub7f12462012-11-20 13:01:12 -0800838def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700839 """
840 Do a barrier command
841 Return 0 on success, -1 on error
842 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700843 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800844 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800845 if resp is None:
846 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700847 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800848 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700849
Rich Lane9a003812012-10-04 17:17:59 -0700850def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700851 """
852 Get a port's configuration
853
854 Gets the switch feature configuration and grabs one port's
855 configuration
856
857 @returns (hwaddr, config, advert) The hwaddress, configuration and
858 advertised values
859 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700860
861 if ofp.OFP_VERSION <= 3:
862 request = ofp.message.features_request()
863 reply, _ = controller.transact(request)
864 if reply is None:
865 logging.warn("Get feature request failed")
866 return None, None, None
867 logging.debug(reply.show())
868 ports = reply.ports
869 else:
870 request = ofp.message.port_desc_stats_request()
871 # TODO do multipart correctly
872 reply, _ = controller.transact(request)
873 if reply is None:
874 logging.warn("Port desc stats request failed")
875 return None, None, None
876 logging.debug(reply.show())
877 ports = reply.entries
878
879 for port in ports:
880 if port.port_no == port_no:
881 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700882
Rich Lane9a003812012-10-04 17:17:59 -0700883 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700884 return None, None, None
885
Rich Lane9a003812012-10-04 17:17:59 -0700886def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700887 """
888 Set the port configuration according the given parameters
889
890 Gets the switch feature configuration and updates one port's
891 configuration value according to config and mask
892 """
Rich Lane9a003812012-10-04 17:17:59 -0700893 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700894
895 hw_addr, _, _ = port_config_get(controller, port_no)
896
Rich Lanee717c6e2013-03-12 10:25:50 -0700897 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700898 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700899 if hw_addr != None:
900 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700901 mod.config = config
902 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700903 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800904 controller.message_send(mod)
905 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700906
Rich Lane2014f9b2012-10-05 15:29:40 -0700907def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700908 """
909 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700910 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700911 @param pkt Expected packet; may be None if yes_ports is empty
912 @param yes_ports Set or list of ports that should recieve packet
913 @param no_ports Set or list of ports that should not receive packet
914 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700915
916 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700917 """
Rich Lane91765672012-12-06 16:33:04 -0800918
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700919 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800920 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700921 exp_pkt_arg = pkt
922
Dan Talayco92c99122010-06-03 13:53:18 -0700923 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700924 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700925 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800926 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700927 assert_if.assertTrue(rcv_pkt is not None,
928 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800929 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800930 logging.debug("Expected %s" % format_packet(pkt))
931 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800932 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800933 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700934 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700935 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700936 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700937 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700938 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700939 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800940 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700941 assert_if.assertTrue(rcv_pkt is None,
942 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700943
944
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700945def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700946 """
947 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700948 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700949
950 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700951
952 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700953 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700954 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800955 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700956 exp_pkt_arg = exp_pkt
957
Dan Talaycof6e76c02012-03-23 10:56:12 -0700958 if type(egr_ports) == type([]):
959 egr_port_list = egr_ports
960 else:
961 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700962
Dan Talaycof6e76c02012-03-23 10:56:12 -0700963 # Expect a packet from each port on egr port list
964 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700965 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -0700966 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700967 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700968 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700969 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700970
Dan Talaycof6e76c02012-03-23 10:56:12 -0700971 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700972 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700973 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700974
Dan Talaycof6e76c02012-03-23 10:56:12 -0700975 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700976 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700977 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700978 str(rcv_port))
979
980 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700981 logging.error("ERROR: Packet match failed.")
982 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700983 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700984 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700985 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700986 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
987 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700988 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700989 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700990
Dan Talayco551befa2010-07-15 17:05:32 -0700991def match_verify(parent, req_match, res_match):
992 """
993 Verify flow matches agree; if they disagree, report where
994
995 parent must implement assertEqual
996 Use str() to ensure content is compared and not pointers
997 """
998
999 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1000 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1001 " != " + hex(res_match.wildcards))
1002 parent.assertEqual(req_match.in_port, res_match.in_port,
1003 'Match failed: in_port: ' + str(req_match.in_port) +
1004 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001005 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1006 'Match failed: eth_src: ' + str(req_match.eth_src) +
1007 " != " + str(res_match.eth_src))
1008 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1009 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1010 " != " + str(res_match.eth_dst))
1011 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1012 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1013 " != " + str(res_match.vlan_vid))
1014 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
1015 'Match failed: vlan_pcp: ' +
1016 str(req_match.vlan_pcp) + " != " +
1017 str(res_match.vlan_pcp))
1018 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1019 'Match failed: eth_type: ' + str(req_match.eth_type) +
1020 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001021
Rich Lanee717c6e2013-03-12 10:25:50 -07001022 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001023 and (req_match.eth_type == IP_ETHERTYPE)):
1024 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1025 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1026 " != " + str(res_match.ip_dscp))
1027 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1028 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1029 " != " + str(res_match.ip_proto))
1030 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1031 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1032 " != " + str(res_match.ipv4_src))
1033 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1034 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1035 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001036
Rich Lanee717c6e2013-03-12 10:25:50 -07001037 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001038 and ((req_match.ip_proto == TCP_PROTOCOL)
1039 or (req_match.ip_proto == UDP_PROTOCOL))):
1040 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
1041 'Match failed: tcp_src: ' +
1042 str(req_match.tcp_src) +
1043 " != " + str(res_match.tcp_src))
1044 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
1045 'Match failed: tcp_dst: ' +
1046 str(req_match.tcp_dst) +
1047 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001048
Ed Swierk99a74de2012-08-22 06:40:54 -07001049def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001050 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001051 if ofp.OFP_VERSION in [1, 2]:
1052 match.wildcards |= required_wildcards(parent)
1053 else:
1054 # TODO remove incompatible OXM entries
1055 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001056 return match
1057
1058def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001059 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001060 """
1061 Create a flow message
1062
1063 Match on packet with given wildcards.
1064 See flow_match_test for other parameter descriptoins
1065 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001066 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001067 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001068 """
Rich Lanef6883512013-03-11 17:00:09 -07001069 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001070 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001071 if wildcards is None:
1072 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001073 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001074 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001075 match.wildcards = wildcards
1076 match.in_port = ing_port
1077
Dan Talaycof6e76c02012-03-23 10:56:12 -07001078 if type(egr_ports) == type([]):
1079 egr_port_list = egr_ports
1080 else:
1081 egr_port_list = [egr_ports]
1082
Rich Lanee717c6e2013-03-12 10:25:50 -07001083 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001084 request.match = match
1085 request.buffer_id = 0xffffffff
1086 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001087 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001088 request.hard_timeout = 1
1089
Rich Lane400fb9b2013-10-10 17:20:54 -07001090 if ofp.OFP_VERSION == 1:
1091 actions = request.actions
1092 else:
1093 actions = []
1094 request.instructions.append(ofp.instruction.apply_actions(actions))
1095
Dan Talayco551befa2010-07-15 17:05:32 -07001096 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001097 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001098
1099 # Set up output/enqueue action if directed
1100 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001101 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001102 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001103 for egr_port in egr_port_list:
1104 act.port = egr_port
1105 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001106 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001107 elif egr_ports is not None:
1108 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001109 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001110 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001111 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001112
Rich Lane9a003812012-10-04 17:17:59 -07001113 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001114
1115 return request
1116
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001117def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001118 """
1119 Install a flow mod message in the switch
1120
1121 @param parent Must implement controller, assertEqual, assertTrue
1122 @param request The request, all set to go
1123 @param clear_table If true, clear the flow table before installing
1124 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001125
Rich Lane2014f9b2012-10-05 15:29:40 -07001126 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001127 if(clear_table_override != None):
1128 clear_table = clear_table_override
1129
1130 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001131 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001132 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001133
Rich Lane9a003812012-10-04 17:17:59 -07001134 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001135 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001136
Rich Lane3a261d52013-01-03 17:45:08 -08001137 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001138
Ed Swierk99a74de2012-08-22 06:40:54 -07001139def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001140 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001141 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001142 """
1143 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001144 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001145
1146 Run test with packet through switch from ing_port to egr_port
1147 See flow_match_test for parameter descriptions
1148 """
1149
Ed Swierk99a74de2012-08-22 06:40:54 -07001150 if wildcards is None:
1151 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001152 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001153 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001154 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001155 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001156 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001157 if exp_pkt is None:
1158 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001159
1160 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001161 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001162 action_list=action_list)
1163
1164 flow_msg_install(parent, request)
1165
Rich Lane9a003812012-10-04 17:17:59 -07001166 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001167 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001168 parent.dataplane.send(ing_port, str(pkt))
1169
Rich Lane8f45e2d2013-10-01 16:06:54 -07001170 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001171 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001172
Rich Lane89725bb2012-12-03 16:23:27 -08001173def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001174 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001175 action_list=None):
1176 """
1177 Packet-out test on single TCP packet
1178 @param egr_ports A single port or list of ports
1179
1180 Run test sending packet-out to egr_ports. The goal is to test the actions
1181 taken on the packet, not the matching which is of course irrelevant.
1182 See flow_match_test for parameter descriptions
1183 """
1184
1185 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001186 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001187 if exp_pkt is None:
1188 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001189
Rich Lanee717c6e2013-03-12 10:25:50 -07001190 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001191 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001192 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001193 msg.data = str(pkt)
1194 if action_list is not None:
1195 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001196 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001197
1198 # Set up output action
1199 if egr_ports is not None:
1200 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001201 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001202 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001203 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001204
1205 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001206 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001207
Rich Lane8f45e2d2013-10-01 16:06:54 -07001208 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001209 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001210
Dan Talaycof6e76c02012-03-23 10:56:12 -07001211def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1212 """
1213 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001214 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001215 @param of_ports List of OF port numbers
1216 @param how_many Number of ports to be added to the list
1217 @param exclude_list List of ports not to be used
1218 @returns An empty list if unable to find enough ports
1219 """
1220
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001221 if how_many == 0:
1222 return []
1223
Dan Talaycof6e76c02012-03-23 10:56:12 -07001224 count = 0
1225 egr_ports = []
1226 for egr_idx in range(len(of_ports)):
1227 if of_ports[egr_idx] not in exclude_list:
1228 egr_ports.append(of_ports[egr_idx])
1229 count += 1
1230 if count >= how_many:
1231 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001232 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001233 return []
1234
Rich Laned0478ff2013-03-11 12:46:58 -07001235def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001236 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001237 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001238 """
Rich Lane89725bb2012-12-03 16:23:27 -08001239 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001240
1241 @param max_test If > 0 no more than this number of tests are executed.
1242 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001243 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001244 @param pkt If not None, use this packet for ingress
1245 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001246 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001247 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1248 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001249 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001250 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001251 if wildcards is None:
1252 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001253 of_ports = port_map.keys()
1254 of_ports.sort()
1255 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1256 test_count = 0
1257
Dan Talaycocfa172f2012-03-23 12:03:00 -07001258 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001259 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001260
Dan Talayco551befa2010-07-15 17:05:32 -07001261 for ing_idx in range(len(of_ports)):
1262 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001263 egr_ports = get_egr_list(parent, of_ports, egr_count,
1264 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001265 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001266 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001267 if len(egr_ports) == 0:
1268 parent.assertTrue(0, "Failed to generate egress port list")
1269
1270 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001271 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001272 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001273 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001274 test_count += 1
1275 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001276 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001277 break
1278
Ed Swierk38eea082013-01-02 19:46:20 -08001279 if not test_param_get('pktout_actions', default=True):
1280 return
Rich Lane89725bb2012-12-03 16:23:27 -08001281
1282 ingress_port = of_ports[0]
1283 egr_ports = get_egr_list(parent, of_ports, egr_count,
1284 exclude_list=[ingress_port])
1285 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001286 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001287 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001288 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001289 pkt=pkt, exp_pkt=exp_pkt,
1290 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001291
Rich Lane2014f9b2012-10-05 15:29:40 -07001292def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001293 """
1294 Return value passed via test-params if present
1295
Dan Talayco4b2bee62010-07-20 14:10:05 -07001296 @param key The lookup key
1297 @param default Default value to use if not found
1298
1299 If the pair 'key=val' appeared in the string passed to --test-params
1300 on the command line, return val (as interpreted by exec). Otherwise
1301 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001302
1303 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1304 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001305 """
1306 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001307 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001308 except:
1309 return default
1310
Dan Talayco4b2bee62010-07-20 14:10:05 -07001311 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001312 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001313 except:
1314 return default
1315
1316def action_generate(parent, field_to_mod, mod_field_vals):
1317 """
1318 Create an action to modify the field indicated in field_to_mod
1319
1320 @param parent Must implement, assertTrue
1321 @param field_to_mod The field to modify as a string name
1322 @param mod_field_vals Hash of values to use for modified values
1323 """
1324
1325 act = None
1326
1327 if field_to_mod in ['pktlen']:
1328 return None
1329
Rich Laned0478ff2013-03-11 12:46:58 -07001330 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001331 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001332 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001333 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001334 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001335 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001336 elif field_to_mod == 'dl_vlan_enable':
1337 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001338 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001339 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001340 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001341 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001342 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001343 act.vlan_vid = mod_field_vals['vlan_vid']
1344 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001345 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001346 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001347 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001348 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001349 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001350 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001351 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001352 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001353 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001354 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001355 act.nw_tos = mod_field_vals['ip_tos']
1356 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001357 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001358 act.tp_port = mod_field_vals['tcp_sport']
1359 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001360 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001361 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001362 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001363 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001364 act.tp_port = mod_field_vals['udp_sport']
1365 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001366 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001367 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001368 else:
1369 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1370
1371 return act
1372
1373def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001374 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001375 """
1376 Set up the ingress and expected packet and action list for a test
1377
Rich Lane2014f9b2012-10-05 15:29:40 -07001378 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001379 @param start_field_values Field values to use for ingress packet (optional)
1380 @param mod_field_values Field values to use for modified packet (optional)
1381 @param mod_fields The list of fields to be modified by the switch in the test.
1382 @params check_test_params If True, will check the parameters vid, add_vlan
1383 and strip_vlan from the command line.
1384
1385 Returns a triple: pkt-to-send, expected-pkt, action-list
1386 """
1387
1388 new_actions = []
1389
Dan Talayco4b2bee62010-07-20 14:10:05 -07001390 base_pkt_params = {}
1391 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001392 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1393 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001394 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001395 base_pkt_params['vlan_vid'] = 2
1396 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001397 base_pkt_params['ip_src'] = '192.168.0.1'
1398 base_pkt_params['ip_dst'] = '192.168.0.2'
1399 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001400 if tp == "tcp":
1401 base_pkt_params['tcp_sport'] = 1234
1402 base_pkt_params['tcp_dport'] = 80
1403 elif tp == "udp":
1404 base_pkt_params['udp_sport'] = 1234
1405 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001406 for keyname in start_field_vals.keys():
1407 base_pkt_params[keyname] = start_field_vals[keyname]
1408
1409 mod_pkt_params = {}
1410 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001411 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1412 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001413 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001414 mod_pkt_params['vlan_vid'] = 3
1415 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001416 mod_pkt_params['ip_src'] = '10.20.30.40'
1417 mod_pkt_params['ip_dst'] = '50.60.70.80'
1418 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001419 if tp == "tcp":
1420 mod_pkt_params['tcp_sport'] = 4321
1421 mod_pkt_params['tcp_dport'] = 8765
1422 elif tp == "udp":
1423 mod_pkt_params['udp_sport'] = 4321
1424 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001425 for keyname in mod_field_vals.keys():
1426 mod_pkt_params[keyname] = mod_field_vals[keyname]
1427
1428 # Check for test param modifications
1429 strip = False
1430 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001431 add_vlan = test_param_get('add_vlan')
1432 strip_vlan = test_param_get('strip_vlan')
1433 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001434
1435 if add_vlan and strip_vlan:
1436 parent.assertTrue(0, "Add and strip VLAN both specified")
1437
1438 if vid:
1439 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001440 base_pkt_params['vlan_vid'] = vid
1441 if 'vlan_vid' in mod_fields:
1442 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001443
1444 if add_vlan:
1445 base_pkt_params['dl_vlan_enable'] = False
1446 mod_pkt_params['dl_vlan_enable'] = True
1447 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1448 mod_fields.append('pktlen')
1449 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001450 if 'vlan_vid' not in mod_fields:
1451 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001452 elif strip_vlan:
1453 base_pkt_params['dl_vlan_enable'] = True
1454 mod_pkt_params['dl_vlan_enable'] = False
1455 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1456 mod_fields.append('dl_vlan_enable')
1457 mod_fields.append('pktlen')
1458
Rich Lane110e0e32012-10-26 16:21:46 -07001459 if tp == "tcp":
1460 packet_builder = simple_tcp_packet
1461 elif tp == "udp":
1462 packet_builder = simple_udp_packet
1463 else:
1464 raise NotImplementedError("unknown transport protocol %s" % tp)
1465
Dan Talayco4b2bee62010-07-20 14:10:05 -07001466 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001467 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468
1469 # Build the expected packet, modifying the indicated fields
1470 for item in mod_fields:
1471 base_pkt_params[item] = mod_pkt_params[item]
1472 act = action_generate(parent, item, mod_pkt_params)
1473 if act:
1474 new_actions.append(act)
1475
Rich Lane110e0e32012-10-26 16:21:46 -07001476 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477
1478 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001479
1480# Generate a simple "drop" flow mod
1481# If in_band is true, then only drop from first test port
1482def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001483 request = ofp.message.flow_add()
1484 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001485 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001486 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001487 for of_port, ifname in port_map.items(): # Grab first port
1488 break
1489 request.match.in_port = of_port
1490 request.buffer_id = 0xffffffff
1491 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001492
1493def skip_message_emit(parent, s):
1494 """
1495 Print out a 'skipped' message to stderr
1496
1497 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001498 """
1499 global skipped_test_count
1500
1501 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001502 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001503 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001504 sys.stderr.write("(skipped) ")
1505 else:
1506 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001507
Dan Talayco8a64e332012-03-28 14:53:20 -07001508
1509def all_stats_get(parent):
1510 """
1511 Get the aggregate stats for all flows in the table
1512 @param parent Test instance with controller connection and assert
1513 @returns dict with keys flows, packets, bytes, active (flows),
1514 lookups, matched
1515 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001516 stat_req = ofp.message.aggregate_stats_request()
1517 stat_req.match = ofp.match()
1518 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001519 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001520 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001521
1522 rv = {}
1523
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001524 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001525 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001526
Rich Lane5fd6faf2013-03-11 13:30:20 -07001527 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001528 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1529 obj.packet_count, obj.byte_count)
1530 break
1531
Rich Lanee717c6e2013-03-12 10:25:50 -07001532 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001533 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001534
1535
1536 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001537 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001538 rv["active"] += obj.active_count
1539 rv["lookups"] += obj.lookup_count
1540 rv["matched"] += obj.matched_count
1541
1542 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001543
Rich Lane7744e112013-01-11 17:23:57 -08001544_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001545FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1546 for x in range(256)])
1547
1548def hex_dump_buffer(src, length=16):
1549 """
1550 Convert src to a hex dump string and return the string
1551 @param src The source buffer
1552 @param length The number of bytes shown in each line
1553 @returns A string showing the hex dump
1554 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001555 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001556 for i in xrange(0, len(src), length):
1557 chars = src[i:i+length]
1558 hex = ' '.join(["%02x" % ord(x) for x in chars])
1559 printable = ''.join(["%s" % ((ord(x) <= 127 and
1560 FILTER[ord(x)]) or '.') for x in chars])
1561 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1562 return ''.join(result)
1563
1564def format_packet(pkt):
1565 return "Packet length %d \n%s" % (len(str(pkt)),
1566 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001567
1568def inspect_packet(pkt):
1569 """
1570 Wrapper around scapy's show() method.
1571 @returns A string showing the dissected packet.
1572 """
1573 from cStringIO import StringIO
1574 out = None
1575 backup = sys.stdout
1576 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001577 tmp = StringIO()
1578 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001579 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001580 out = tmp.getvalue()
1581 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001582 finally:
1583 sys.stdout = backup
1584 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001585
1586def nonstandard(cls):
1587 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001588 Testcase decorator that marks the test as being non-standard.
1589 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001590 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001591 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001592 return cls
1593
1594def disabled(cls):
1595 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001596 Testcase decorator that marks the test as being disabled.
1597 These tests are not automatically added to the "standard" group or
1598 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001599 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001600 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001601 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001602
1603def group(name):
1604 """
1605 Testcase decorator that adds the test to a group.
1606 """
1607 def fn(cls):
1608 if not hasattr(cls, "_groups"):
1609 cls._groups = []
1610 cls._groups.append(name)
1611 return cls
1612 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001613
1614def version(ver):
1615 """
1616 Testcase decorator that specifies which versions of OpenFlow the test
1617 supports. The default is 1.0+. This decorator may only be used once.
1618
1619 Supported syntax:
1620 1.0 -> 1.0
1621 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1622 1.0+ -> 1.0, 1.1, 1.2, 1.3
1623 """
1624 versions = parse_version(ver)
1625 def fn(cls):
1626 cls._versions = versions
1627 return cls
1628 return fn
1629
1630def parse_version(ver):
1631 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1632 if re.match("^1\.\d+$", ver):
1633 versions = set([ver])
1634 elif re.match("^(1\.\d+)\+$", ver):
1635 if not ver[:-1] in allowed_versions:
1636 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1637 versions = set()
1638 if ver != "1.1+": versions.add("1.0")
1639 if ver != "1.2+": versions.add("1.1")
1640 if ver != "1.3+": versions.add("1.2")
1641 versions.add("1.3")
1642 else:
1643 versions = set(ver.split(','))
1644
1645 for version in versions:
1646 if not version in allowed_versions:
1647 raise ValueError("invalid OpenFlow version %s" % version)
1648
1649 return versions
1650
1651assert(parse_version("1.0") == set(["1.0"]))
1652assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1653assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001654
Rich Laneae3428c2013-03-07 14:37:42 -08001655def get_stats(test, req):
1656 """
1657 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1658 """
Rich Lane609194f2013-10-21 06:17:37 -07001659 msgtype = ofp.OFPT_STATS_REPLY
1660 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001661 stats = []
1662 reply, _ = test.controller.transact(req)
1663 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001664 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001665 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001666 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001667 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001668 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001669 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001670 return stats
1671
Rich Lanebd56ed62013-07-10 15:49:44 -07001672def get_flow_stats(test, match, table_id=None,
1673 out_port=None, out_group=None,
1674 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001675 """
1676 Retrieve a list of flow stats entries.
1677 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001678
1679 if table_id == None:
1680 if ofp.OFP_VERSION <= 2:
1681 table_id = 0xff
1682 else:
1683 table_id = ofp.OFPTT_ALL
1684
Rich Lanef3bc48c2013-05-03 17:39:35 -07001685 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001686 if ofp.OFP_VERSION == 1:
1687 out_port = ofp.OFPP_NONE
1688 else:
1689 out_port = ofp.OFPP_ANY
1690
1691 if out_group == None:
1692 if ofp.OFP_VERSION > 1:
1693 out_group = ofp.OFPP_ANY
1694
Rich Lanee717c6e2013-03-12 10:25:50 -07001695 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001696 table_id=table_id,
1697 out_port=out_port)
1698 if ofp.OFP_VERSION > 1:
1699 req.out_group = out_group
1700 req.cookie = cookie
1701 req.cookie_mask = cookie_mask
1702
Rich Laneae3428c2013-03-07 14:37:42 -08001703 return get_stats(test, req)
1704
Rich Lane968b6192013-03-07 15:34:43 -08001705def get_port_stats(test, port_no):
1706 """
1707 Retrieve a list of port stats entries.
1708 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001709 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001710 return get_stats(test, req)
1711
Rich Lane6a334922013-03-07 16:14:52 -08001712def get_queue_stats(test, port_no, queue_id):
1713 """
1714 Retrieve a list of queue stats entries.
1715 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001716 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001717 return get_stats(test, req)
1718
Rich Laneae3428c2013-03-07 14:37:42 -08001719def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001720 initial=[],
1721 pkts=None, bytes=None):
1722 """
1723 Verify that flow stats changed as expected.
1724
1725 Optionally takes an 'initial' list of stats entries, as returned by
1726 get_flow_stats(). If 'initial' is not given the counters are assumed to
1727 begin at 0.
1728 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001729
Rich Laneae3428c2013-03-07 14:37:42 -08001730 def accumulate(stats):
1731 pkts_acc = bytes_acc = 0
1732 for stat in stats:
1733 pkts_acc += stat.packet_count
1734 bytes_acc += stat.byte_count
1735 return (pkts_acc, bytes_acc)
1736
1737 pkts_before, bytes_before = accumulate(initial)
1738
1739 # Wait 10s for counters to update
1740 pkt_diff = byte_diff = None
1741 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001742 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001743 pkts_after, bytes_after = accumulate(stats)
1744 pkt_diff = pkts_after - pkts_before
1745 byte_diff = bytes_after - bytes_before
1746 if (pkts == None or pkt_diff >= pkts) and \
1747 (bytes == None or byte_diff >= bytes):
1748 break
Dan Talayco53724732013-03-08 23:54:02 -08001749 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001750
1751 if pkts != None:
1752 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1753
1754 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001755 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1756 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001757
Rich Lane968b6192013-03-07 15:34:43 -08001758def verify_port_stats(test, port,
1759 initial=[],
1760 tx_pkts=None, rx_pkts=None,
1761 tx_bytes=None, rx_bytes=None):
1762 """
1763 Verify that port stats changed as expected.
1764
1765 Optionally takes an 'initial' list of stats entries, as returned by
1766 get_port_stats(). If 'initial' is not given the counters are assumed to
1767 begin at 0.
1768 """
1769 def accumulate(stats):
1770 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1771 for stat in stats:
1772 tx_pkts_acc += stat.tx_packets
1773 rx_pkts_acc += stat.rx_packets
1774 tx_bytes_acc += stat.tx_bytes
1775 rx_bytes_acc += stat.rx_bytes
1776 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1777
1778 tx_pkts_before, rx_pkts_before, \
1779 tx_bytes_before, rx_bytes_before = accumulate(initial)
1780
1781 # Wait 10s for counters to update
1782 for i in range(0, 100):
1783 stats = get_port_stats(test, port)
1784 tx_pkts_after, rx_pkts_after, \
1785 tx_bytes_after, rx_bytes_after = accumulate(stats)
1786 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1787 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1788 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1789 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001790 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1791 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001792 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1793 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001794 break
1795 time.sleep(0.1)
1796
1797 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001798 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1799 "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 -08001800 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001801 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1802 "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 -08001803 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001804 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1805 "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 -08001806 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001807 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1808 "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 -08001809
Rich Lane6a334922013-03-07 16:14:52 -08001810def verify_queue_stats(test, port_no, queue_id,
1811 initial=[],
1812 pkts=None, bytes=None):
1813 """
1814 Verify that queue stats changed as expected.
1815
1816 Optionally takes an 'initial' list of stats entries, as returned by
1817 get_queue_stats(). If 'initial' is not given the counters are assumed to
1818 begin at 0.
1819 """
1820 def accumulate(stats):
1821 pkts_acc = bytes_acc = 0
1822 for stat in stats:
1823 pkts_acc += stat.tx_packets
1824 bytes_acc += stat.tx_bytes
1825 return (pkts_acc, bytes_acc)
1826
1827 pkts_before, bytes_before = accumulate(initial)
1828
1829 # Wait 10s for counters to update
1830 pkt_diff = byte_diff = None
1831 for i in range(0, 100):
1832 stats = get_queue_stats(test, port_no, queue_id)
1833 pkts_after, bytes_after = accumulate(stats)
1834 pkt_diff = pkts_after - pkts_before
1835 byte_diff = bytes_after - bytes_before
1836 if (pkts == None or pkt_diff >= pkts) and \
1837 (bytes == None or byte_diff >= bytes):
1838 break
Dan Talayco53724732013-03-08 23:54:02 -08001839 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001840
1841 if pkts != None:
1842 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1843
1844 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001845 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1846 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001847
Rich Lane4c504f32013-06-07 17:24:14 -07001848def packet_in_match(msg, data, in_port=None, reason=None):
1849 """
1850 Check whether the packet_in message 'msg' has fields matching 'data',
1851 'in_port', and 'reason'.
1852
1853 This function handles truncated packet_in data. The 'in_port' and 'reason'
1854 parameters are optional.
1855
1856 @param msg packet_in message
1857 @param data Expected packet_in data
1858 @param in_port Expected packet_in in_port, or None
1859 @param reason Expected packet_in reason, or None
1860 """
1861
Rich Lanec0d26dd2013-07-10 12:46:03 -07001862 if ofp.OFP_VERSION <= 2:
1863 pkt_in_port = msg.in_port
1864 else:
1865 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1866 if ofp.oxm.in_port in oxms:
1867 pkt_in_port = oxms[ofp.oxm.in_port].value
1868 else:
1869 logging.warn("Missing in_port in packet-in message")
1870 pkt_in_port = None
1871
1872 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001873 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001874 return False
1875
Rich Lanec0d26dd2013-07-10 12:46:03 -07001876 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001877 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1878 return False
1879
1880 # Check that one of the packets is a prefix of the other.
1881 # The received packet may be either truncated or padded, but not both.
1882 # (Some of the padding may be truncated but that's irrelevant). We
1883 # need to check that the smaller packet is a prefix of the larger one.
1884 # Note that this check succeeds if the switch sends a zero-length
1885 # packet-in.
1886 compare_len = min(len(msg.data), len(data))
1887 if data[:compare_len] != msg.data[:compare_len]:
1888 logging.debug("Incorrect packet_in data")
1889 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1890 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1891 return False
1892
1893 return True
1894
1895def verify_packet_in(test, data, in_port, reason, controller=None):
1896 """
1897 Assert that the controller receives a packet_in message matching data 'data'
1898 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1899 itself, that's up to the test case.
1900
1901 @param test Instance of base_tests.SimpleProtocol
1902 @param pkt String to expect as the packet_in data
1903 @param in_port OpenFlow port number to expect as the packet_in in_port
1904 @param reason One of OFPR_* to expect as the packet_in reason
1905 @param controller Controller instance, defaults to test.controller
1906 @returns The received packet-in message
1907 """
1908
1909 if controller == None:
1910 controller = test.controller
1911
1912 end_time = time.time() + oftest.ofutils.default_timeout
1913
1914 while True:
1915 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1916 if not msg:
1917 # Timeout
1918 break
1919 elif packet_in_match(msg, data, in_port, reason):
1920 # Found a matching message
1921 break
1922
Kiran Poola58c5c042014-05-15 15:11:06 -07001923 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001924 return msg
1925
1926def verify_no_packet_in(test, data, in_port, controller=None):
1927 """
1928 Assert that the controller does not receive a packet_in message matching
1929 data 'data' from port 'in_port'.
1930
1931 @param test Instance of base_tests.SimpleProtocol
1932 @param pkt String to expect as the packet_in data
1933 @param in_port OpenFlow port number to expect as the packet_in in_port
1934 @param controller Controller instance, defaults to test.controller
1935 """
1936
1937 if controller == None:
1938 controller = test.controller
1939
1940 # Negative test, need to wait a short amount of time before checking we
1941 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001942 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001943
1944 # Check every packet_in queued in the controller
1945 while True:
1946 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1947 if msg == None:
1948 # No more queued packet_in messages
1949 break
1950 elif packet_in_match(msg, data, in_port, None):
1951 # Found a matching message
1952 break
1953
Rich Lane82c882d2013-08-09 17:13:52 -07001954 if in_port == None:
1955 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1956 else:
1957 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001958
Rich Lane045db072013-08-06 13:16:30 -07001959def openflow_ports(num=None):
1960 """
1961 Return a list of 'num' OpenFlow port numbers
1962
1963 If 'num' is None, return all available ports. Otherwise, limit the length
1964 of the result to 'num' and raise an exception if not enough ports are
1965 available.
1966 """
1967 ports = sorted(oftest.config["port_map"].keys())
1968 if num != None and len(ports) < num:
1969 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
1970 return ports[:num]
1971
Rich Lanee4b384d2013-09-13 14:33:40 -07001972def verify_packet(test, pkt, ofport):
1973 """
1974 Check that an expected packet is received
1975 """
1976 logging.debug("Checking for pkt on port %r", ofport)
1977 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
1978 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08001979 return (rcv_port, rcv_pkt, pkt_time)
1980
Rich Lanee4b384d2013-09-13 14:33:40 -07001981def verify_no_packet(test, pkt, ofport):
1982 """
1983 Check that a particular packet is not received
1984 """
1985 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07001986 (rcv_port, rcv_pkt, pkt_time) = \
1987 test.dataplane.poll(
1988 port_number=ofport, exp_pkt=str(pkt),
1989 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001990 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
1991
1992def verify_no_other_packets(test):
1993 """
1994 Check that no unexpected packets are received
1995
1996 This is a no-op if the --relax option is in effect.
1997 """
1998 if oftest.config["relax"]:
1999 return
2000 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002001 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002002 if rcv_pkt != None:
2003 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2004 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2005
2006def verify_packets(test, pkt, ofports):
2007 """
2008 Check that a packet is received on certain ports
2009
2010 Also verifies that the packet is not received on any other ports, and that no
2011 other packets are received (unless --relax is in effect).
2012
2013 This covers the common and simplest cases for checking dataplane outputs.
2014 For more complex usage, like multiple different packets being output, or
2015 multiple packets on the same port, use the primitive verify_packet,
2016 verify_no_packet, and verify_no_other_packets functions directly.
2017 """
2018 pkt = str(pkt)
2019 for ofport in openflow_ports():
2020 if ofport in ofports:
2021 verify_packet(test, pkt, ofport)
2022 else:
2023 verify_no_packet(test, pkt, ofport)
2024 verify_no_other_packets(test)
2025
Rich Lane12d04592013-10-10 17:21:07 -07002026def verify_no_errors(ctrl):
2027 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2028 if error:
2029 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002030
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002031def verify_capability(test, capability):
2032 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002033 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002034
2035 @param test Instance of base_tests.SimpleProtocol
2036 @param capability One of ofp_capabilities.
2037 """
2038 logging.info("Verifing that capability code is valid.")
2039 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2040 "Capability code %d does not exist." % capability)
2041 capability_str = ofp.const.ofp_capabilities_map[capability]
2042
2043 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002044 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002045 req = ofp.message.features_request()
2046 res, raw = test.controller.transact(req)
2047 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2048 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2049 ("Unexpected packet type %d received in response to "
2050 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002051 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002052
Jonathan Stout641167f2014-02-04 12:07:10 -05002053 if (res.capabilities & capability) > 0:
2054 logging.info("Switch capabilities bitmask claims to support %s",
2055 capability_str)
2056 return True, res.capabilities
2057 else:
2058 logging.info("Capabilities bitmask does not support %s.",
2059 capability_str)
2060 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002061
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002062def verify_configuration_flag(test, flag):
2063 """
2064 Return True if DUT supports specified configuration flag.
2065
2066 @param test Instance of base_tests.SimpleProtocol
2067 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002068 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002069 """
2070 logging.info("Verifing that flag is valid.")
2071 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2072 "flag %s does not exist." % flag)
2073 flag_str = ofp.const.ofp_config_flags_map[flag]
2074
2075 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
2076 req = ofp.message.get_config_request()
2077 rv = test.controller.message_send(req)
2078 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2079
2080 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2081 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2082 timeout=2)
2083 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2084 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2085
2086 if res.flags == flag:
2087 logging.info("%s flag is set.", flag_str)
2088 return True, res.flags
2089 else:
2090 logging.info("%s flag is not set.", flag_str)
2091 return False, res.flags
2092
Rich Lane7744e112013-01-11 17:23:57 -08002093__all__ = list(set(locals()) - _import_blacklist)