blob: 5e56589f7e7d3a0b4354cbcdc31754a365b4d82f [file] [log] [blame]
Dan Talaycod2ca1032010-03-10 14:40:26 -08001import sys
Dan Talayco92c99122010-06-03 13:53:18 -07002import copy
Rich Lane6242d9f2013-01-06 17:35:39 -08003import logging
4import types
5import time
Rich Lane5a9a1922013-01-11 14:29:30 -08006import re
Flavio Castro1c9b1252016-02-04 18:42:58 -05007from Queue import Queue
8
Rich Lanea68176f2013-08-09 17:41:05 -07009import packet as scapy
Dan Talayco41eae8b2010-03-10 13:57:06 -080010
Rich Lanecd97d3d2013-01-07 18:50:06 -080011import oftest
12import oftest.controller
13import oftest.dataplane
Rich Lanef6883512013-03-11 17:00:09 -070014import oftest.parse
Rich Lane4c504f32013-06-07 17:24:14 -070015import oftest.ofutils
Rich Lanee717c6e2013-03-12 10:25:50 -070016import ofp
Dan Talaycoc901f4d2010-03-07 21:55:45 -080017
Dan Talaycoba3745c2010-07-21 21:51:08 -070018global skipped_test_count
19skipped_test_count = 0
20
Rich Lane7744e112013-01-11 17:23:57 -080021_import_blacklist = set(locals().keys())
22
Dan Talayco551befa2010-07-15 17:05:32 -070023# Some useful defines
24IP_ETHERTYPE = 0x800
25TCP_PROTOCOL = 0x6
26UDP_PROTOCOL = 0x11
27
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000028MINSIZE = 0
29
Tony van der Peet80c5b202013-11-20 11:47:48 +130030def delete_all_flows(ctrl, send_barrier=True):
Dan Talayco41eae8b2010-03-10 13:57:06 -080031 """
32 Delete all flows on the switch
33 @param ctrl The controller object for the test
Tony van der Peet80c5b202013-11-20 11:47:48 +130034 @param send_barrier Whether or not to send a barrier message
Dan Talayco41eae8b2010-03-10 13:57:06 -080035 """
36
Rich Lane9a003812012-10-04 17:17:59 -070037 logging.info("Deleting all flows")
Rich Lanee717c6e2013-03-12 10:25:50 -070038 msg = ofp.message.flow_delete()
Rich Lanec717f442013-06-13 15:49:09 -070039 if ofp.OFP_VERSION in [1, 2]:
40 msg.match.wildcards = ofp.OFPFW_ALL
41 msg.out_port = ofp.OFPP_NONE
42 msg.buffer_id = 0xffffffff
43 elif ofp.OFP_VERSION >= 3:
44 msg.table_id = ofp.OFPTT_ALL
45 msg.buffer_id = ofp.OFP_NO_BUFFER
46 msg.out_port = ofp.OFPP_ANY
47 msg.out_group = ofp.OFPG_ANY
Rich Lane5c3151c2013-01-03 17:15:41 -080048 ctrl.message_send(msg)
Tony van der Peet80c5b202013-11-20 11:47:48 +130049 if send_barrier:
50 do_barrier(ctrl)
Rich Lane32bf9482013-01-03 17:26:30 -080051 return 0 # for backwards compatibility
Dan Talayco41eae8b2010-03-10 13:57:06 -080052
Rich Lane5f3c9b22013-10-10 17:20:30 -070053def delete_all_groups(ctrl):
54 """
55 Delete all groups on the switch
56 @param ctrl The controller object for the test
57 """
58
59 logging.info("Deleting all groups")
Rich Lane5de5e632013-11-24 10:15:25 -080060 msg = ofp.message.group_delete(group_id=ofp.OFPG_ALL)
Rich Lane5f3c9b22013-10-10 17:20:30 -070061 ctrl.message_send(msg)
62 do_barrier(ctrl)
63
Flavio Castro1c9b1252016-02-04 18:42:58 -050064def delete_groups(ctrl, group_queue=Queue()):
65 """
66 Delete all groups on list
67 @param ctrl The controller object for the test
68 :param group_queue:
69 """
70 logging.info("Deleting groups")
71 while (not group_queue.empty()):
Pier1e4e98e2016-10-26 14:36:05 -070072 msg = ofp.message.group_delete(group_id=group_queue.get())
Flavio Castro1c9b1252016-02-04 18:42:58 -050073 ctrl.message_send(msg)
74 do_barrier(ctrl)
75
Saurav Das34992182017-04-14 15:59:48 -070076def delete_group(ctrl, group_id):
77 """
78 Delete a single group
79 @param ctrl The controller object for the test
80 :param group_id
81 """
82 logging.info("Deleting a single group with groupId:" + str(group_id))
83 msg = ofp.message.group_delete(group_id=group_id)
84 ctrl.message_send(msg)
85 do_barrier(ctrl)
86
Ed Swierk99a74de2012-08-22 06:40:54 -070087def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070088 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070089 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -070090 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
91 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -070092 else:
93 return 0
94
macauley_cheng0a0a7f62015-11-06 11:36:50 +080095def simple_packet(content='00 00 00 11 33 55 00 00 00 11 22 33 81 00 00 03 '
96 '08 00 45 00 00 2e 04 d2 00 00 7f 00 b2 47 c0 a8 '
97 '01 64 c0 a8 02 02 00 00 00 00 00 00 00 00 00 00 '
98 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'):
macauley_cheng739f54b2015-11-09 13:52:59 +080099
100 pkt = ''.join(content.split(" ")).decode('hex')
macauley_chengc80249d2015-11-09 14:11:18 +0800101 pkt = scapy.Ether(pkt)
macauley_cheng739f54b2015-11-09 13:52:59 +0800102 if len(pkt) < 64:
103 pkt = pkt/("D" * (64 - len(pkt)))
macauley_chengc80249d2015-11-09 14:11:18 +0800104 #scapy.hexdump(pkt)
macauley_cheng0a0a7f62015-11-06 11:36:50 +0800105 return pkt
106
Dan Talayco41eae8b2010-03-10 13:57:06 -0800107def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700108 eth_dst='00:01:02:03:04:05',
109 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700110 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700111 vlan_vid=0,
112 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700113 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800114 ip_src='192.168.0.1',
115 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700116 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800117 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800118 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700119 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700120 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700121 ip_ihl=None,
122 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800123 ):
124 """
125 Return a simple dataplane TCP packet
126
127 Supports a few parameters:
128 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700129 @param eth_dst Destinatino MAC
130 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700131 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700132 @param vlan_vid VLAN ID
133 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800134 @param ip_src IP source
135 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700136 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800137 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800138 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700139 @param tcp_sport TCP source port
140 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800141
142 Generates a simple TCP request. Users
143 shouldn't assume anything about this packet other than that
144 it is a valid ethernet/IP/TCP frame.
145 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000146
147 if MINSIZE > pktlen:
148 pktlen = MINSIZE
149
Dan Talayco551befa2010-07-15 17:05:32 -0700150 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800151 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700152 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
153 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
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)/ \
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 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700157 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700158 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800159 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700160 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700161 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700162 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800163 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 -0700164 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700165
Dan Talayco41eae8b2010-03-10 13:57:06 -0800166 pkt = pkt/("D" * (pktlen - len(pkt)))
167
168 return pkt
169
Rich Lane86aceb02013-07-17 18:45:38 -0700170def simple_tcpv6_packet(pktlen=100,
171 eth_dst='00:01:02:03:04:05',
172 eth_src='00:06:07:08:09:0a',
173 dl_vlan_enable=False,
174 vlan_vid=0,
175 vlan_pcp=0,
176 ipv6_src='2001:db8:85a3::8a2e:370:7334',
177 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
178 ipv6_tc=0,
179 ipv6_hlim=64,
180 ipv6_fl=0,
181 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700182 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700183 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700184 """
185 Return a simple IPv6/TCP packet
186
187 Supports a few parameters:
188 @param len Length of packet in bytes w/o CRC
189 @param eth_dst Destination MAC
190 @param eth_src Source MAC
191 @param dl_vlan_enable True if the packet is with vlan, False otherwise
192 @param vlan_vid VLAN ID
193 @param vlan_pcp VLAN priority
194 @param ipv6_src IPv6 source
195 @param ipv6_dst IPv6 destination
196 @param ipv6_tc IPv6 traffic class
197 @param ipv6_ttl IPv6 hop limit
198 @param ipv6_fl IPv6 flow label
199 @param tcp_dport TCP destination port
200 @param tcp_sport TCP source port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700201 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700202
203 Generates a simple TCP request. Users shouldn't assume anything about this
204 packet other than that it is a valid ethernet/IPv6/TCP frame.
205 """
206
207 if MINSIZE > pktlen:
208 pktlen = MINSIZE
209
210 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
211 if dl_vlan_enable or vlan_vid or vlan_pcp:
212 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
213 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 -0700214 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700215 pkt /= ("D" * (pktlen - len(pkt)))
216
217 return pkt
218
Rich Lane6ee7bea2012-10-26 16:19:29 -0700219def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700220 eth_dst='00:01:02:03:04:05',
221 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700222 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700223 vlan_vid=0,
224 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700225 dl_vlan_cfi=0,
226 ip_src='192.168.0.1',
227 ip_dst='192.168.0.2',
228 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800229 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700230 udp_sport=1234,
231 udp_dport=80,
232 ip_ihl=None,
233 ip_options=False
234 ):
235 """
236 Return a simple dataplane UDP packet
237
238 Supports a few parameters:
239 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700240 @param eth_dst Destination MAC
241 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700242 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700243 @param vlan_vid VLAN ID
244 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700245 @param ip_src IP source
246 @param ip_dst IP destination
247 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800248 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700249 @param udp_dport UDP destination port
250 @param udp_sport UDP source port
251
252 Generates a simple UDP packet. Users shouldn't assume anything about
253 this packet other than that it is a valid ethernet/IP/UDP frame.
254 """
255
256 if MINSIZE > pktlen:
257 pktlen = MINSIZE
258
259 # Note Dot1Q.id is really CFI
260 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700261 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
262 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
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)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700264 scapy.UDP(sport=udp_sport, dport=udp_dport)
265 else:
266 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700267 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800268 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700269 scapy.UDP(sport=udp_sport, dport=udp_dport)
270 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700271 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800272 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 -0700273 scapy.UDP(sport=udp_sport, dport=udp_dport)
274
275 pkt = pkt/("D" * (pktlen - len(pkt)))
276
277 return pkt
278
macauley_chengb0ec33d2015-09-04 11:32:44 +0800279
280def simple_tcp_packet_two_vlan(pktlen=100,
281 eth_dst='00:01:02:03:04:05',
282 eth_src='00:06:07:08:09:0a',
283 out_dl_vlan_enable=False,
284 in_dl_vlan_enable=False,
285 out_vlan_vid=0,
286 out_vlan_pcp=0,
287 out_dl_vlan_cfi=0,
288 in_vlan_vid=0,
289 in_vlan_pcp=0,
290 in_dl_vlan_cfi=0,
291 ip_src='192.168.0.1',
292 ip_dst='192.168.0.2',
293 ip_tos=0,
294 ip_ttl=64,
295 tcp_sport=1234,
296 tcp_dport=80,
297 tcp_flags="S",
298 ip_ihl=None,
299 ip_options=False
300 ):
301 """
302 Return a simple dataplane TCP packet
303
304 Supports a few parameters:
305 @param len Length of packet in bytes w/o CRC
306 @param eth_dst Destinatino MAC
307 @param eth_src Source MAC
308 @param dl_vlan_enable True if the packet is with vlan, False otherwise
309 @param vlan_vid VLAN ID
310 @param vlan_pcp VLAN priority
311 @param ip_src IP source
312 @param ip_dst IP destination
313 @param ip_tos IP ToS
314 @param ip_ttl IP TTL
315 @param tcp_dport TCP destination port
316 @param tcp_sport TCP source port
317 @param tcp_flags TCP Control flags
318
319 Generates a simple TCP request. Users
320 shouldn't assume anything about this packet other than that
321 it is a valid ethernet/IP/TCP frame.
322 """
323
324 if MINSIZE > pktlen:
325 pktlen = MINSIZE
326
327 # Note Dot1Q.id is really CFI
328 if (out_dl_vlan_enable and 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
332 if in_dl_vlan_enable:
333 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
334
335 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
336 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
337 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
338 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
339 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
340 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
341 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
342 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
343 assert(0) #shall not have this caes
344 else:
345 if not ip_options:
346 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
347 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
348 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
349 else:
350 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
351 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
352 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
353
354 pkt = pkt/("D" * (pktlen - len(pkt)))
355
356 return pkt
357
macauley17cd60d2015-07-27 17:41:18 +0800358def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
359 eth_src='00:06:07:08:09:0a',
360 dl_vlan_enable=False,
361 vlan_vid=0,
362 vlan_pcp=0,
363 dl_vlan_cfi=0,
364 ip_src='192.168.0.1',
365 ip_dst='192.168.0.2',
366 ip_tos=0,
367 ip_ttl=64,
368 udp_sport=1234,
369 udp_dport=4789,
370 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800371 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800372 ip_ihl=None,
373 ip_options=False
374 ):
375 """
376 Return a simple dataplane UDP packet
377
378 Supports a few parameters:
379 @param len Length of packet in bytes w/o CRC
380 @param eth_dst Destination MAC
381 @param eth_src Source MAC
382 @param dl_vlan_enable True if the packet is with vlan, False otherwise
383 @param vlan_vid VLAN ID
384 @param vlan_pcp VLAN priority
385 @param ip_src IP source
386 @param ip_dst IP destination
387 @param ip_tos IP ToS
388 @param ip_ttl IP TTL
389 @param udp_dport UDP destination port
390 @param udp_sport UDP source port
391 @param inner_pyload inner pacekt content
392 Generates a simple UDP packet. Users shouldn't assume anything about
393 this packet other than that it is a valid ethernet/IP/UDP frame.
394 """
395
396 # Note Dot1Q.id is really CFI
397 if (dl_vlan_enable):
398 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
399 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
400 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
401 scapy.UDP(sport=udp_sport, dport=udp_dport)
402 else:
403 if not ip_options:
404 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
405 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
406 scapy.UDP(sport=udp_sport, dport=udp_dport)
407 else:
408 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
409 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
410 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800411
macauley17cd60d2015-07-27 17:41:18 +0800412 #add vxlan header
413 pkt = pkt/scapy.VXLAN(vni=vnid)
414 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800415 if inner_payload!=None:
416 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800417
418 return pkt
419
Flavio Castro72a45d52015-12-02 16:37:05 -0500420def mpls_packet(pktlen=100,
421 eth_dst='00:01:02:03:04:05',
422 eth_src='00:06:07:08:09:0a',
423 dl_vlan_enable=False,
424 vlan_vid=0,
425 vlan_pcp=0,
426 dl_vlan_cfi=0,
427 ip_src='192.168.0.1',
428 ip_dst='192.168.0.2',
429 ip_tos=0,
430 ip_ttl=64,
431 tcp_sport=1234,
432 tcp_dport=80,
433 tcp_flags="S",
434 ip_ihl=None,
435 ip_options=False,
436 label=None,
Flavio Castro167f5bd2015-12-02 19:33:53 -0500437 inner_payload=True
Flavio Castro72a45d52015-12-02 16:37:05 -0500438 ):
439 if MINSIZE > pktlen:
440 pktlen = MINSIZE
441
442 # Note Dot1Q.id is really CFI
443 if (dl_vlan_enable):
444 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
445 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
446 else:
447 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
448
449 #add MPLS header
450 for i in range(len(label)):
451 l,c,s,t=label[i]
452 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
453
454 #add innder payload
455 if inner_payload!=None:
456 pkt=pkt / \
457 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
458 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Flavio Castro167f5bd2015-12-02 19:33:53 -0500459
460 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500461
462 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800463
Pier23784aa2016-09-19 20:08:21 -0700464def pw_packet(pktlen=100,
465 out_eth_dst='00:01:02:03:04:05',
466 out_eth_src='00:06:07:08:09:0a',
467 label=None,
468 cw=None,
469 in_eth_dst='00:01:02:03:04:05',
470 in_eth_src='00:06:07:08:09:0a',
471 out_dl_vlan_enable=False,
472 in_dl_vlan_enable=False,
473 out_vlan_vid=0,
474 out_vlan_pcp=0,
475 out_dl_vlan_cfi=0,
476 in_vlan_vid=0,
477 in_vlan_pcp=0,
478 in_dl_vlan_cfi=0,
479 ip_src='192.168.0.1',
480 ip_dst='192.168.0.2',
481 ip_tos=0,
482 ip_ttl=64,
483 tcp_sport=1234,
484 tcp_dport=80,
485 tcp_flags="S",
486 ip_ihl=None,
487 ip_options=False
488 ):
489 """
490 Return a simple dataplane TCP packet encapsulated
491 in a pw packet
492 """
493
494 # Add the outer ethernet header
495 if MINSIZE > pktlen:
496 pktlen = MINSIZE
497
498 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
499
500 #add MPLS header
501 for i in range(len(label)):
502 l,c,s,t=label[i]
503 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
504
505 #add the PW CW
506 l,c,s,t=cw
507 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
508
509 # Note Dot1Q.id is really CFI
510 if (out_dl_vlan_enable and in_dl_vlan_enable):
511
512 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
513 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
514
515 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
516
517 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
518 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
519
520 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
521
522 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
523 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
524 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
525 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
526
527 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
528
529 assert(0) #shall not have this caes
530
531 else:
532 if not ip_options:
533 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
534 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
535 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
536 else:
537 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
538 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
539 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
540
541 pkt = pkt/("D" * (pktlen - len(pkt)))
542
543 return pkt
544
Pier1e4e98e2016-10-26 14:36:05 -0700545def mplsv6_packet(pktlen=100,
546 eth_dst='00:01:02:03:04:05',
547 eth_src='00:06:07:08:09:0a',
548 dl_vlan_enable=False,
549 vlan_vid=0,
550 vlan_pcp=0,
551 dl_vlan_cfi=0,
552 ipv6_src='2001:db8:85a3::8a2e:370:7334',
553 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
554 ipv6_tc=0,
555 ipv6_hlim=64,
556 ipv6_fl=0,
557 tcp_sport=1234,
558 tcp_dport=80,
559 tcp_flags="S",
560 label=None,
561 inner_payload=True
562 ):
563 if MINSIZE > pktlen:
564 pktlen = MINSIZE
565
566 # Note Dot1Q.id is really CFI
567 if (dl_vlan_enable):
568 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
569 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
570 else:
571 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
572
573 #add MPLS header
574 for i in range(len(label)):
575 l,c,s,t=label[i]
576 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
577
578 #add innder payload
579 if inner_payload!=None:
580 pkt=pkt / \
581 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
582 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
583
584 pkt = pkt/("D" * (pktlen - len(pkt)))
585
586 return pkt
587
macauley_cheng45833df2015-08-31 15:19:07 +0800588def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
589 eth_src='00:06:07:08:09:0a',
590 dl_vlan_enable=False,
591 vlan_vid=0,
592 vlan_pcp=0,
593 dl_vlan_cfi=0,
594 label=None,
595 inner_payload=None
596 ):
597 """
598 Return a simple dataplane MPLS packet
599
600 Supports a few parameters:
601 @param len Length of packet in bytes w/o CRC
602 @param eth_dst Destination MAC
603 @param eth_src Source MAC
604 @param dl_vlan_enable True if the packet is with vlan, False otherwise
605 @param vlan_vid VLAN ID
606 @param vlan_pcp VLAN priority
607 @param inner_pyload inner pacekt content
608 Generates a simple MPLS packet. Users shouldn't assume anything about
609 this packet other than that it is a valid ethernet/IP/UDP frame.
610 """
611
612 # Note Dot1Q.id is really CFI
613 if (dl_vlan_enable):
614 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
615 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
616 else:
617 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
618
619 #add MPLS header
620 for i in range(len(label)):
621 l,c,s,t=label[i]
622 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
623
624 #add innder payload
625 if inner_payload!=None:
626 pkt=pkt/inner_payload
627
628 return pkt
629
Rich Lane86aceb02013-07-17 18:45:38 -0700630def simple_udpv6_packet(pktlen=100,
631 eth_dst='00:01:02:03:04:05',
632 eth_src='00:06:07:08:09:0a',
633 dl_vlan_enable=False,
634 vlan_vid=0,
635 vlan_pcp=0,
636 ipv6_src='2001:db8:85a3::8a2e:370:7334',
637 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
638 ipv6_tc=0,
639 ipv6_hlim=64,
640 ipv6_fl=0,
641 udp_sport=1234,
642 udp_dport=80):
643 """
644 Return a simple IPv6/UDP packet
645
646 Supports a few parameters:
647 @param len Length of packet in bytes w/o CRC
648 @param eth_dst Destination MAC
649 @param eth_src Source MAC
650 @param dl_vlan_enable True if the packet is with vlan, False otherwise
651 @param vlan_vid VLAN ID
652 @param vlan_pcp VLAN priority
653 @param ipv6_src IPv6 source
654 @param ipv6_dst IPv6 destination
655 @param ipv6_tc IPv6 traffic class
656 @param ipv6_ttl IPv6 hop limit
657 @param ipv6_fl IPv6 flow label
658 @param udp_dport UDP destination port
659 @param udp_sport UDP source port
660
661 Generates a simple UDP request. Users shouldn't assume anything about this
662 packet other than that it is a valid ethernet/IPv6/UDP frame.
663 """
664
665 if MINSIZE > pktlen:
666 pktlen = MINSIZE
667
668 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
669 if dl_vlan_enable or vlan_vid or vlan_pcp:
670 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
671 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
672 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
673 pkt /= ("D" * (pktlen - len(pkt)))
674
675 return pkt
676
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700677def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700678 eth_dst='00:01:02:03:04:05',
679 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700680 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700681 vlan_vid=0,
682 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700683 ip_src='192.168.0.1',
684 ip_dst='192.168.0.2',
685 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800686 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600687 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700688 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600689 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600690 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700691 """
692 Return a simple ICMP packet
693
694 Supports a few parameters:
695 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700696 @param eth_dst Destinatino MAC
697 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700698 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700699 @param vlan_vid VLAN ID
700 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700701 @param ip_src IP source
702 @param ip_dst IP destination
703 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800704 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600705 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700706 @param icmp_type ICMP type
707 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600708 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700709
710 Generates a simple ICMP ECHO REQUEST. Users
711 shouldn't assume anything about this packet other than that
712 it is a valid ethernet/ICMP frame.
713 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000714
715 if MINSIZE > pktlen:
716 pktlen = MINSIZE
717
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700718 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700719 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
720 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600721 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600722 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700723 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700724 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600725 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600726 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700727
728 pkt = pkt/("0" * (pktlen - len(pkt)))
729
730 return pkt
731
Rich Lane86aceb02013-07-17 18:45:38 -0700732def simple_icmpv6_packet(pktlen=100,
733 eth_dst='00:01:02:03:04:05',
734 eth_src='00:06:07:08:09:0a',
735 dl_vlan_enable=False,
736 vlan_vid=0,
737 vlan_pcp=0,
738 ipv6_src='2001:db8:85a3::8a2e:370:7334',
739 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
740 ipv6_tc=0,
741 ipv6_hlim=64,
742 ipv6_fl=0,
743 icmp_type=8,
744 icmp_code=0):
745 """
746 Return a simple ICMPv6 packet
747
748 Supports a few parameters:
749 @param len Length of packet in bytes w/o CRC
750 @param eth_dst Destination MAC
751 @param eth_src Source MAC
752 @param dl_vlan_enable True if the packet is with vlan, False otherwise
753 @param vlan_vid VLAN ID
754 @param vlan_pcp VLAN priority
755 @param ipv6_src IPv6 source
756 @param ipv6_dst IPv6 destination
757 @param ipv6_tc IPv6 traffic class
758 @param ipv6_ttl IPv6 hop limit
759 @param ipv6_fl IPv6 flow label
760 @param icmp_type ICMP type
761 @param icmp_code ICMP code
762
763 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
764 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
765 """
766
767 if MINSIZE > pktlen:
768 pktlen = MINSIZE
769
770 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
771 if dl_vlan_enable or vlan_vid or vlan_pcp:
772 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
773 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
774 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
775 pkt /= ("D" * (pktlen - len(pkt)))
776
777 return pkt
778
Shudong Zhouc7562b12013-02-06 01:12:18 -0800779def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700780 eth_dst='ff:ff:ff:ff:ff:ff',
781 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800782 vlan_vid=0,
783 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800784 arp_op=1,
785 ip_snd='192.168.0.1',
786 ip_tgt='192.168.0.2',
787 hw_snd='00:06:07:08:09:0a',
788 hw_tgt='00:00:00:00:00:00',
789 ):
790 """
791 Return a simple ARP packet
792
793 Supports a few parameters:
794 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700795 @param eth_dst Destinatino MAC
796 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800797 @param arp_op Operation (1=request, 2=reply)
798 @param ip_snd Sender IP
799 @param ip_tgt Target IP
800 @param hw_snd Sender hardware address
801 @param hw_tgt Target hardware address
802
803 Generates a simple ARP REQUEST. Users
804 shouldn't assume anything about this packet other than that
805 it is a valid ethernet/ARP frame.
806 """
807
808 if MINSIZE > pktlen:
809 pktlen = MINSIZE
810
Rich Lanee01611f2014-01-15 14:55:11 -0800811 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
812 if vlan_vid or vlan_pcp:
813 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
814 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 -0800815
Rich Laned459ce52014-01-24 12:09:54 -0800816 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800817
818 return pkt
819
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700820def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800821 eth_dst='00:01:02:03:04:05',
822 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700823 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000824
825 if MINSIZE > pktlen:
826 pktlen = MINSIZE
827
Rich Laned0478ff2013-03-11 12:46:58 -0700828 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700829
830 pkt = pkt/("0" * (pktlen - len(pkt)))
831
832 return pkt
833
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800834def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700835 eth_dst='00:01:02:03:04:05',
836 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800837 dl_vlan_outer=20,
838 dl_vlan_pcp_outer=0,
839 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700840 vlan_vid=10,
841 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800842 dl_vlan_cfi=0,
843 ip_src='192.168.0.1',
844 ip_dst='192.168.0.2',
845 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800846 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800847 tcp_sport=1234,
848 tcp_dport=80,
849 ip_ihl=None,
850 ip_options=False
851 ):
852 """
853 Return a doubly tagged dataplane TCP packet
854
855 Supports a few parameters:
856 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700857 @param eth_dst Destinatino MAC
858 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800859 @param dl_vlan_outer Outer VLAN ID
860 @param dl_vlan_pcp_outer Outer VLAN priority
861 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700862 @param vlan_vid Inner VLAN ID
863 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800864 @param dl_vlan_cfi VLAN cfi bit
865 @param ip_src IP source
866 @param ip_dst IP destination
867 @param ip_tos IP ToS
868 @param tcp_dport TCP destination port
869 @param ip_sport TCP source port
870
871 Generates a TCP request. Users
872 shouldn't assume anything about this packet other than that
873 it is a valid ethernet/IP/TCP frame.
874 """
875
876 if MINSIZE > pktlen:
877 pktlen = MINSIZE
878
879 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700880 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800881 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700882 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800883 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800884 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
885
886 pkt = pkt/("D" * (pktlen - len(pkt)))
887
888 return pkt
889
Shudong Zhoub7f12462012-11-20 13:01:12 -0800890def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700891 """
892 Do a barrier command
893 Return 0 on success, -1 on error
894 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700895 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800896 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800897 if resp is None:
898 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700899 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800900 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700901
Rich Lane9a003812012-10-04 17:17:59 -0700902def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700903 """
904 Get a port's configuration
905
906 Gets the switch feature configuration and grabs one port's
907 configuration
908
909 @returns (hwaddr, config, advert) The hwaddress, configuration and
910 advertised values
911 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700912
913 if ofp.OFP_VERSION <= 3:
914 request = ofp.message.features_request()
915 reply, _ = controller.transact(request)
916 if reply is None:
917 logging.warn("Get feature request failed")
918 return None, None, None
919 logging.debug(reply.show())
920 ports = reply.ports
921 else:
922 request = ofp.message.port_desc_stats_request()
923 # TODO do multipart correctly
924 reply, _ = controller.transact(request)
925 if reply is None:
926 logging.warn("Port desc stats request failed")
927 return None, None, None
928 logging.debug(reply.show())
929 ports = reply.entries
930
931 for port in ports:
932 if port.port_no == port_no:
933 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700934
Rich Lane9a003812012-10-04 17:17:59 -0700935 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700936 return None, None, None
937
Rich Lane9a003812012-10-04 17:17:59 -0700938def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700939 """
940 Set the port configuration according the given parameters
941
942 Gets the switch feature configuration and updates one port's
943 configuration value according to config and mask
944 """
Rich Lane9a003812012-10-04 17:17:59 -0700945 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700946
947 hw_addr, _, _ = port_config_get(controller, port_no)
948
Rich Lanee717c6e2013-03-12 10:25:50 -0700949 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700950 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700951 if hw_addr != None:
952 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700953 mod.config = config
954 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700955 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800956 controller.message_send(mod)
957 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700958
Rich Lane2014f9b2012-10-05 15:29:40 -0700959def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700960 """
961 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700962 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700963 @param pkt Expected packet; may be None if yes_ports is empty
964 @param yes_ports Set or list of ports that should recieve packet
965 @param no_ports Set or list of ports that should not receive packet
966 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700967
968 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700969 """
Rich Lane91765672012-12-06 16:33:04 -0800970
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700971 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800972 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700973 exp_pkt_arg = pkt
974
Dan Talayco92c99122010-06-03 13:53:18 -0700975 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700976 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700977 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800978 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700979 assert_if.assertTrue(rcv_pkt is not None,
980 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800981 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800982 logging.debug("Expected %s" % format_packet(pkt))
983 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800984 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800985 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700986 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700987 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700988 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700989 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700990 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700991 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800992 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700993 assert_if.assertTrue(rcv_pkt is None,
994 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700995
996
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700997def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700998 """
999 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -07001000 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001001
1002 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -07001003
1004 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -07001005 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001006 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001007 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001008 exp_pkt_arg = exp_pkt
1009
Dan Talaycof6e76c02012-03-23 10:56:12 -07001010 if type(egr_ports) == type([]):
1011 egr_port_list = egr_ports
1012 else:
1013 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001014
Dan Talaycof6e76c02012-03-23 10:56:12 -07001015 # Expect a packet from each port on egr port list
1016 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001017 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001018 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001019 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001020 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001021 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001022
Dan Talaycof6e76c02012-03-23 10:56:12 -07001023 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -07001024 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001025 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001026
Dan Talaycof6e76c02012-03-23 10:56:12 -07001027 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001028 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -07001029 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001030 str(rcv_port))
1031
1032 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001033 logging.error("ERROR: Packet match failed.")
1034 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001035 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001036 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001037 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001038 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1039 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001040 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001041 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001042
Dan Talayco551befa2010-07-15 17:05:32 -07001043def match_verify(parent, req_match, res_match):
1044 """
1045 Verify flow matches agree; if they disagree, report where
1046
1047 parent must implement assertEqual
1048 Use str() to ensure content is compared and not pointers
1049 """
1050
1051 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1052 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1053 " != " + hex(res_match.wildcards))
1054 parent.assertEqual(req_match.in_port, res_match.in_port,
1055 'Match failed: in_port: ' + str(req_match.in_port) +
1056 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001057 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1058 'Match failed: eth_src: ' + str(req_match.eth_src) +
1059 " != " + str(res_match.eth_src))
1060 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1061 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1062 " != " + str(res_match.eth_dst))
1063 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1064 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1065 " != " + str(res_match.vlan_vid))
1066 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
1067 'Match failed: vlan_pcp: ' +
1068 str(req_match.vlan_pcp) + " != " +
1069 str(res_match.vlan_pcp))
1070 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1071 'Match failed: eth_type: ' + str(req_match.eth_type) +
1072 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001073
Rich Lanee717c6e2013-03-12 10:25:50 -07001074 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001075 and (req_match.eth_type == IP_ETHERTYPE)):
1076 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1077 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1078 " != " + str(res_match.ip_dscp))
1079 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1080 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1081 " != " + str(res_match.ip_proto))
1082 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1083 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1084 " != " + str(res_match.ipv4_src))
1085 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1086 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1087 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001088
Rich Lanee717c6e2013-03-12 10:25:50 -07001089 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001090 and ((req_match.ip_proto == TCP_PROTOCOL)
1091 or (req_match.ip_proto == UDP_PROTOCOL))):
1092 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
1093 'Match failed: tcp_src: ' +
1094 str(req_match.tcp_src) +
1095 " != " + str(res_match.tcp_src))
1096 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
1097 'Match failed: tcp_dst: ' +
1098 str(req_match.tcp_dst) +
1099 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001100
Ed Swierk99a74de2012-08-22 06:40:54 -07001101def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001102 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001103 if ofp.OFP_VERSION in [1, 2]:
1104 match.wildcards |= required_wildcards(parent)
1105 else:
1106 # TODO remove incompatible OXM entries
1107 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001108 return match
1109
1110def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001111 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001112 """
1113 Create a flow message
1114
1115 Match on packet with given wildcards.
1116 See flow_match_test for other parameter descriptoins
1117 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001118 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001119 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001120 """
Rich Lanef6883512013-03-11 17:00:09 -07001121 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001122 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001123 if wildcards is None:
1124 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001125 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001126 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001127 match.wildcards = wildcards
1128 match.in_port = ing_port
1129
Dan Talaycof6e76c02012-03-23 10:56:12 -07001130 if type(egr_ports) == type([]):
1131 egr_port_list = egr_ports
1132 else:
1133 egr_port_list = [egr_ports]
1134
Rich Lanee717c6e2013-03-12 10:25:50 -07001135 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001136 request.match = match
1137 request.buffer_id = 0xffffffff
1138 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001139 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001140 request.hard_timeout = 1
1141
Rich Lane400fb9b2013-10-10 17:20:54 -07001142 if ofp.OFP_VERSION == 1:
1143 actions = request.actions
1144 else:
1145 actions = []
1146 request.instructions.append(ofp.instruction.apply_actions(actions))
1147
Dan Talayco551befa2010-07-15 17:05:32 -07001148 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001149 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001150
1151 # Set up output/enqueue action if directed
1152 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001153 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001154 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001155 for egr_port in egr_port_list:
1156 act.port = egr_port
1157 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001158 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001159 elif egr_ports is not None:
1160 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001161 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001162 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001163 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001164
Rich Lane9a003812012-10-04 17:17:59 -07001165 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001166
1167 return request
1168
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001169def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001170 """
1171 Install a flow mod message in the switch
1172
1173 @param parent Must implement controller, assertEqual, assertTrue
1174 @param request The request, all set to go
1175 @param clear_table If true, clear the flow table before installing
1176 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001177
Rich Lane2014f9b2012-10-05 15:29:40 -07001178 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001179 if(clear_table_override != None):
1180 clear_table = clear_table_override
1181
1182 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001183 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001184 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001185
Rich Lane9a003812012-10-04 17:17:59 -07001186 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001187 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001188
Rich Lane3a261d52013-01-03 17:45:08 -08001189 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001190
Ed Swierk99a74de2012-08-22 06:40:54 -07001191def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001192 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001193 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001194 """
1195 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001196 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001197
1198 Run test with packet through switch from ing_port to egr_port
1199 See flow_match_test for parameter descriptions
1200 """
1201
Ed Swierk99a74de2012-08-22 06:40:54 -07001202 if wildcards is None:
1203 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001204 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001205 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001206 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001207 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001208 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001209 if exp_pkt is None:
1210 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001211
1212 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001213 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001214 action_list=action_list)
1215
1216 flow_msg_install(parent, request)
1217
Rich Lane9a003812012-10-04 17:17:59 -07001218 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001219 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001220 parent.dataplane.send(ing_port, str(pkt))
1221
Rich Lane8f45e2d2013-10-01 16:06:54 -07001222 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001223 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001224
Rich Lane89725bb2012-12-03 16:23:27 -08001225def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001226 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001227 action_list=None):
1228 """
1229 Packet-out test on single TCP packet
1230 @param egr_ports A single port or list of ports
1231
1232 Run test sending packet-out to egr_ports. The goal is to test the actions
1233 taken on the packet, not the matching which is of course irrelevant.
1234 See flow_match_test for parameter descriptions
1235 """
1236
1237 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001238 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001239 if exp_pkt is None:
1240 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001241
Rich Lanee717c6e2013-03-12 10:25:50 -07001242 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001243 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001244 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001245 msg.data = str(pkt)
1246 if action_list is not None:
1247 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001248 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001249
1250 # Set up output action
1251 if egr_ports is not None:
1252 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001253 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001254 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001255 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001256
1257 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001258 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001259
Rich Lane8f45e2d2013-10-01 16:06:54 -07001260 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001261 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001262
Dan Talaycof6e76c02012-03-23 10:56:12 -07001263def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1264 """
1265 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001266 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001267 @param of_ports List of OF port numbers
1268 @param how_many Number of ports to be added to the list
1269 @param exclude_list List of ports not to be used
1270 @returns An empty list if unable to find enough ports
1271 """
1272
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001273 if how_many == 0:
1274 return []
1275
Dan Talaycof6e76c02012-03-23 10:56:12 -07001276 count = 0
1277 egr_ports = []
1278 for egr_idx in range(len(of_ports)):
1279 if of_ports[egr_idx] not in exclude_list:
1280 egr_ports.append(of_ports[egr_idx])
1281 count += 1
1282 if count >= how_many:
1283 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001284 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001285 return []
1286
Rich Laned0478ff2013-03-11 12:46:58 -07001287def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001288 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001289 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001290 """
Rich Lane89725bb2012-12-03 16:23:27 -08001291 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001292
1293 @param max_test If > 0 no more than this number of tests are executed.
1294 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001295 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001296 @param pkt If not None, use this packet for ingress
1297 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001298 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001299 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1300 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001301 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001302 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001303 if wildcards is None:
1304 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001305 of_ports = port_map.keys()
1306 of_ports.sort()
1307 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1308 test_count = 0
1309
Dan Talaycocfa172f2012-03-23 12:03:00 -07001310 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001311 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001312
Dan Talayco551befa2010-07-15 17:05:32 -07001313 for ing_idx in range(len(of_ports)):
1314 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001315 egr_ports = get_egr_list(parent, of_ports, egr_count,
1316 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001317 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001318 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001319 if len(egr_ports) == 0:
1320 parent.assertTrue(0, "Failed to generate egress port list")
1321
1322 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001323 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001324 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001325 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001326 test_count += 1
1327 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001328 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001329 break
1330
Ed Swierk38eea082013-01-02 19:46:20 -08001331 if not test_param_get('pktout_actions', default=True):
1332 return
Rich Lane89725bb2012-12-03 16:23:27 -08001333
1334 ingress_port = of_ports[0]
1335 egr_ports = get_egr_list(parent, of_ports, egr_count,
1336 exclude_list=[ingress_port])
1337 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001338 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001339 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001340 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001341 pkt=pkt, exp_pkt=exp_pkt,
1342 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001343
Rich Lane2014f9b2012-10-05 15:29:40 -07001344def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001345 """
1346 Return value passed via test-params if present
1347
Dan Talayco4b2bee62010-07-20 14:10:05 -07001348 @param key The lookup key
1349 @param default Default value to use if not found
1350
1351 If the pair 'key=val' appeared in the string passed to --test-params
1352 on the command line, return val (as interpreted by exec). Otherwise
1353 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001354
1355 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1356 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001357 """
1358 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001359 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001360 except:
1361 return default
1362
Dan Talayco4b2bee62010-07-20 14:10:05 -07001363 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001364 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001365 except:
1366 return default
1367
1368def action_generate(parent, field_to_mod, mod_field_vals):
1369 """
1370 Create an action to modify the field indicated in field_to_mod
1371
1372 @param parent Must implement, assertTrue
1373 @param field_to_mod The field to modify as a string name
1374 @param mod_field_vals Hash of values to use for modified values
1375 """
1376
1377 act = None
1378
1379 if field_to_mod in ['pktlen']:
1380 return None
1381
Rich Laned0478ff2013-03-11 12:46:58 -07001382 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001383 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001384 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001385 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001386 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001387 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001388 elif field_to_mod == 'dl_vlan_enable':
1389 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001390 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001391 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001392 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001393 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001394 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001395 act.vlan_vid = mod_field_vals['vlan_vid']
1396 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001397 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001398 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001399 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001400 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001401 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001402 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001403 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001404 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001405 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001406 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001407 act.nw_tos = mod_field_vals['ip_tos']
1408 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001409 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001410 act.tp_port = mod_field_vals['tcp_sport']
1411 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001412 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001413 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001414 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001415 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001416 act.tp_port = mod_field_vals['udp_sport']
1417 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001418 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001419 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001420 else:
1421 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1422
1423 return act
1424
1425def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001426 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001427 """
1428 Set up the ingress and expected packet and action list for a test
1429
Rich Lane2014f9b2012-10-05 15:29:40 -07001430 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 @param start_field_values Field values to use for ingress packet (optional)
1432 @param mod_field_values Field values to use for modified packet (optional)
1433 @param mod_fields The list of fields to be modified by the switch in the test.
1434 @params check_test_params If True, will check the parameters vid, add_vlan
1435 and strip_vlan from the command line.
1436
1437 Returns a triple: pkt-to-send, expected-pkt, action-list
1438 """
1439
1440 new_actions = []
1441
Dan Talayco4b2bee62010-07-20 14:10:05 -07001442 base_pkt_params = {}
1443 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001444 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1445 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001446 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001447 base_pkt_params['vlan_vid'] = 2
1448 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001449 base_pkt_params['ip_src'] = '192.168.0.1'
1450 base_pkt_params['ip_dst'] = '192.168.0.2'
1451 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001452 if tp == "tcp":
1453 base_pkt_params['tcp_sport'] = 1234
1454 base_pkt_params['tcp_dport'] = 80
1455 elif tp == "udp":
1456 base_pkt_params['udp_sport'] = 1234
1457 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001458 for keyname in start_field_vals.keys():
1459 base_pkt_params[keyname] = start_field_vals[keyname]
1460
1461 mod_pkt_params = {}
1462 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001463 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1464 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001465 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001466 mod_pkt_params['vlan_vid'] = 3
1467 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468 mod_pkt_params['ip_src'] = '10.20.30.40'
1469 mod_pkt_params['ip_dst'] = '50.60.70.80'
1470 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001471 if tp == "tcp":
1472 mod_pkt_params['tcp_sport'] = 4321
1473 mod_pkt_params['tcp_dport'] = 8765
1474 elif tp == "udp":
1475 mod_pkt_params['udp_sport'] = 4321
1476 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477 for keyname in mod_field_vals.keys():
1478 mod_pkt_params[keyname] = mod_field_vals[keyname]
1479
1480 # Check for test param modifications
1481 strip = False
1482 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001483 add_vlan = test_param_get('add_vlan')
1484 strip_vlan = test_param_get('strip_vlan')
1485 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001486
1487 if add_vlan and strip_vlan:
1488 parent.assertTrue(0, "Add and strip VLAN both specified")
1489
1490 if vid:
1491 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001492 base_pkt_params['vlan_vid'] = vid
1493 if 'vlan_vid' in mod_fields:
1494 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495
1496 if add_vlan:
1497 base_pkt_params['dl_vlan_enable'] = False
1498 mod_pkt_params['dl_vlan_enable'] = True
1499 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1500 mod_fields.append('pktlen')
1501 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001502 if 'vlan_vid' not in mod_fields:
1503 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001504 elif strip_vlan:
1505 base_pkt_params['dl_vlan_enable'] = True
1506 mod_pkt_params['dl_vlan_enable'] = False
1507 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1508 mod_fields.append('dl_vlan_enable')
1509 mod_fields.append('pktlen')
1510
Rich Lane110e0e32012-10-26 16:21:46 -07001511 if tp == "tcp":
1512 packet_builder = simple_tcp_packet
1513 elif tp == "udp":
1514 packet_builder = simple_udp_packet
1515 else:
1516 raise NotImplementedError("unknown transport protocol %s" % tp)
1517
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001519 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520
1521 # Build the expected packet, modifying the indicated fields
1522 for item in mod_fields:
1523 base_pkt_params[item] = mod_pkt_params[item]
1524 act = action_generate(parent, item, mod_pkt_params)
1525 if act:
1526 new_actions.append(act)
1527
Rich Lane110e0e32012-10-26 16:21:46 -07001528 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001529
1530 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001531
1532# Generate a simple "drop" flow mod
1533# If in_band is true, then only drop from first test port
1534def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001535 request = ofp.message.flow_add()
1536 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001537 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001538 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001539 for of_port, ifname in port_map.items(): # Grab first port
1540 break
1541 request.match.in_port = of_port
1542 request.buffer_id = 0xffffffff
1543 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001544
1545def skip_message_emit(parent, s):
1546 """
1547 Print out a 'skipped' message to stderr
1548
1549 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001550 """
1551 global skipped_test_count
1552
1553 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001554 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001555 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001556 sys.stderr.write("(skipped) ")
1557 else:
1558 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001559
Dan Talayco8a64e332012-03-28 14:53:20 -07001560
1561def all_stats_get(parent):
1562 """
1563 Get the aggregate stats for all flows in the table
1564 @param parent Test instance with controller connection and assert
1565 @returns dict with keys flows, packets, bytes, active (flows),
1566 lookups, matched
1567 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001568 stat_req = ofp.message.aggregate_stats_request()
1569 stat_req.match = ofp.match()
1570 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001571 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001572 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001573
1574 rv = {}
1575
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001576 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001577 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001578
Rich Lane5fd6faf2013-03-11 13:30:20 -07001579 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001580 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1581 obj.packet_count, obj.byte_count)
1582 break
1583
Rich Lanee717c6e2013-03-12 10:25:50 -07001584 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001585 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001586
1587
1588 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001589 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001590 rv["active"] += obj.active_count
1591 rv["lookups"] += obj.lookup_count
1592 rv["matched"] += obj.matched_count
1593
1594 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001595
Rich Lane7744e112013-01-11 17:23:57 -08001596_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001597FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1598 for x in range(256)])
1599
1600def hex_dump_buffer(src, length=16):
1601 """
1602 Convert src to a hex dump string and return the string
1603 @param src The source buffer
1604 @param length The number of bytes shown in each line
1605 @returns A string showing the hex dump
1606 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001607 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001608 for i in xrange(0, len(src), length):
1609 chars = src[i:i+length]
1610 hex = ' '.join(["%02x" % ord(x) for x in chars])
1611 printable = ''.join(["%s" % ((ord(x) <= 127 and
1612 FILTER[ord(x)]) or '.') for x in chars])
1613 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1614 return ''.join(result)
1615
1616def format_packet(pkt):
1617 return "Packet length %d \n%s" % (len(str(pkt)),
1618 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001619
1620def inspect_packet(pkt):
1621 """
1622 Wrapper around scapy's show() method.
1623 @returns A string showing the dissected packet.
1624 """
1625 from cStringIO import StringIO
1626 out = None
1627 backup = sys.stdout
1628 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001629 tmp = StringIO()
1630 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001631 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001632 out = tmp.getvalue()
1633 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001634 finally:
1635 sys.stdout = backup
1636 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001637
1638def nonstandard(cls):
1639 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001640 Testcase decorator that marks the test as being non-standard.
1641 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001642 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001643 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001644 return cls
1645
1646def disabled(cls):
1647 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001648 Testcase decorator that marks the test as being disabled.
1649 These tests are not automatically added to the "standard" group or
1650 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001651 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001652 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001653 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001654
1655def group(name):
1656 """
1657 Testcase decorator that adds the test to a group.
1658 """
1659 def fn(cls):
1660 if not hasattr(cls, "_groups"):
1661 cls._groups = []
1662 cls._groups.append(name)
1663 return cls
1664 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001665
1666def version(ver):
1667 """
1668 Testcase decorator that specifies which versions of OpenFlow the test
1669 supports. The default is 1.0+. This decorator may only be used once.
1670
1671 Supported syntax:
1672 1.0 -> 1.0
1673 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1674 1.0+ -> 1.0, 1.1, 1.2, 1.3
1675 """
1676 versions = parse_version(ver)
1677 def fn(cls):
1678 cls._versions = versions
1679 return cls
1680 return fn
1681
1682def parse_version(ver):
1683 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1684 if re.match("^1\.\d+$", ver):
1685 versions = set([ver])
1686 elif re.match("^(1\.\d+)\+$", ver):
1687 if not ver[:-1] in allowed_versions:
1688 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1689 versions = set()
1690 if ver != "1.1+": versions.add("1.0")
1691 if ver != "1.2+": versions.add("1.1")
1692 if ver != "1.3+": versions.add("1.2")
1693 versions.add("1.3")
1694 else:
1695 versions = set(ver.split(','))
1696
1697 for version in versions:
1698 if not version in allowed_versions:
1699 raise ValueError("invalid OpenFlow version %s" % version)
1700
1701 return versions
1702
1703assert(parse_version("1.0") == set(["1.0"]))
1704assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1705assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001706
Rich Laneae3428c2013-03-07 14:37:42 -08001707def get_stats(test, req):
1708 """
1709 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1710 """
Rich Lane609194f2013-10-21 06:17:37 -07001711 msgtype = ofp.OFPT_STATS_REPLY
1712 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001713 stats = []
1714 reply, _ = test.controller.transact(req)
1715 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001716 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001717 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001718 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001719 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001720 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001721 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001722 return stats
1723
Rich Lanebd56ed62013-07-10 15:49:44 -07001724def get_flow_stats(test, match, table_id=None,
1725 out_port=None, out_group=None,
1726 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001727 """
1728 Retrieve a list of flow stats entries.
1729 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001730
1731 if table_id == None:
1732 if ofp.OFP_VERSION <= 2:
1733 table_id = 0xff
1734 else:
1735 table_id = ofp.OFPTT_ALL
1736
Rich Lanef3bc48c2013-05-03 17:39:35 -07001737 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001738 if ofp.OFP_VERSION == 1:
1739 out_port = ofp.OFPP_NONE
1740 else:
1741 out_port = ofp.OFPP_ANY
1742
1743 if out_group == None:
1744 if ofp.OFP_VERSION > 1:
1745 out_group = ofp.OFPP_ANY
1746
Rich Lanee717c6e2013-03-12 10:25:50 -07001747 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001748 table_id=table_id,
1749 out_port=out_port)
1750 if ofp.OFP_VERSION > 1:
1751 req.out_group = out_group
1752 req.cookie = cookie
1753 req.cookie_mask = cookie_mask
1754
Rich Laneae3428c2013-03-07 14:37:42 -08001755 return get_stats(test, req)
1756
Rich Lane968b6192013-03-07 15:34:43 -08001757def get_port_stats(test, port_no):
1758 """
1759 Retrieve a list of port stats entries.
1760 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001761 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001762 return get_stats(test, req)
1763
Rich Lane6a334922013-03-07 16:14:52 -08001764def get_queue_stats(test, port_no, queue_id):
1765 """
1766 Retrieve a list of queue stats entries.
1767 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001768 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001769 return get_stats(test, req)
1770
Rich Laneae3428c2013-03-07 14:37:42 -08001771def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001772 initial=[],
1773 pkts=None, bytes=None):
1774 """
1775 Verify that flow stats changed as expected.
1776
1777 Optionally takes an 'initial' list of stats entries, as returned by
1778 get_flow_stats(). If 'initial' is not given the counters are assumed to
1779 begin at 0.
1780 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001781
Rich Laneae3428c2013-03-07 14:37:42 -08001782 def accumulate(stats):
1783 pkts_acc = bytes_acc = 0
1784 for stat in stats:
1785 pkts_acc += stat.packet_count
1786 bytes_acc += stat.byte_count
1787 return (pkts_acc, bytes_acc)
1788
1789 pkts_before, bytes_before = accumulate(initial)
1790
1791 # Wait 10s for counters to update
1792 pkt_diff = byte_diff = None
1793 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001794 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001795 pkts_after, bytes_after = accumulate(stats)
1796 pkt_diff = pkts_after - pkts_before
1797 byte_diff = bytes_after - bytes_before
1798 if (pkts == None or pkt_diff >= pkts) and \
1799 (bytes == None or byte_diff >= bytes):
1800 break
Dan Talayco53724732013-03-08 23:54:02 -08001801 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001802
1803 if pkts != None:
1804 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1805
1806 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001807 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1808 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001809
Rich Lane968b6192013-03-07 15:34:43 -08001810def verify_port_stats(test, port,
1811 initial=[],
1812 tx_pkts=None, rx_pkts=None,
1813 tx_bytes=None, rx_bytes=None):
1814 """
1815 Verify that port stats changed as expected.
1816
1817 Optionally takes an 'initial' list of stats entries, as returned by
1818 get_port_stats(). If 'initial' is not given the counters are assumed to
1819 begin at 0.
1820 """
1821 def accumulate(stats):
1822 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1823 for stat in stats:
1824 tx_pkts_acc += stat.tx_packets
1825 rx_pkts_acc += stat.rx_packets
1826 tx_bytes_acc += stat.tx_bytes
1827 rx_bytes_acc += stat.rx_bytes
1828 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1829
1830 tx_pkts_before, rx_pkts_before, \
1831 tx_bytes_before, rx_bytes_before = accumulate(initial)
1832
1833 # Wait 10s for counters to update
1834 for i in range(0, 100):
1835 stats = get_port_stats(test, port)
1836 tx_pkts_after, rx_pkts_after, \
1837 tx_bytes_after, rx_bytes_after = accumulate(stats)
1838 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1839 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1840 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1841 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001842 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1843 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001844 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1845 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001846 break
1847 time.sleep(0.1)
1848
1849 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001850 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1851 "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 -08001852 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001853 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1854 "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 -08001855 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001856 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1857 "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 -08001858 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001859 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1860 "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 -08001861
Rich Lane6a334922013-03-07 16:14:52 -08001862def verify_queue_stats(test, port_no, queue_id,
1863 initial=[],
1864 pkts=None, bytes=None):
1865 """
1866 Verify that queue stats changed as expected.
1867
1868 Optionally takes an 'initial' list of stats entries, as returned by
1869 get_queue_stats(). If 'initial' is not given the counters are assumed to
1870 begin at 0.
1871 """
1872 def accumulate(stats):
1873 pkts_acc = bytes_acc = 0
1874 for stat in stats:
1875 pkts_acc += stat.tx_packets
1876 bytes_acc += stat.tx_bytes
1877 return (pkts_acc, bytes_acc)
1878
1879 pkts_before, bytes_before = accumulate(initial)
1880
1881 # Wait 10s for counters to update
1882 pkt_diff = byte_diff = None
1883 for i in range(0, 100):
1884 stats = get_queue_stats(test, port_no, queue_id)
1885 pkts_after, bytes_after = accumulate(stats)
1886 pkt_diff = pkts_after - pkts_before
1887 byte_diff = bytes_after - bytes_before
1888 if (pkts == None or pkt_diff >= pkts) and \
1889 (bytes == None or byte_diff >= bytes):
1890 break
Dan Talayco53724732013-03-08 23:54:02 -08001891 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001892
1893 if pkts != None:
1894 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1895
1896 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001897 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1898 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001899
Rich Lane4c504f32013-06-07 17:24:14 -07001900def packet_in_match(msg, data, in_port=None, reason=None):
1901 """
1902 Check whether the packet_in message 'msg' has fields matching 'data',
1903 'in_port', and 'reason'.
1904
1905 This function handles truncated packet_in data. The 'in_port' and 'reason'
1906 parameters are optional.
1907
1908 @param msg packet_in message
1909 @param data Expected packet_in data
1910 @param in_port Expected packet_in in_port, or None
1911 @param reason Expected packet_in reason, or None
1912 """
1913
Rich Lanec0d26dd2013-07-10 12:46:03 -07001914 if ofp.OFP_VERSION <= 2:
1915 pkt_in_port = msg.in_port
1916 else:
1917 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1918 if ofp.oxm.in_port in oxms:
1919 pkt_in_port = oxms[ofp.oxm.in_port].value
1920 else:
1921 logging.warn("Missing in_port in packet-in message")
1922 pkt_in_port = None
1923
1924 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001925 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001926 return False
1927
Rich Lanec0d26dd2013-07-10 12:46:03 -07001928 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001929 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1930 return False
1931
1932 # Check that one of the packets is a prefix of the other.
1933 # The received packet may be either truncated or padded, but not both.
1934 # (Some of the padding may be truncated but that's irrelevant). We
1935 # need to check that the smaller packet is a prefix of the larger one.
1936 # Note that this check succeeds if the switch sends a zero-length
1937 # packet-in.
1938 compare_len = min(len(msg.data), len(data))
1939 if data[:compare_len] != msg.data[:compare_len]:
1940 logging.debug("Incorrect packet_in data")
1941 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1942 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1943 return False
1944
1945 return True
1946
1947def verify_packet_in(test, data, in_port, reason, controller=None):
1948 """
1949 Assert that the controller receives a packet_in message matching data 'data'
1950 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1951 itself, that's up to the test case.
1952
1953 @param test Instance of base_tests.SimpleProtocol
1954 @param pkt String to expect as the packet_in data
1955 @param in_port OpenFlow port number to expect as the packet_in in_port
1956 @param reason One of OFPR_* to expect as the packet_in reason
1957 @param controller Controller instance, defaults to test.controller
1958 @returns The received packet-in message
1959 """
1960
1961 if controller == None:
1962 controller = test.controller
1963
1964 end_time = time.time() + oftest.ofutils.default_timeout
1965
1966 while True:
1967 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1968 if not msg:
1969 # Timeout
1970 break
1971 elif packet_in_match(msg, data, in_port, reason):
1972 # Found a matching message
1973 break
1974
Kiran Poola58c5c042014-05-15 15:11:06 -07001975 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001976 return msg
1977
1978def verify_no_packet_in(test, data, in_port, controller=None):
1979 """
1980 Assert that the controller does not receive a packet_in message matching
1981 data 'data' from port 'in_port'.
1982
1983 @param test Instance of base_tests.SimpleProtocol
1984 @param pkt String to expect as the packet_in data
1985 @param in_port OpenFlow port number to expect as the packet_in in_port
1986 @param controller Controller instance, defaults to test.controller
1987 """
1988
1989 if controller == None:
1990 controller = test.controller
1991
1992 # Negative test, need to wait a short amount of time before checking we
1993 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001994 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001995
1996 # Check every packet_in queued in the controller
1997 while True:
1998 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1999 if msg == None:
2000 # No more queued packet_in messages
2001 break
2002 elif packet_in_match(msg, data, in_port, None):
2003 # Found a matching message
2004 break
2005
Rich Lane82c882d2013-08-09 17:13:52 -07002006 if in_port == None:
2007 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
2008 else:
2009 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002010
Rich Lane045db072013-08-06 13:16:30 -07002011def openflow_ports(num=None):
2012 """
2013 Return a list of 'num' OpenFlow port numbers
2014
2015 If 'num' is None, return all available ports. Otherwise, limit the length
2016 of the result to 'num' and raise an exception if not enough ports are
2017 available.
2018 """
2019 ports = sorted(oftest.config["port_map"].keys())
2020 if num != None and len(ports) < num:
2021 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2022 return ports[:num]
2023
Rich Lanee4b384d2013-09-13 14:33:40 -07002024def verify_packet(test, pkt, ofport):
2025 """
2026 Check that an expected packet is received
2027 """
2028 logging.debug("Checking for pkt on port %r", ofport)
2029 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2030 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002031 return (rcv_port, rcv_pkt, pkt_time)
2032
Rich Lanee4b384d2013-09-13 14:33:40 -07002033def verify_no_packet(test, pkt, ofport):
2034 """
2035 Check that a particular packet is not received
2036 """
2037 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002038 (rcv_port, rcv_pkt, pkt_time) = \
2039 test.dataplane.poll(
2040 port_number=ofport, exp_pkt=str(pkt),
2041 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002042 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2043
2044def verify_no_other_packets(test):
2045 """
2046 Check that no unexpected packets are received
2047
2048 This is a no-op if the --relax option is in effect.
2049 """
2050 if oftest.config["relax"]:
2051 return
2052 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002053 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002054 if rcv_pkt != None:
2055 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2056 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2057
2058def verify_packets(test, pkt, ofports):
2059 """
2060 Check that a packet is received on certain ports
2061
2062 Also verifies that the packet is not received on any other ports, and that no
2063 other packets are received (unless --relax is in effect).
2064
2065 This covers the common and simplest cases for checking dataplane outputs.
2066 For more complex usage, like multiple different packets being output, or
2067 multiple packets on the same port, use the primitive verify_packet,
2068 verify_no_packet, and verify_no_other_packets functions directly.
2069 """
2070 pkt = str(pkt)
2071 for ofport in openflow_ports():
2072 if ofport in ofports:
2073 verify_packet(test, pkt, ofport)
2074 else:
2075 verify_no_packet(test, pkt, ofport)
2076 verify_no_other_packets(test)
2077
Rich Lane12d04592013-10-10 17:21:07 -07002078def verify_no_errors(ctrl):
2079 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2080 if error:
2081 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002082
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002083def verify_capability(test, capability):
2084 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002085 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002086
2087 @param test Instance of base_tests.SimpleProtocol
2088 @param capability One of ofp_capabilities.
2089 """
2090 logging.info("Verifing that capability code is valid.")
2091 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2092 "Capability code %d does not exist." % capability)
2093 capability_str = ofp.const.ofp_capabilities_map[capability]
2094
2095 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002096 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002097 req = ofp.message.features_request()
2098 res, raw = test.controller.transact(req)
2099 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2100 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2101 ("Unexpected packet type %d received in response to "
2102 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002103 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002104
Jonathan Stout641167f2014-02-04 12:07:10 -05002105 if (res.capabilities & capability) > 0:
2106 logging.info("Switch capabilities bitmask claims to support %s",
2107 capability_str)
2108 return True, res.capabilities
2109 else:
2110 logging.info("Capabilities bitmask does not support %s.",
2111 capability_str)
2112 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002113
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002114def verify_configuration_flag(test, flag):
2115 """
2116 Return True if DUT supports specified configuration flag.
2117
2118 @param test Instance of base_tests.SimpleProtocol
2119 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002120 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002121 """
2122 logging.info("Verifing that flag is valid.")
2123 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2124 "flag %s does not exist." % flag)
2125 flag_str = ofp.const.ofp_config_flags_map[flag]
2126
2127 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
2128 req = ofp.message.get_config_request()
2129 rv = test.controller.message_send(req)
2130 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2131
2132 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2133 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2134 timeout=2)
2135 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2136 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2137
2138 if res.flags == flag:
2139 logging.info("%s flag is set.", flag_str)
2140 return True, res.flags
2141 else:
2142 logging.info("%s flag is not set.", flag_str)
2143 return False, res.flags
2144
Rich Lane7744e112013-01-11 17:23:57 -08002145__all__ = list(set(locals()) - _import_blacklist)