blob: 7c6978baf1e35ba47a1abc82feee3bc77a07144d [file] [log] [blame]
Dan Talaycod2ca1032010-03-10 14:40:26 -08001import sys
Dan Talayco92c99122010-06-03 13:53:18 -07002import copy
Rich Lane6242d9f2013-01-06 17:35:39 -08003import logging
4import types
5import time
Rich Lane5a9a1922013-01-11 14:29:30 -08006import re
Rich Lanea68176f2013-08-09 17:41:05 -07007import packet as scapy
Dan Talayco41eae8b2010-03-10 13:57:06 -08008
Rich Lanecd97d3d2013-01-07 18:50:06 -08009import oftest
10import oftest.controller
11import oftest.dataplane
Rich Lanef6883512013-03-11 17:00:09 -070012import oftest.parse
Rich Lane4c504f32013-06-07 17:24:14 -070013import oftest.ofutils
Rich Lanee717c6e2013-03-12 10:25:50 -070014import ofp
Dan Talaycoc901f4d2010-03-07 21:55:45 -080015
Dan Talaycoba3745c2010-07-21 21:51:08 -070016global skipped_test_count
17skipped_test_count = 0
18
Rich Lane7744e112013-01-11 17:23:57 -080019_import_blacklist = set(locals().keys())
20
Dan Talayco551befa2010-07-15 17:05:32 -070021# Some useful defines
22IP_ETHERTYPE = 0x800
23TCP_PROTOCOL = 0x6
24UDP_PROTOCOL = 0x11
25
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000026MINSIZE = 0
27
Tony van der Peet80c5b202013-11-20 11:47:48 +130028def delete_all_flows(ctrl, send_barrier=True):
Dan Talayco41eae8b2010-03-10 13:57:06 -080029 """
30 Delete all flows on the switch
31 @param ctrl The controller object for the test
Tony van der Peet80c5b202013-11-20 11:47:48 +130032 @param send_barrier Whether or not to send a barrier message
Dan Talayco41eae8b2010-03-10 13:57:06 -080033 """
34
Rich Lane9a003812012-10-04 17:17:59 -070035 logging.info("Deleting all flows")
Rich Lanee717c6e2013-03-12 10:25:50 -070036 msg = ofp.message.flow_delete()
Rich Lanec717f442013-06-13 15:49:09 -070037 if ofp.OFP_VERSION in [1, 2]:
38 msg.match.wildcards = ofp.OFPFW_ALL
39 msg.out_port = ofp.OFPP_NONE
40 msg.buffer_id = 0xffffffff
41 elif ofp.OFP_VERSION >= 3:
42 msg.table_id = ofp.OFPTT_ALL
43 msg.buffer_id = ofp.OFP_NO_BUFFER
44 msg.out_port = ofp.OFPP_ANY
45 msg.out_group = ofp.OFPG_ANY
Rich Lane5c3151c2013-01-03 17:15:41 -080046 ctrl.message_send(msg)
Tony van der Peet80c5b202013-11-20 11:47:48 +130047 if send_barrier:
48 do_barrier(ctrl)
Rich Lane32bf9482013-01-03 17:26:30 -080049 return 0 # for backwards compatibility
Dan Talayco41eae8b2010-03-10 13:57:06 -080050
Rich Lane5f3c9b22013-10-10 17:20:30 -070051def delete_all_groups(ctrl):
52 """
53 Delete all groups on the switch
54 @param ctrl The controller object for the test
55 """
56
57 logging.info("Deleting all groups")
Rich Lane5de5e632013-11-24 10:15:25 -080058 msg = ofp.message.group_delete(group_id=ofp.OFPG_ALL)
Rich Lane5f3c9b22013-10-10 17:20:30 -070059 ctrl.message_send(msg)
60 do_barrier(ctrl)
61
Ed Swierk99a74de2012-08-22 06:40:54 -070062def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070063 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070064 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -070065 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
66 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -070067 else:
68 return 0
69
macauley_cheng0a0a7f62015-11-06 11:36:50 +080070def simple_packet(content='00 00 00 11 33 55 00 00 00 11 22 33 81 00 00 03 '
71 '08 00 45 00 00 2e 04 d2 00 00 7f 00 b2 47 c0 a8 '
72 '01 64 c0 a8 02 02 00 00 00 00 00 00 00 00 00 00 '
73 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'):
macauley_cheng739f54b2015-11-09 13:52:59 +080074
75 pkt = ''.join(content.split(" ")).decode('hex')
macauley_chengc80249d2015-11-09 14:11:18 +080076 pkt = scapy.Ether(pkt)
macauley_cheng739f54b2015-11-09 13:52:59 +080077 if len(pkt) < 64:
78 pkt = pkt/("D" * (64 - len(pkt)))
macauley_chengc80249d2015-11-09 14:11:18 +080079 #scapy.hexdump(pkt)
macauley_cheng0a0a7f62015-11-06 11:36:50 +080080 return pkt
81
Dan Talayco41eae8b2010-03-10 13:57:06 -080082def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -070083 eth_dst='00:01:02:03:04:05',
84 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070085 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -070086 vlan_vid=0,
87 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -070088 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -080089 ip_src='192.168.0.1',
90 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070091 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -080092 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -080093 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070094 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -070095 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070096 ip_ihl=None,
97 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -080098 ):
99 """
100 Return a simple dataplane TCP packet
101
102 Supports a few parameters:
103 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700104 @param eth_dst Destinatino MAC
105 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700106 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700107 @param vlan_vid VLAN ID
108 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800109 @param ip_src IP source
110 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700111 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800112 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800113 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700114 @param tcp_sport TCP source port
115 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800116
117 Generates a simple TCP request. Users
118 shouldn't assume anything about this packet other than that
119 it is a valid ethernet/IP/TCP frame.
120 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000121
122 if MINSIZE > pktlen:
123 pktlen = MINSIZE
124
Dan Talayco551befa2010-07-15 17:05:32 -0700125 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800126 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700127 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
128 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800129 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700130 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700131 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700132 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700133 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800134 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700135 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700136 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700137 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800138 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 -0700139 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700140
Dan Talayco41eae8b2010-03-10 13:57:06 -0800141 pkt = pkt/("D" * (pktlen - len(pkt)))
142
143 return pkt
144
Rich Lane86aceb02013-07-17 18:45:38 -0700145def simple_tcpv6_packet(pktlen=100,
146 eth_dst='00:01:02:03:04:05',
147 eth_src='00:06:07:08:09:0a',
148 dl_vlan_enable=False,
149 vlan_vid=0,
150 vlan_pcp=0,
151 ipv6_src='2001:db8:85a3::8a2e:370:7334',
152 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
153 ipv6_tc=0,
154 ipv6_hlim=64,
155 ipv6_fl=0,
156 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700157 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700158 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700159 """
160 Return a simple IPv6/TCP packet
161
162 Supports a few parameters:
163 @param len Length of packet in bytes w/o CRC
164 @param eth_dst Destination MAC
165 @param eth_src Source MAC
166 @param dl_vlan_enable True if the packet is with vlan, False otherwise
167 @param vlan_vid VLAN ID
168 @param vlan_pcp VLAN priority
169 @param ipv6_src IPv6 source
170 @param ipv6_dst IPv6 destination
171 @param ipv6_tc IPv6 traffic class
172 @param ipv6_ttl IPv6 hop limit
173 @param ipv6_fl IPv6 flow label
174 @param tcp_dport TCP destination port
175 @param tcp_sport TCP source port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700176 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700177
178 Generates a simple TCP request. Users shouldn't assume anything about this
179 packet other than that it is a valid ethernet/IPv6/TCP frame.
180 """
181
182 if MINSIZE > pktlen:
183 pktlen = MINSIZE
184
185 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
186 if dl_vlan_enable or vlan_vid or vlan_pcp:
187 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
188 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 -0700189 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700190 pkt /= ("D" * (pktlen - len(pkt)))
191
192 return pkt
193
Rich Lane6ee7bea2012-10-26 16:19:29 -0700194def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700195 eth_dst='00:01:02:03:04:05',
196 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700197 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700198 vlan_vid=0,
199 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700200 dl_vlan_cfi=0,
201 ip_src='192.168.0.1',
202 ip_dst='192.168.0.2',
203 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800204 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700205 udp_sport=1234,
206 udp_dport=80,
207 ip_ihl=None,
208 ip_options=False
209 ):
210 """
211 Return a simple dataplane UDP packet
212
213 Supports a few parameters:
214 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700215 @param eth_dst Destination MAC
216 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700217 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700218 @param vlan_vid VLAN ID
219 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700220 @param ip_src IP source
221 @param ip_dst IP destination
222 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800223 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700224 @param udp_dport UDP destination port
225 @param udp_sport UDP source port
226
227 Generates a simple UDP packet. Users shouldn't assume anything about
228 this packet other than that it is a valid ethernet/IP/UDP frame.
229 """
230
231 if MINSIZE > pktlen:
232 pktlen = MINSIZE
233
234 # Note Dot1Q.id is really CFI
235 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700236 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
237 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800238 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700239 scapy.UDP(sport=udp_sport, dport=udp_dport)
240 else:
241 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700242 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800243 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700244 scapy.UDP(sport=udp_sport, dport=udp_dport)
245 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700246 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800247 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 -0700248 scapy.UDP(sport=udp_sport, dport=udp_dport)
249
250 pkt = pkt/("D" * (pktlen - len(pkt)))
251
252 return pkt
253
macauley_chengb0ec33d2015-09-04 11:32:44 +0800254
255def simple_tcp_packet_two_vlan(pktlen=100,
256 eth_dst='00:01:02:03:04:05',
257 eth_src='00:06:07:08:09:0a',
258 out_dl_vlan_enable=False,
259 in_dl_vlan_enable=False,
260 out_vlan_vid=0,
261 out_vlan_pcp=0,
262 out_dl_vlan_cfi=0,
263 in_vlan_vid=0,
264 in_vlan_pcp=0,
265 in_dl_vlan_cfi=0,
266 ip_src='192.168.0.1',
267 ip_dst='192.168.0.2',
268 ip_tos=0,
269 ip_ttl=64,
270 tcp_sport=1234,
271 tcp_dport=80,
272 tcp_flags="S",
273 ip_ihl=None,
274 ip_options=False
275 ):
276 """
277 Return a simple dataplane TCP packet
278
279 Supports a few parameters:
280 @param len Length of packet in bytes w/o CRC
281 @param eth_dst Destinatino MAC
282 @param eth_src Source MAC
283 @param dl_vlan_enable True if the packet is with vlan, False otherwise
284 @param vlan_vid VLAN ID
285 @param vlan_pcp VLAN priority
286 @param ip_src IP source
287 @param ip_dst IP destination
288 @param ip_tos IP ToS
289 @param ip_ttl IP TTL
290 @param tcp_dport TCP destination port
291 @param tcp_sport TCP source port
292 @param tcp_flags TCP Control flags
293
294 Generates a simple TCP request. Users
295 shouldn't assume anything about this packet other than that
296 it is a valid ethernet/IP/TCP frame.
297 """
298
299 if MINSIZE > pktlen:
300 pktlen = MINSIZE
301
302 # Note Dot1Q.id is really CFI
303 if (out_dl_vlan_enable and in_dl_vlan_enable):
304 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
305 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
306
307 if in_dl_vlan_enable:
308 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
309
310 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
311 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
312 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
313 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
314 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
315 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
316 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
317 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
318 assert(0) #shall not have this caes
319 else:
320 if not ip_options:
321 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
322 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
323 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
324 else:
325 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
326 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
327 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
328
329 pkt = pkt/("D" * (pktlen - len(pkt)))
330
331 return pkt
332
macauley17cd60d2015-07-27 17:41:18 +0800333def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
334 eth_src='00:06:07:08:09:0a',
335 dl_vlan_enable=False,
336 vlan_vid=0,
337 vlan_pcp=0,
338 dl_vlan_cfi=0,
339 ip_src='192.168.0.1',
340 ip_dst='192.168.0.2',
341 ip_tos=0,
342 ip_ttl=64,
343 udp_sport=1234,
344 udp_dport=4789,
345 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800346 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800347 ip_ihl=None,
348 ip_options=False
349 ):
350 """
351 Return a simple dataplane UDP packet
352
353 Supports a few parameters:
354 @param len Length of packet in bytes w/o CRC
355 @param eth_dst Destination MAC
356 @param eth_src Source MAC
357 @param dl_vlan_enable True if the packet is with vlan, False otherwise
358 @param vlan_vid VLAN ID
359 @param vlan_pcp VLAN priority
360 @param ip_src IP source
361 @param ip_dst IP destination
362 @param ip_tos IP ToS
363 @param ip_ttl IP TTL
364 @param udp_dport UDP destination port
365 @param udp_sport UDP source port
366 @param inner_pyload inner pacekt content
367 Generates a simple UDP packet. Users shouldn't assume anything about
368 this packet other than that it is a valid ethernet/IP/UDP frame.
369 """
370
371 # Note Dot1Q.id is really CFI
372 if (dl_vlan_enable):
373 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
374 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
375 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
376 scapy.UDP(sport=udp_sport, dport=udp_dport)
377 else:
378 if not ip_options:
379 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
380 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
381 scapy.UDP(sport=udp_sport, dport=udp_dport)
382 else:
383 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
384 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
385 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800386
macauley17cd60d2015-07-27 17:41:18 +0800387 #add vxlan header
388 pkt = pkt/scapy.VXLAN(vni=vnid)
389 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800390 if inner_payload!=None:
391 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800392
393 return pkt
394
Flavio Castro72a45d52015-12-02 16:37:05 -0500395def mpls_packet(pktlen=100,
396 eth_dst='00:01:02:03:04:05',
397 eth_src='00:06:07:08:09:0a',
398 dl_vlan_enable=False,
399 vlan_vid=0,
400 vlan_pcp=0,
401 dl_vlan_cfi=0,
402 ip_src='192.168.0.1',
403 ip_dst='192.168.0.2',
404 ip_tos=0,
405 ip_ttl=64,
406 tcp_sport=1234,
407 tcp_dport=80,
408 tcp_flags="S",
409 ip_ihl=None,
410 ip_options=False,
411 label=None,
412 inner_payload=None
413 ):
414 if MINSIZE > pktlen:
415 pktlen = MINSIZE
416
417 # Note Dot1Q.id is really CFI
418 if (dl_vlan_enable):
419 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
420 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
421 else:
422 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
423
424 #add MPLS header
425 for i in range(len(label)):
426 l,c,s,t=label[i]
427 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
428
429 #add innder payload
430 if inner_payload!=None:
431 pkt=pkt / \
432 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
433 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
434
435 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800436
437def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
438 eth_src='00:06:07:08:09:0a',
439 dl_vlan_enable=False,
440 vlan_vid=0,
441 vlan_pcp=0,
442 dl_vlan_cfi=0,
443 label=None,
444 inner_payload=None
445 ):
446 """
447 Return a simple dataplane MPLS packet
448
449 Supports a few parameters:
450 @param len Length of packet in bytes w/o CRC
451 @param eth_dst Destination MAC
452 @param eth_src Source MAC
453 @param dl_vlan_enable True if the packet is with vlan, False otherwise
454 @param vlan_vid VLAN ID
455 @param vlan_pcp VLAN priority
456 @param inner_pyload inner pacekt content
457 Generates a simple MPLS packet. Users shouldn't assume anything about
458 this packet other than that it is a valid ethernet/IP/UDP frame.
459 """
460
461 # Note Dot1Q.id is really CFI
462 if (dl_vlan_enable):
463 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
464 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
465 else:
466 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
467
468 #add MPLS header
469 for i in range(len(label)):
470 l,c,s,t=label[i]
471 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
472
473 #add innder payload
474 if inner_payload!=None:
475 pkt=pkt/inner_payload
476
477 return pkt
478
Rich Lane86aceb02013-07-17 18:45:38 -0700479def simple_udpv6_packet(pktlen=100,
480 eth_dst='00:01:02:03:04:05',
481 eth_src='00:06:07:08:09:0a',
482 dl_vlan_enable=False,
483 vlan_vid=0,
484 vlan_pcp=0,
485 ipv6_src='2001:db8:85a3::8a2e:370:7334',
486 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
487 ipv6_tc=0,
488 ipv6_hlim=64,
489 ipv6_fl=0,
490 udp_sport=1234,
491 udp_dport=80):
492 """
493 Return a simple IPv6/UDP packet
494
495 Supports a few parameters:
496 @param len Length of packet in bytes w/o CRC
497 @param eth_dst Destination MAC
498 @param eth_src Source MAC
499 @param dl_vlan_enable True if the packet is with vlan, False otherwise
500 @param vlan_vid VLAN ID
501 @param vlan_pcp VLAN priority
502 @param ipv6_src IPv6 source
503 @param ipv6_dst IPv6 destination
504 @param ipv6_tc IPv6 traffic class
505 @param ipv6_ttl IPv6 hop limit
506 @param ipv6_fl IPv6 flow label
507 @param udp_dport UDP destination port
508 @param udp_sport UDP source port
509
510 Generates a simple UDP request. Users shouldn't assume anything about this
511 packet other than that it is a valid ethernet/IPv6/UDP frame.
512 """
513
514 if MINSIZE > pktlen:
515 pktlen = MINSIZE
516
517 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
518 if dl_vlan_enable or vlan_vid or vlan_pcp:
519 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
520 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
521 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
522 pkt /= ("D" * (pktlen - len(pkt)))
523
524 return pkt
525
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700526def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700527 eth_dst='00:01:02:03:04:05',
528 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700529 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700530 vlan_vid=0,
531 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700532 ip_src='192.168.0.1',
533 ip_dst='192.168.0.2',
534 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800535 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600536 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700537 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600538 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600539 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700540 """
541 Return a simple ICMP packet
542
543 Supports a few parameters:
544 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700545 @param eth_dst Destinatino MAC
546 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700547 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700548 @param vlan_vid VLAN ID
549 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700550 @param ip_src IP source
551 @param ip_dst IP destination
552 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800553 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600554 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700555 @param icmp_type ICMP type
556 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600557 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700558
559 Generates a simple ICMP ECHO REQUEST. Users
560 shouldn't assume anything about this packet other than that
561 it is a valid ethernet/ICMP frame.
562 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000563
564 if MINSIZE > pktlen:
565 pktlen = MINSIZE
566
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700567 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700568 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
569 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600570 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600571 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700572 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700573 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600574 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600575 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700576
577 pkt = pkt/("0" * (pktlen - len(pkt)))
578
579 return pkt
580
Rich Lane86aceb02013-07-17 18:45:38 -0700581def simple_icmpv6_packet(pktlen=100,
582 eth_dst='00:01:02:03:04:05',
583 eth_src='00:06:07:08:09:0a',
584 dl_vlan_enable=False,
585 vlan_vid=0,
586 vlan_pcp=0,
587 ipv6_src='2001:db8:85a3::8a2e:370:7334',
588 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
589 ipv6_tc=0,
590 ipv6_hlim=64,
591 ipv6_fl=0,
592 icmp_type=8,
593 icmp_code=0):
594 """
595 Return a simple ICMPv6 packet
596
597 Supports a few parameters:
598 @param len Length of packet in bytes w/o CRC
599 @param eth_dst Destination MAC
600 @param eth_src Source MAC
601 @param dl_vlan_enable True if the packet is with vlan, False otherwise
602 @param vlan_vid VLAN ID
603 @param vlan_pcp VLAN priority
604 @param ipv6_src IPv6 source
605 @param ipv6_dst IPv6 destination
606 @param ipv6_tc IPv6 traffic class
607 @param ipv6_ttl IPv6 hop limit
608 @param ipv6_fl IPv6 flow label
609 @param icmp_type ICMP type
610 @param icmp_code ICMP code
611
612 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
613 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
614 """
615
616 if MINSIZE > pktlen:
617 pktlen = MINSIZE
618
619 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
620 if dl_vlan_enable or vlan_vid or vlan_pcp:
621 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
622 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
623 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
624 pkt /= ("D" * (pktlen - len(pkt)))
625
626 return pkt
627
Shudong Zhouc7562b12013-02-06 01:12:18 -0800628def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700629 eth_dst='ff:ff:ff:ff:ff:ff',
630 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800631 vlan_vid=0,
632 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800633 arp_op=1,
634 ip_snd='192.168.0.1',
635 ip_tgt='192.168.0.2',
636 hw_snd='00:06:07:08:09:0a',
637 hw_tgt='00:00:00:00:00:00',
638 ):
639 """
640 Return a simple ARP packet
641
642 Supports a few parameters:
643 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700644 @param eth_dst Destinatino MAC
645 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800646 @param arp_op Operation (1=request, 2=reply)
647 @param ip_snd Sender IP
648 @param ip_tgt Target IP
649 @param hw_snd Sender hardware address
650 @param hw_tgt Target hardware address
651
652 Generates a simple ARP REQUEST. Users
653 shouldn't assume anything about this packet other than that
654 it is a valid ethernet/ARP frame.
655 """
656
657 if MINSIZE > pktlen:
658 pktlen = MINSIZE
659
Rich Lanee01611f2014-01-15 14:55:11 -0800660 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
661 if vlan_vid or vlan_pcp:
662 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
663 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 -0800664
Rich Laned459ce52014-01-24 12:09:54 -0800665 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800666
667 return pkt
668
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700669def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800670 eth_dst='00:01:02:03:04:05',
671 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700672 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000673
674 if MINSIZE > pktlen:
675 pktlen = MINSIZE
676
Rich Laned0478ff2013-03-11 12:46:58 -0700677 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700678
679 pkt = pkt/("0" * (pktlen - len(pkt)))
680
681 return pkt
682
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800683def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700684 eth_dst='00:01:02:03:04:05',
685 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800686 dl_vlan_outer=20,
687 dl_vlan_pcp_outer=0,
688 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700689 vlan_vid=10,
690 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800691 dl_vlan_cfi=0,
692 ip_src='192.168.0.1',
693 ip_dst='192.168.0.2',
694 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800695 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800696 tcp_sport=1234,
697 tcp_dport=80,
698 ip_ihl=None,
699 ip_options=False
700 ):
701 """
702 Return a doubly tagged dataplane TCP packet
703
704 Supports a few parameters:
705 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700706 @param eth_dst Destinatino MAC
707 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800708 @param dl_vlan_outer Outer VLAN ID
709 @param dl_vlan_pcp_outer Outer VLAN priority
710 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700711 @param vlan_vid Inner VLAN ID
712 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800713 @param dl_vlan_cfi VLAN cfi bit
714 @param ip_src IP source
715 @param ip_dst IP destination
716 @param ip_tos IP ToS
717 @param tcp_dport TCP destination port
718 @param ip_sport TCP source port
719
720 Generates a TCP request. Users
721 shouldn't assume anything about this packet other than that
722 it is a valid ethernet/IP/TCP frame.
723 """
724
725 if MINSIZE > pktlen:
726 pktlen = MINSIZE
727
728 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700729 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800730 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700731 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800732 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800733 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
734
735 pkt = pkt/("D" * (pktlen - len(pkt)))
736
737 return pkt
738
Shudong Zhoub7f12462012-11-20 13:01:12 -0800739def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700740 """
741 Do a barrier command
742 Return 0 on success, -1 on error
743 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700744 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800745 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800746 if resp is None:
747 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700748 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800749 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700750
Rich Lane9a003812012-10-04 17:17:59 -0700751def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700752 """
753 Get a port's configuration
754
755 Gets the switch feature configuration and grabs one port's
756 configuration
757
758 @returns (hwaddr, config, advert) The hwaddress, configuration and
759 advertised values
760 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700761
762 if ofp.OFP_VERSION <= 3:
763 request = ofp.message.features_request()
764 reply, _ = controller.transact(request)
765 if reply is None:
766 logging.warn("Get feature request failed")
767 return None, None, None
768 logging.debug(reply.show())
769 ports = reply.ports
770 else:
771 request = ofp.message.port_desc_stats_request()
772 # TODO do multipart correctly
773 reply, _ = controller.transact(request)
774 if reply is None:
775 logging.warn("Port desc stats request failed")
776 return None, None, None
777 logging.debug(reply.show())
778 ports = reply.entries
779
780 for port in ports:
781 if port.port_no == port_no:
782 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700783
Rich Lane9a003812012-10-04 17:17:59 -0700784 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700785 return None, None, None
786
Rich Lane9a003812012-10-04 17:17:59 -0700787def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700788 """
789 Set the port configuration according the given parameters
790
791 Gets the switch feature configuration and updates one port's
792 configuration value according to config and mask
793 """
Rich Lane9a003812012-10-04 17:17:59 -0700794 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700795
796 hw_addr, _, _ = port_config_get(controller, port_no)
797
Rich Lanee717c6e2013-03-12 10:25:50 -0700798 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700799 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700800 if hw_addr != None:
801 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700802 mod.config = config
803 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700804 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800805 controller.message_send(mod)
806 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700807
Rich Lane2014f9b2012-10-05 15:29:40 -0700808def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700809 """
810 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700811 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700812 @param pkt Expected packet; may be None if yes_ports is empty
813 @param yes_ports Set or list of ports that should recieve packet
814 @param no_ports Set or list of ports that should not receive packet
815 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700816
817 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700818 """
Rich Lane91765672012-12-06 16:33:04 -0800819
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700820 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800821 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700822 exp_pkt_arg = pkt
823
Dan Talayco92c99122010-06-03 13:53:18 -0700824 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700825 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700826 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800827 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700828 assert_if.assertTrue(rcv_pkt is not None,
829 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800830 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800831 logging.debug("Expected %s" % format_packet(pkt))
832 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800833 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800834 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700835 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700836 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700837 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700838 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700839 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700840 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800841 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700842 assert_if.assertTrue(rcv_pkt is None,
843 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700844
845
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700846def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700847 """
848 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700849 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700850
851 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700852
853 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700854 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700855 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800856 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700857 exp_pkt_arg = exp_pkt
858
Dan Talaycof6e76c02012-03-23 10:56:12 -0700859 if type(egr_ports) == type([]):
860 egr_port_list = egr_ports
861 else:
862 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700863
Dan Talaycof6e76c02012-03-23 10:56:12 -0700864 # Expect a packet from each port on egr port list
865 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700866 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -0700867 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700868 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700869 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700870 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700871
Dan Talaycof6e76c02012-03-23 10:56:12 -0700872 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700873 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700874 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700875
Dan Talaycof6e76c02012-03-23 10:56:12 -0700876 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700877 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700878 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700879 str(rcv_port))
880
881 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700882 logging.error("ERROR: Packet match failed.")
883 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700884 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700885 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700886 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700887 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
888 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700889 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700890 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700891
Dan Talayco551befa2010-07-15 17:05:32 -0700892def match_verify(parent, req_match, res_match):
893 """
894 Verify flow matches agree; if they disagree, report where
895
896 parent must implement assertEqual
897 Use str() to ensure content is compared and not pointers
898 """
899
900 parent.assertEqual(req_match.wildcards, res_match.wildcards,
901 'Match failed: wildcards: ' + hex(req_match.wildcards) +
902 " != " + hex(res_match.wildcards))
903 parent.assertEqual(req_match.in_port, res_match.in_port,
904 'Match failed: in_port: ' + str(req_match.in_port) +
905 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -0700906 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
907 'Match failed: eth_src: ' + str(req_match.eth_src) +
908 " != " + str(res_match.eth_src))
909 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
910 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
911 " != " + str(res_match.eth_dst))
912 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
913 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
914 " != " + str(res_match.vlan_vid))
915 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
916 'Match failed: vlan_pcp: ' +
917 str(req_match.vlan_pcp) + " != " +
918 str(res_match.vlan_pcp))
919 parent.assertEqual(req_match.eth_type, res_match.eth_type,
920 'Match failed: eth_type: ' + str(req_match.eth_type) +
921 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -0700922
Rich Lanee717c6e2013-03-12 10:25:50 -0700923 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -0700924 and (req_match.eth_type == IP_ETHERTYPE)):
925 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
926 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
927 " != " + str(res_match.ip_dscp))
928 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
929 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
930 " != " + str(res_match.ip_proto))
931 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
932 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
933 " != " + str(res_match.ipv4_src))
934 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
935 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
936 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700937
Rich Lanee717c6e2013-03-12 10:25:50 -0700938 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -0700939 and ((req_match.ip_proto == TCP_PROTOCOL)
940 or (req_match.ip_proto == UDP_PROTOCOL))):
941 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
942 'Match failed: tcp_src: ' +
943 str(req_match.tcp_src) +
944 " != " + str(res_match.tcp_src))
945 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
946 'Match failed: tcp_dst: ' +
947 str(req_match.tcp_dst) +
948 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700949
Ed Swierk99a74de2012-08-22 06:40:54 -0700950def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -0700951 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -0700952 if ofp.OFP_VERSION in [1, 2]:
953 match.wildcards |= required_wildcards(parent)
954 else:
955 # TODO remove incompatible OXM entries
956 pass
Ed Swierk99a74de2012-08-22 06:40:54 -0700957 return match
958
959def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700960 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700961 """
962 Create a flow message
963
964 Match on packet with given wildcards.
965 See flow_match_test for other parameter descriptoins
966 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -0700967 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700968 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700969 """
Rich Lanef6883512013-03-11 17:00:09 -0700970 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -0700971 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -0700972 if wildcards is None:
973 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -0700974 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -0700975 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -0700976 match.wildcards = wildcards
977 match.in_port = ing_port
978
Dan Talaycof6e76c02012-03-23 10:56:12 -0700979 if type(egr_ports) == type([]):
980 egr_port_list = egr_ports
981 else:
982 egr_port_list = [egr_ports]
983
Rich Lanee717c6e2013-03-12 10:25:50 -0700984 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -0700985 request.match = match
986 request.buffer_id = 0xffffffff
987 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -0700988 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -0700989 request.hard_timeout = 1
990
Rich Lane400fb9b2013-10-10 17:20:54 -0700991 if ofp.OFP_VERSION == 1:
992 actions = request.actions
993 else:
994 actions = []
995 request.instructions.append(ofp.instruction.apply_actions(actions))
996
Dan Talayco551befa2010-07-15 17:05:32 -0700997 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -0700998 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -0700999
1000 # Set up output/enqueue action if directed
1001 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001002 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001003 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001004 for egr_port in egr_port_list:
1005 act.port = egr_port
1006 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001007 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001008 elif egr_ports is not None:
1009 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001010 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001011 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001012 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001013
Rich Lane9a003812012-10-04 17:17:59 -07001014 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001015
1016 return request
1017
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001018def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001019 """
1020 Install a flow mod message in the switch
1021
1022 @param parent Must implement controller, assertEqual, assertTrue
1023 @param request The request, all set to go
1024 @param clear_table If true, clear the flow table before installing
1025 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001026
Rich Lane2014f9b2012-10-05 15:29:40 -07001027 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001028 if(clear_table_override != None):
1029 clear_table = clear_table_override
1030
1031 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001032 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001033 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001034
Rich Lane9a003812012-10-04 17:17:59 -07001035 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001036 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001037
Rich Lane3a261d52013-01-03 17:45:08 -08001038 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001039
Ed Swierk99a74de2012-08-22 06:40:54 -07001040def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001041 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001042 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001043 """
1044 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001045 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001046
1047 Run test with packet through switch from ing_port to egr_port
1048 See flow_match_test for parameter descriptions
1049 """
1050
Ed Swierk99a74de2012-08-22 06:40:54 -07001051 if wildcards is None:
1052 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001053 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001054 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001055 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001056 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001057 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001058 if exp_pkt is None:
1059 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001060
1061 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001062 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001063 action_list=action_list)
1064
1065 flow_msg_install(parent, request)
1066
Rich Lane9a003812012-10-04 17:17:59 -07001067 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001068 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001069 parent.dataplane.send(ing_port, str(pkt))
1070
Rich Lane8f45e2d2013-10-01 16:06:54 -07001071 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001072 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001073
Rich Lane89725bb2012-12-03 16:23:27 -08001074def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001075 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001076 action_list=None):
1077 """
1078 Packet-out test on single TCP packet
1079 @param egr_ports A single port or list of ports
1080
1081 Run test sending packet-out to egr_ports. The goal is to test the actions
1082 taken on the packet, not the matching which is of course irrelevant.
1083 See flow_match_test for parameter descriptions
1084 """
1085
1086 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001087 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001088 if exp_pkt is None:
1089 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001090
Rich Lanee717c6e2013-03-12 10:25:50 -07001091 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001092 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001093 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001094 msg.data = str(pkt)
1095 if action_list is not None:
1096 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001097 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001098
1099 # Set up output action
1100 if egr_ports is not None:
1101 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001102 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001103 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001104 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001105
1106 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001107 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001108
Rich Lane8f45e2d2013-10-01 16:06:54 -07001109 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001110 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001111
Dan Talaycof6e76c02012-03-23 10:56:12 -07001112def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1113 """
1114 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001115 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001116 @param of_ports List of OF port numbers
1117 @param how_many Number of ports to be added to the list
1118 @param exclude_list List of ports not to be used
1119 @returns An empty list if unable to find enough ports
1120 """
1121
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001122 if how_many == 0:
1123 return []
1124
Dan Talaycof6e76c02012-03-23 10:56:12 -07001125 count = 0
1126 egr_ports = []
1127 for egr_idx in range(len(of_ports)):
1128 if of_ports[egr_idx] not in exclude_list:
1129 egr_ports.append(of_ports[egr_idx])
1130 count += 1
1131 if count >= how_many:
1132 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001133 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001134 return []
1135
Rich Laned0478ff2013-03-11 12:46:58 -07001136def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001137 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001138 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001139 """
Rich Lane89725bb2012-12-03 16:23:27 -08001140 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001141
1142 @param max_test If > 0 no more than this number of tests are executed.
1143 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001144 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001145 @param pkt If not None, use this packet for ingress
1146 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001147 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001148 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1149 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001150 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001151 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001152 if wildcards is None:
1153 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001154 of_ports = port_map.keys()
1155 of_ports.sort()
1156 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1157 test_count = 0
1158
Dan Talaycocfa172f2012-03-23 12:03:00 -07001159 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001160 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001161
Dan Talayco551befa2010-07-15 17:05:32 -07001162 for ing_idx in range(len(of_ports)):
1163 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001164 egr_ports = get_egr_list(parent, of_ports, egr_count,
1165 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001166 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001167 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001168 if len(egr_ports) == 0:
1169 parent.assertTrue(0, "Failed to generate egress port list")
1170
1171 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001172 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001173 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001174 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001175 test_count += 1
1176 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001177 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001178 break
1179
Ed Swierk38eea082013-01-02 19:46:20 -08001180 if not test_param_get('pktout_actions', default=True):
1181 return
Rich Lane89725bb2012-12-03 16:23:27 -08001182
1183 ingress_port = of_ports[0]
1184 egr_ports = get_egr_list(parent, of_ports, egr_count,
1185 exclude_list=[ingress_port])
1186 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001187 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001188 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001189 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001190 pkt=pkt, exp_pkt=exp_pkt,
1191 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001192
Rich Lane2014f9b2012-10-05 15:29:40 -07001193def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001194 """
1195 Return value passed via test-params if present
1196
Dan Talayco4b2bee62010-07-20 14:10:05 -07001197 @param key The lookup key
1198 @param default Default value to use if not found
1199
1200 If the pair 'key=val' appeared in the string passed to --test-params
1201 on the command line, return val (as interpreted by exec). Otherwise
1202 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001203
1204 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1205 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001206 """
1207 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001208 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001209 except:
1210 return default
1211
Dan Talayco4b2bee62010-07-20 14:10:05 -07001212 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001213 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001214 except:
1215 return default
1216
1217def action_generate(parent, field_to_mod, mod_field_vals):
1218 """
1219 Create an action to modify the field indicated in field_to_mod
1220
1221 @param parent Must implement, assertTrue
1222 @param field_to_mod The field to modify as a string name
1223 @param mod_field_vals Hash of values to use for modified values
1224 """
1225
1226 act = None
1227
1228 if field_to_mod in ['pktlen']:
1229 return None
1230
Rich Laned0478ff2013-03-11 12:46:58 -07001231 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001232 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001233 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001234 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001235 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001236 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001237 elif field_to_mod == 'dl_vlan_enable':
1238 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001239 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001240 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001241 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001242 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001243 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001244 act.vlan_vid = mod_field_vals['vlan_vid']
1245 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001246 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001247 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001248 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001249 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001250 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001251 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001252 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001253 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001254 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001255 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001256 act.nw_tos = mod_field_vals['ip_tos']
1257 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001258 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001259 act.tp_port = mod_field_vals['tcp_sport']
1260 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001261 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001262 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001263 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001264 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001265 act.tp_port = mod_field_vals['udp_sport']
1266 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001267 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001268 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001269 else:
1270 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1271
1272 return act
1273
1274def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001275 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001276 """
1277 Set up the ingress and expected packet and action list for a test
1278
Rich Lane2014f9b2012-10-05 15:29:40 -07001279 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001280 @param start_field_values Field values to use for ingress packet (optional)
1281 @param mod_field_values Field values to use for modified packet (optional)
1282 @param mod_fields The list of fields to be modified by the switch in the test.
1283 @params check_test_params If True, will check the parameters vid, add_vlan
1284 and strip_vlan from the command line.
1285
1286 Returns a triple: pkt-to-send, expected-pkt, action-list
1287 """
1288
1289 new_actions = []
1290
Dan Talayco4b2bee62010-07-20 14:10:05 -07001291 base_pkt_params = {}
1292 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001293 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1294 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001295 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001296 base_pkt_params['vlan_vid'] = 2
1297 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001298 base_pkt_params['ip_src'] = '192.168.0.1'
1299 base_pkt_params['ip_dst'] = '192.168.0.2'
1300 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001301 if tp == "tcp":
1302 base_pkt_params['tcp_sport'] = 1234
1303 base_pkt_params['tcp_dport'] = 80
1304 elif tp == "udp":
1305 base_pkt_params['udp_sport'] = 1234
1306 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001307 for keyname in start_field_vals.keys():
1308 base_pkt_params[keyname] = start_field_vals[keyname]
1309
1310 mod_pkt_params = {}
1311 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001312 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1313 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001314 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001315 mod_pkt_params['vlan_vid'] = 3
1316 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001317 mod_pkt_params['ip_src'] = '10.20.30.40'
1318 mod_pkt_params['ip_dst'] = '50.60.70.80'
1319 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001320 if tp == "tcp":
1321 mod_pkt_params['tcp_sport'] = 4321
1322 mod_pkt_params['tcp_dport'] = 8765
1323 elif tp == "udp":
1324 mod_pkt_params['udp_sport'] = 4321
1325 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001326 for keyname in mod_field_vals.keys():
1327 mod_pkt_params[keyname] = mod_field_vals[keyname]
1328
1329 # Check for test param modifications
1330 strip = False
1331 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001332 add_vlan = test_param_get('add_vlan')
1333 strip_vlan = test_param_get('strip_vlan')
1334 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001335
1336 if add_vlan and strip_vlan:
1337 parent.assertTrue(0, "Add and strip VLAN both specified")
1338
1339 if vid:
1340 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001341 base_pkt_params['vlan_vid'] = vid
1342 if 'vlan_vid' in mod_fields:
1343 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001344
1345 if add_vlan:
1346 base_pkt_params['dl_vlan_enable'] = False
1347 mod_pkt_params['dl_vlan_enable'] = True
1348 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1349 mod_fields.append('pktlen')
1350 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001351 if 'vlan_vid' not in mod_fields:
1352 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001353 elif strip_vlan:
1354 base_pkt_params['dl_vlan_enable'] = True
1355 mod_pkt_params['dl_vlan_enable'] = False
1356 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1357 mod_fields.append('dl_vlan_enable')
1358 mod_fields.append('pktlen')
1359
Rich Lane110e0e32012-10-26 16:21:46 -07001360 if tp == "tcp":
1361 packet_builder = simple_tcp_packet
1362 elif tp == "udp":
1363 packet_builder = simple_udp_packet
1364 else:
1365 raise NotImplementedError("unknown transport protocol %s" % tp)
1366
Dan Talayco4b2bee62010-07-20 14:10:05 -07001367 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001368 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001369
1370 # Build the expected packet, modifying the indicated fields
1371 for item in mod_fields:
1372 base_pkt_params[item] = mod_pkt_params[item]
1373 act = action_generate(parent, item, mod_pkt_params)
1374 if act:
1375 new_actions.append(act)
1376
Rich Lane110e0e32012-10-26 16:21:46 -07001377 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001378
1379 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001380
1381# Generate a simple "drop" flow mod
1382# If in_band is true, then only drop from first test port
1383def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001384 request = ofp.message.flow_add()
1385 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001386 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001387 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001388 for of_port, ifname in port_map.items(): # Grab first port
1389 break
1390 request.match.in_port = of_port
1391 request.buffer_id = 0xffffffff
1392 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001393
1394def skip_message_emit(parent, s):
1395 """
1396 Print out a 'skipped' message to stderr
1397
1398 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001399 """
1400 global skipped_test_count
1401
1402 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001403 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001404 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001405 sys.stderr.write("(skipped) ")
1406 else:
1407 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001408
Dan Talayco8a64e332012-03-28 14:53:20 -07001409
1410def all_stats_get(parent):
1411 """
1412 Get the aggregate stats for all flows in the table
1413 @param parent Test instance with controller connection and assert
1414 @returns dict with keys flows, packets, bytes, active (flows),
1415 lookups, matched
1416 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001417 stat_req = ofp.message.aggregate_stats_request()
1418 stat_req.match = ofp.match()
1419 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001420 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001421 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001422
1423 rv = {}
1424
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001425 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001426 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001427
Rich Lane5fd6faf2013-03-11 13:30:20 -07001428 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001429 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1430 obj.packet_count, obj.byte_count)
1431 break
1432
Rich Lanee717c6e2013-03-12 10:25:50 -07001433 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001434 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001435
1436
1437 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001438 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001439 rv["active"] += obj.active_count
1440 rv["lookups"] += obj.lookup_count
1441 rv["matched"] += obj.matched_count
1442
1443 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001444
Rich Lane7744e112013-01-11 17:23:57 -08001445_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001446FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1447 for x in range(256)])
1448
1449def hex_dump_buffer(src, length=16):
1450 """
1451 Convert src to a hex dump string and return the string
1452 @param src The source buffer
1453 @param length The number of bytes shown in each line
1454 @returns A string showing the hex dump
1455 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001456 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001457 for i in xrange(0, len(src), length):
1458 chars = src[i:i+length]
1459 hex = ' '.join(["%02x" % ord(x) for x in chars])
1460 printable = ''.join(["%s" % ((ord(x) <= 127 and
1461 FILTER[ord(x)]) or '.') for x in chars])
1462 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1463 return ''.join(result)
1464
1465def format_packet(pkt):
1466 return "Packet length %d \n%s" % (len(str(pkt)),
1467 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001468
1469def inspect_packet(pkt):
1470 """
1471 Wrapper around scapy's show() method.
1472 @returns A string showing the dissected packet.
1473 """
1474 from cStringIO import StringIO
1475 out = None
1476 backup = sys.stdout
1477 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001478 tmp = StringIO()
1479 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001480 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001481 out = tmp.getvalue()
1482 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001483 finally:
1484 sys.stdout = backup
1485 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001486
1487def nonstandard(cls):
1488 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001489 Testcase decorator that marks the test as being non-standard.
1490 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001491 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001492 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001493 return cls
1494
1495def disabled(cls):
1496 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001497 Testcase decorator that marks the test as being disabled.
1498 These tests are not automatically added to the "standard" group or
1499 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001500 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001501 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001502 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001503
1504def group(name):
1505 """
1506 Testcase decorator that adds the test to a group.
1507 """
1508 def fn(cls):
1509 if not hasattr(cls, "_groups"):
1510 cls._groups = []
1511 cls._groups.append(name)
1512 return cls
1513 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001514
1515def version(ver):
1516 """
1517 Testcase decorator that specifies which versions of OpenFlow the test
1518 supports. The default is 1.0+. This decorator may only be used once.
1519
1520 Supported syntax:
1521 1.0 -> 1.0
1522 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1523 1.0+ -> 1.0, 1.1, 1.2, 1.3
1524 """
1525 versions = parse_version(ver)
1526 def fn(cls):
1527 cls._versions = versions
1528 return cls
1529 return fn
1530
1531def parse_version(ver):
1532 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1533 if re.match("^1\.\d+$", ver):
1534 versions = set([ver])
1535 elif re.match("^(1\.\d+)\+$", ver):
1536 if not ver[:-1] in allowed_versions:
1537 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1538 versions = set()
1539 if ver != "1.1+": versions.add("1.0")
1540 if ver != "1.2+": versions.add("1.1")
1541 if ver != "1.3+": versions.add("1.2")
1542 versions.add("1.3")
1543 else:
1544 versions = set(ver.split(','))
1545
1546 for version in versions:
1547 if not version in allowed_versions:
1548 raise ValueError("invalid OpenFlow version %s" % version)
1549
1550 return versions
1551
1552assert(parse_version("1.0") == set(["1.0"]))
1553assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1554assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001555
Rich Laneae3428c2013-03-07 14:37:42 -08001556def get_stats(test, req):
1557 """
1558 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1559 """
Rich Lane609194f2013-10-21 06:17:37 -07001560 msgtype = ofp.OFPT_STATS_REPLY
1561 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001562 stats = []
1563 reply, _ = test.controller.transact(req)
1564 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001565 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001566 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001567 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001568 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001569 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001570 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001571 return stats
1572
Rich Lanebd56ed62013-07-10 15:49:44 -07001573def get_flow_stats(test, match, table_id=None,
1574 out_port=None, out_group=None,
1575 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001576 """
1577 Retrieve a list of flow stats entries.
1578 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001579
1580 if table_id == None:
1581 if ofp.OFP_VERSION <= 2:
1582 table_id = 0xff
1583 else:
1584 table_id = ofp.OFPTT_ALL
1585
Rich Lanef3bc48c2013-05-03 17:39:35 -07001586 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001587 if ofp.OFP_VERSION == 1:
1588 out_port = ofp.OFPP_NONE
1589 else:
1590 out_port = ofp.OFPP_ANY
1591
1592 if out_group == None:
1593 if ofp.OFP_VERSION > 1:
1594 out_group = ofp.OFPP_ANY
1595
Rich Lanee717c6e2013-03-12 10:25:50 -07001596 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001597 table_id=table_id,
1598 out_port=out_port)
1599 if ofp.OFP_VERSION > 1:
1600 req.out_group = out_group
1601 req.cookie = cookie
1602 req.cookie_mask = cookie_mask
1603
Rich Laneae3428c2013-03-07 14:37:42 -08001604 return get_stats(test, req)
1605
Rich Lane968b6192013-03-07 15:34:43 -08001606def get_port_stats(test, port_no):
1607 """
1608 Retrieve a list of port stats entries.
1609 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001610 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001611 return get_stats(test, req)
1612
Rich Lane6a334922013-03-07 16:14:52 -08001613def get_queue_stats(test, port_no, queue_id):
1614 """
1615 Retrieve a list of queue stats entries.
1616 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001617 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001618 return get_stats(test, req)
1619
Rich Laneae3428c2013-03-07 14:37:42 -08001620def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001621 initial=[],
1622 pkts=None, bytes=None):
1623 """
1624 Verify that flow stats changed as expected.
1625
1626 Optionally takes an 'initial' list of stats entries, as returned by
1627 get_flow_stats(). If 'initial' is not given the counters are assumed to
1628 begin at 0.
1629 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001630
Rich Laneae3428c2013-03-07 14:37:42 -08001631 def accumulate(stats):
1632 pkts_acc = bytes_acc = 0
1633 for stat in stats:
1634 pkts_acc += stat.packet_count
1635 bytes_acc += stat.byte_count
1636 return (pkts_acc, bytes_acc)
1637
1638 pkts_before, bytes_before = accumulate(initial)
1639
1640 # Wait 10s for counters to update
1641 pkt_diff = byte_diff = None
1642 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001643 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001644 pkts_after, bytes_after = accumulate(stats)
1645 pkt_diff = pkts_after - pkts_before
1646 byte_diff = bytes_after - bytes_before
1647 if (pkts == None or pkt_diff >= pkts) and \
1648 (bytes == None or byte_diff >= bytes):
1649 break
Dan Talayco53724732013-03-08 23:54:02 -08001650 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001651
1652 if pkts != None:
1653 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1654
1655 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001656 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1657 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001658
Rich Lane968b6192013-03-07 15:34:43 -08001659def verify_port_stats(test, port,
1660 initial=[],
1661 tx_pkts=None, rx_pkts=None,
1662 tx_bytes=None, rx_bytes=None):
1663 """
1664 Verify that port stats changed as expected.
1665
1666 Optionally takes an 'initial' list of stats entries, as returned by
1667 get_port_stats(). If 'initial' is not given the counters are assumed to
1668 begin at 0.
1669 """
1670 def accumulate(stats):
1671 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1672 for stat in stats:
1673 tx_pkts_acc += stat.tx_packets
1674 rx_pkts_acc += stat.rx_packets
1675 tx_bytes_acc += stat.tx_bytes
1676 rx_bytes_acc += stat.rx_bytes
1677 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1678
1679 tx_pkts_before, rx_pkts_before, \
1680 tx_bytes_before, rx_bytes_before = accumulate(initial)
1681
1682 # Wait 10s for counters to update
1683 for i in range(0, 100):
1684 stats = get_port_stats(test, port)
1685 tx_pkts_after, rx_pkts_after, \
1686 tx_bytes_after, rx_bytes_after = accumulate(stats)
1687 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1688 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1689 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1690 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001691 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1692 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001693 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1694 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001695 break
1696 time.sleep(0.1)
1697
1698 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001699 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1700 "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 -08001701 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001702 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1703 "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 -08001704 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001705 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1706 "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 -08001707 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001708 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1709 "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 -08001710
Rich Lane6a334922013-03-07 16:14:52 -08001711def verify_queue_stats(test, port_no, queue_id,
1712 initial=[],
1713 pkts=None, bytes=None):
1714 """
1715 Verify that queue stats changed as expected.
1716
1717 Optionally takes an 'initial' list of stats entries, as returned by
1718 get_queue_stats(). If 'initial' is not given the counters are assumed to
1719 begin at 0.
1720 """
1721 def accumulate(stats):
1722 pkts_acc = bytes_acc = 0
1723 for stat in stats:
1724 pkts_acc += stat.tx_packets
1725 bytes_acc += stat.tx_bytes
1726 return (pkts_acc, bytes_acc)
1727
1728 pkts_before, bytes_before = accumulate(initial)
1729
1730 # Wait 10s for counters to update
1731 pkt_diff = byte_diff = None
1732 for i in range(0, 100):
1733 stats = get_queue_stats(test, port_no, queue_id)
1734 pkts_after, bytes_after = accumulate(stats)
1735 pkt_diff = pkts_after - pkts_before
1736 byte_diff = bytes_after - bytes_before
1737 if (pkts == None or pkt_diff >= pkts) and \
1738 (bytes == None or byte_diff >= bytes):
1739 break
Dan Talayco53724732013-03-08 23:54:02 -08001740 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001741
1742 if pkts != None:
1743 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1744
1745 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001746 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1747 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001748
Rich Lane4c504f32013-06-07 17:24:14 -07001749def packet_in_match(msg, data, in_port=None, reason=None):
1750 """
1751 Check whether the packet_in message 'msg' has fields matching 'data',
1752 'in_port', and 'reason'.
1753
1754 This function handles truncated packet_in data. The 'in_port' and 'reason'
1755 parameters are optional.
1756
1757 @param msg packet_in message
1758 @param data Expected packet_in data
1759 @param in_port Expected packet_in in_port, or None
1760 @param reason Expected packet_in reason, or None
1761 """
1762
Rich Lanec0d26dd2013-07-10 12:46:03 -07001763 if ofp.OFP_VERSION <= 2:
1764 pkt_in_port = msg.in_port
1765 else:
1766 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1767 if ofp.oxm.in_port in oxms:
1768 pkt_in_port = oxms[ofp.oxm.in_port].value
1769 else:
1770 logging.warn("Missing in_port in packet-in message")
1771 pkt_in_port = None
1772
1773 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001774 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001775 return False
1776
Rich Lanec0d26dd2013-07-10 12:46:03 -07001777 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001778 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1779 return False
1780
1781 # Check that one of the packets is a prefix of the other.
1782 # The received packet may be either truncated or padded, but not both.
1783 # (Some of the padding may be truncated but that's irrelevant). We
1784 # need to check that the smaller packet is a prefix of the larger one.
1785 # Note that this check succeeds if the switch sends a zero-length
1786 # packet-in.
1787 compare_len = min(len(msg.data), len(data))
1788 if data[:compare_len] != msg.data[:compare_len]:
1789 logging.debug("Incorrect packet_in data")
1790 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1791 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1792 return False
1793
1794 return True
1795
1796def verify_packet_in(test, data, in_port, reason, controller=None):
1797 """
1798 Assert that the controller receives a packet_in message matching data 'data'
1799 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1800 itself, that's up to the test case.
1801
1802 @param test Instance of base_tests.SimpleProtocol
1803 @param pkt String to expect as the packet_in data
1804 @param in_port OpenFlow port number to expect as the packet_in in_port
1805 @param reason One of OFPR_* to expect as the packet_in reason
1806 @param controller Controller instance, defaults to test.controller
1807 @returns The received packet-in message
1808 """
1809
1810 if controller == None:
1811 controller = test.controller
1812
1813 end_time = time.time() + oftest.ofutils.default_timeout
1814
1815 while True:
1816 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1817 if not msg:
1818 # Timeout
1819 break
1820 elif packet_in_match(msg, data, in_port, reason):
1821 # Found a matching message
1822 break
1823
Kiran Poola58c5c042014-05-15 15:11:06 -07001824 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001825 return msg
1826
1827def verify_no_packet_in(test, data, in_port, controller=None):
1828 """
1829 Assert that the controller does not receive a packet_in message matching
1830 data 'data' from port 'in_port'.
1831
1832 @param test Instance of base_tests.SimpleProtocol
1833 @param pkt String to expect as the packet_in data
1834 @param in_port OpenFlow port number to expect as the packet_in in_port
1835 @param controller Controller instance, defaults to test.controller
1836 """
1837
1838 if controller == None:
1839 controller = test.controller
1840
1841 # Negative test, need to wait a short amount of time before checking we
1842 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001843 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001844
1845 # Check every packet_in queued in the controller
1846 while True:
1847 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1848 if msg == None:
1849 # No more queued packet_in messages
1850 break
1851 elif packet_in_match(msg, data, in_port, None):
1852 # Found a matching message
1853 break
1854
Rich Lane82c882d2013-08-09 17:13:52 -07001855 if in_port == None:
1856 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1857 else:
1858 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001859
Rich Lane045db072013-08-06 13:16:30 -07001860def openflow_ports(num=None):
1861 """
1862 Return a list of 'num' OpenFlow port numbers
1863
1864 If 'num' is None, return all available ports. Otherwise, limit the length
1865 of the result to 'num' and raise an exception if not enough ports are
1866 available.
1867 """
1868 ports = sorted(oftest.config["port_map"].keys())
1869 if num != None and len(ports) < num:
1870 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
1871 return ports[:num]
1872
Rich Lanee4b384d2013-09-13 14:33:40 -07001873def verify_packet(test, pkt, ofport):
1874 """
1875 Check that an expected packet is received
1876 """
1877 logging.debug("Checking for pkt on port %r", ofport)
1878 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
1879 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08001880 return (rcv_port, rcv_pkt, pkt_time)
1881
Rich Lanee4b384d2013-09-13 14:33:40 -07001882def verify_no_packet(test, pkt, ofport):
1883 """
1884 Check that a particular packet is not received
1885 """
1886 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07001887 (rcv_port, rcv_pkt, pkt_time) = \
1888 test.dataplane.poll(
1889 port_number=ofport, exp_pkt=str(pkt),
1890 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001891 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
1892
1893def verify_no_other_packets(test):
1894 """
1895 Check that no unexpected packets are received
1896
1897 This is a no-op if the --relax option is in effect.
1898 """
1899 if oftest.config["relax"]:
1900 return
1901 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07001902 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001903 if rcv_pkt != None:
1904 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
1905 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
1906
1907def verify_packets(test, pkt, ofports):
1908 """
1909 Check that a packet is received on certain ports
1910
1911 Also verifies that the packet is not received on any other ports, and that no
1912 other packets are received (unless --relax is in effect).
1913
1914 This covers the common and simplest cases for checking dataplane outputs.
1915 For more complex usage, like multiple different packets being output, or
1916 multiple packets on the same port, use the primitive verify_packet,
1917 verify_no_packet, and verify_no_other_packets functions directly.
1918 """
1919 pkt = str(pkt)
1920 for ofport in openflow_ports():
1921 if ofport in ofports:
1922 verify_packet(test, pkt, ofport)
1923 else:
1924 verify_no_packet(test, pkt, ofport)
1925 verify_no_other_packets(test)
1926
Rich Lane12d04592013-10-10 17:21:07 -07001927def verify_no_errors(ctrl):
1928 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
1929 if error:
1930 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07001931
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001932def verify_capability(test, capability):
1933 """
Jonathan Stout073642d2014-02-04 13:41:48 -05001934 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001935
1936 @param test Instance of base_tests.SimpleProtocol
1937 @param capability One of ofp_capabilities.
1938 """
1939 logging.info("Verifing that capability code is valid.")
1940 test.assertIn(capability, ofp.const.ofp_capabilities_map,
1941 "Capability code %d does not exist." % capability)
1942 capability_str = ofp.const.ofp_capabilities_map[capability]
1943
1944 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05001945 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001946 req = ofp.message.features_request()
1947 res, raw = test.controller.transact(req)
1948 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
1949 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
1950 ("Unexpected packet type %d received in response to "
1951 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05001952 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001953
Jonathan Stout641167f2014-02-04 12:07:10 -05001954 if (res.capabilities & capability) > 0:
1955 logging.info("Switch capabilities bitmask claims to support %s",
1956 capability_str)
1957 return True, res.capabilities
1958 else:
1959 logging.info("Capabilities bitmask does not support %s.",
1960 capability_str)
1961 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001962
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001963def verify_configuration_flag(test, flag):
1964 """
1965 Return True if DUT supports specified configuration flag.
1966
1967 @param test Instance of base_tests.SimpleProtocol
1968 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05001969 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001970 """
1971 logging.info("Verifing that flag is valid.")
1972 test.assertIn(flag, ofp.const.ofp_config_flags_map,
1973 "flag %s does not exist." % flag)
1974 flag_str = ofp.const.ofp_config_flags_map[flag]
1975
1976 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
1977 req = ofp.message.get_config_request()
1978 rv = test.controller.message_send(req)
1979 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
1980
1981 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
1982 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
1983 timeout=2)
1984 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
1985 logging.info("Received OFPT_GET_CONFIG_REPLY ")
1986
1987 if res.flags == flag:
1988 logging.info("%s flag is set.", flag_str)
1989 return True, res.flags
1990 else:
1991 logging.info("%s flag is not set.", flag_str)
1992 return False, res.flags
1993
Rich Lane7744e112013-01-11 17:23:57 -08001994__all__ = list(set(locals()) - _import_blacklist)