blob: c1fc58b51e54abbf442bec3b4656f1fc33e8199e [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,
Flavio Castro167f5bd2015-12-02 19:33:53 -0500412 inner_payload=True
Flavio Castro72a45d52015-12-02 16:37:05 -0500413 ):
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)
Flavio Castro167f5bd2015-12-02 19:33:53 -0500434
435 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500436
437 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800438
439def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
440 eth_src='00:06:07:08:09:0a',
441 dl_vlan_enable=False,
442 vlan_vid=0,
443 vlan_pcp=0,
444 dl_vlan_cfi=0,
445 label=None,
446 inner_payload=None
447 ):
448 """
449 Return a simple dataplane MPLS packet
450
451 Supports a few parameters:
452 @param len Length of packet in bytes w/o CRC
453 @param eth_dst Destination MAC
454 @param eth_src Source MAC
455 @param dl_vlan_enable True if the packet is with vlan, False otherwise
456 @param vlan_vid VLAN ID
457 @param vlan_pcp VLAN priority
458 @param inner_pyload inner pacekt content
459 Generates a simple MPLS packet. Users shouldn't assume anything about
460 this packet other than that it is a valid ethernet/IP/UDP frame.
461 """
462
463 # Note Dot1Q.id is really CFI
464 if (dl_vlan_enable):
465 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
466 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
467 else:
468 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
469
470 #add MPLS header
471 for i in range(len(label)):
472 l,c,s,t=label[i]
473 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
474
475 #add innder payload
476 if inner_payload!=None:
477 pkt=pkt/inner_payload
478
479 return pkt
480
Rich Lane86aceb02013-07-17 18:45:38 -0700481def simple_udpv6_packet(pktlen=100,
482 eth_dst='00:01:02:03:04:05',
483 eth_src='00:06:07:08:09:0a',
484 dl_vlan_enable=False,
485 vlan_vid=0,
486 vlan_pcp=0,
487 ipv6_src='2001:db8:85a3::8a2e:370:7334',
488 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
489 ipv6_tc=0,
490 ipv6_hlim=64,
491 ipv6_fl=0,
492 udp_sport=1234,
493 udp_dport=80):
494 """
495 Return a simple IPv6/UDP packet
496
497 Supports a few parameters:
498 @param len Length of packet in bytes w/o CRC
499 @param eth_dst Destination MAC
500 @param eth_src Source MAC
501 @param dl_vlan_enable True if the packet is with vlan, False otherwise
502 @param vlan_vid VLAN ID
503 @param vlan_pcp VLAN priority
504 @param ipv6_src IPv6 source
505 @param ipv6_dst IPv6 destination
506 @param ipv6_tc IPv6 traffic class
507 @param ipv6_ttl IPv6 hop limit
508 @param ipv6_fl IPv6 flow label
509 @param udp_dport UDP destination port
510 @param udp_sport UDP source port
511
512 Generates a simple UDP request. Users shouldn't assume anything about this
513 packet other than that it is a valid ethernet/IPv6/UDP frame.
514 """
515
516 if MINSIZE > pktlen:
517 pktlen = MINSIZE
518
519 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
520 if dl_vlan_enable or vlan_vid or vlan_pcp:
521 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
522 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
523 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
524 pkt /= ("D" * (pktlen - len(pkt)))
525
526 return pkt
527
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700528def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700529 eth_dst='00:01:02:03:04:05',
530 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700531 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700532 vlan_vid=0,
533 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700534 ip_src='192.168.0.1',
535 ip_dst='192.168.0.2',
536 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800537 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600538 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700539 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600540 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600541 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700542 """
543 Return a simple ICMP packet
544
545 Supports a few parameters:
546 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700547 @param eth_dst Destinatino MAC
548 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700549 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700550 @param vlan_vid VLAN ID
551 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700552 @param ip_src IP source
553 @param ip_dst IP destination
554 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800555 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600556 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700557 @param icmp_type ICMP type
558 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600559 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700560
561 Generates a simple ICMP ECHO REQUEST. Users
562 shouldn't assume anything about this packet other than that
563 it is a valid ethernet/ICMP frame.
564 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000565
566 if MINSIZE > pktlen:
567 pktlen = MINSIZE
568
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700569 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700570 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
571 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600572 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600573 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700574 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700575 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600576 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600577 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700578
579 pkt = pkt/("0" * (pktlen - len(pkt)))
580
581 return pkt
582
Rich Lane86aceb02013-07-17 18:45:38 -0700583def simple_icmpv6_packet(pktlen=100,
584 eth_dst='00:01:02:03:04:05',
585 eth_src='00:06:07:08:09:0a',
586 dl_vlan_enable=False,
587 vlan_vid=0,
588 vlan_pcp=0,
589 ipv6_src='2001:db8:85a3::8a2e:370:7334',
590 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
591 ipv6_tc=0,
592 ipv6_hlim=64,
593 ipv6_fl=0,
594 icmp_type=8,
595 icmp_code=0):
596 """
597 Return a simple ICMPv6 packet
598
599 Supports a few parameters:
600 @param len Length of packet in bytes w/o CRC
601 @param eth_dst Destination MAC
602 @param eth_src Source MAC
603 @param dl_vlan_enable True if the packet is with vlan, False otherwise
604 @param vlan_vid VLAN ID
605 @param vlan_pcp VLAN priority
606 @param ipv6_src IPv6 source
607 @param ipv6_dst IPv6 destination
608 @param ipv6_tc IPv6 traffic class
609 @param ipv6_ttl IPv6 hop limit
610 @param ipv6_fl IPv6 flow label
611 @param icmp_type ICMP type
612 @param icmp_code ICMP code
613
614 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
615 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
616 """
617
618 if MINSIZE > pktlen:
619 pktlen = MINSIZE
620
621 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
622 if dl_vlan_enable or vlan_vid or vlan_pcp:
623 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
624 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
625 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
626 pkt /= ("D" * (pktlen - len(pkt)))
627
628 return pkt
629
Shudong Zhouc7562b12013-02-06 01:12:18 -0800630def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700631 eth_dst='ff:ff:ff:ff:ff:ff',
632 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800633 vlan_vid=0,
634 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800635 arp_op=1,
636 ip_snd='192.168.0.1',
637 ip_tgt='192.168.0.2',
638 hw_snd='00:06:07:08:09:0a',
639 hw_tgt='00:00:00:00:00:00',
640 ):
641 """
642 Return a simple ARP packet
643
644 Supports a few parameters:
645 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700646 @param eth_dst Destinatino MAC
647 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800648 @param arp_op Operation (1=request, 2=reply)
649 @param ip_snd Sender IP
650 @param ip_tgt Target IP
651 @param hw_snd Sender hardware address
652 @param hw_tgt Target hardware address
653
654 Generates a simple ARP REQUEST. Users
655 shouldn't assume anything about this packet other than that
656 it is a valid ethernet/ARP frame.
657 """
658
659 if MINSIZE > pktlen:
660 pktlen = MINSIZE
661
Rich Lanee01611f2014-01-15 14:55:11 -0800662 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
663 if vlan_vid or vlan_pcp:
664 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
665 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 -0800666
Rich Laned459ce52014-01-24 12:09:54 -0800667 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800668
669 return pkt
670
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700671def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800672 eth_dst='00:01:02:03:04:05',
673 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700674 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000675
676 if MINSIZE > pktlen:
677 pktlen = MINSIZE
678
Rich Laned0478ff2013-03-11 12:46:58 -0700679 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700680
681 pkt = pkt/("0" * (pktlen - len(pkt)))
682
683 return pkt
684
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800685def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700686 eth_dst='00:01:02:03:04:05',
687 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800688 dl_vlan_outer=20,
689 dl_vlan_pcp_outer=0,
690 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700691 vlan_vid=10,
692 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800693 dl_vlan_cfi=0,
694 ip_src='192.168.0.1',
695 ip_dst='192.168.0.2',
696 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800697 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800698 tcp_sport=1234,
699 tcp_dport=80,
700 ip_ihl=None,
701 ip_options=False
702 ):
703 """
704 Return a doubly tagged dataplane TCP packet
705
706 Supports a few parameters:
707 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700708 @param eth_dst Destinatino MAC
709 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800710 @param dl_vlan_outer Outer VLAN ID
711 @param dl_vlan_pcp_outer Outer VLAN priority
712 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700713 @param vlan_vid Inner VLAN ID
714 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800715 @param dl_vlan_cfi VLAN cfi bit
716 @param ip_src IP source
717 @param ip_dst IP destination
718 @param ip_tos IP ToS
719 @param tcp_dport TCP destination port
720 @param ip_sport TCP source port
721
722 Generates a TCP request. Users
723 shouldn't assume anything about this packet other than that
724 it is a valid ethernet/IP/TCP frame.
725 """
726
727 if MINSIZE > pktlen:
728 pktlen = MINSIZE
729
730 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700731 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800732 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700733 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800734 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800735 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
736
737 pkt = pkt/("D" * (pktlen - len(pkt)))
738
739 return pkt
740
Shudong Zhoub7f12462012-11-20 13:01:12 -0800741def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700742 """
743 Do a barrier command
744 Return 0 on success, -1 on error
745 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700746 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800747 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800748 if resp is None:
749 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700750 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800751 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700752
Rich Lane9a003812012-10-04 17:17:59 -0700753def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700754 """
755 Get a port's configuration
756
757 Gets the switch feature configuration and grabs one port's
758 configuration
759
760 @returns (hwaddr, config, advert) The hwaddress, configuration and
761 advertised values
762 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700763
764 if ofp.OFP_VERSION <= 3:
765 request = ofp.message.features_request()
766 reply, _ = controller.transact(request)
767 if reply is None:
768 logging.warn("Get feature request failed")
769 return None, None, None
770 logging.debug(reply.show())
771 ports = reply.ports
772 else:
773 request = ofp.message.port_desc_stats_request()
774 # TODO do multipart correctly
775 reply, _ = controller.transact(request)
776 if reply is None:
777 logging.warn("Port desc stats request failed")
778 return None, None, None
779 logging.debug(reply.show())
780 ports = reply.entries
781
782 for port in ports:
783 if port.port_no == port_no:
784 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700785
Rich Lane9a003812012-10-04 17:17:59 -0700786 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700787 return None, None, None
788
Rich Lane9a003812012-10-04 17:17:59 -0700789def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700790 """
791 Set the port configuration according the given parameters
792
793 Gets the switch feature configuration and updates one port's
794 configuration value according to config and mask
795 """
Rich Lane9a003812012-10-04 17:17:59 -0700796 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700797
798 hw_addr, _, _ = port_config_get(controller, port_no)
799
Rich Lanee717c6e2013-03-12 10:25:50 -0700800 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700801 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700802 if hw_addr != None:
803 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700804 mod.config = config
805 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700806 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800807 controller.message_send(mod)
808 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700809
Rich Lane2014f9b2012-10-05 15:29:40 -0700810def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700811 """
812 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700813 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700814 @param pkt Expected packet; may be None if yes_ports is empty
815 @param yes_ports Set or list of ports that should recieve packet
816 @param no_ports Set or list of ports that should not receive packet
817 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700818
819 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700820 """
Rich Lane91765672012-12-06 16:33:04 -0800821
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700822 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800823 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700824 exp_pkt_arg = pkt
825
Dan Talayco92c99122010-06-03 13:53:18 -0700826 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700827 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700828 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800829 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700830 assert_if.assertTrue(rcv_pkt is not None,
831 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800832 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800833 logging.debug("Expected %s" % format_packet(pkt))
834 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800835 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -0800836 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -0700837 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700838 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -0700839 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -0700840 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700841 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700842 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -0800843 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700844 assert_if.assertTrue(rcv_pkt is None,
845 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700846
847
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700848def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700849 """
850 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700851 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700852
853 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -0700854
855 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -0700856 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700857 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800858 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700859 exp_pkt_arg = exp_pkt
860
Dan Talaycof6e76c02012-03-23 10:56:12 -0700861 if type(egr_ports) == type([]):
862 egr_port_list = egr_ports
863 else:
864 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700865
Dan Talaycof6e76c02012-03-23 10:56:12 -0700866 # Expect a packet from each port on egr port list
867 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700868 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -0700869 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700870 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700871 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700872 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700873
Dan Talaycof6e76c02012-03-23 10:56:12 -0700874 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700875 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700876 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700877
Dan Talaycof6e76c02012-03-23 10:56:12 -0700878 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700879 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700880 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700881 str(rcv_port))
882
883 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700884 logging.error("ERROR: Packet match failed.")
885 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700886 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700887 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700888 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700889 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
890 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700891 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700892 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700893
Dan Talayco551befa2010-07-15 17:05:32 -0700894def match_verify(parent, req_match, res_match):
895 """
896 Verify flow matches agree; if they disagree, report where
897
898 parent must implement assertEqual
899 Use str() to ensure content is compared and not pointers
900 """
901
902 parent.assertEqual(req_match.wildcards, res_match.wildcards,
903 'Match failed: wildcards: ' + hex(req_match.wildcards) +
904 " != " + hex(res_match.wildcards))
905 parent.assertEqual(req_match.in_port, res_match.in_port,
906 'Match failed: in_port: ' + str(req_match.in_port) +
907 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -0700908 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
909 'Match failed: eth_src: ' + str(req_match.eth_src) +
910 " != " + str(res_match.eth_src))
911 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
912 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
913 " != " + str(res_match.eth_dst))
914 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
915 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
916 " != " + str(res_match.vlan_vid))
917 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
918 'Match failed: vlan_pcp: ' +
919 str(req_match.vlan_pcp) + " != " +
920 str(res_match.vlan_pcp))
921 parent.assertEqual(req_match.eth_type, res_match.eth_type,
922 'Match failed: eth_type: ' + str(req_match.eth_type) +
923 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -0700924
Rich Lanee717c6e2013-03-12 10:25:50 -0700925 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -0700926 and (req_match.eth_type == IP_ETHERTYPE)):
927 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
928 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
929 " != " + str(res_match.ip_dscp))
930 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
931 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
932 " != " + str(res_match.ip_proto))
933 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
934 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
935 " != " + str(res_match.ipv4_src))
936 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
937 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
938 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700939
Rich Lanee717c6e2013-03-12 10:25:50 -0700940 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -0700941 and ((req_match.ip_proto == TCP_PROTOCOL)
942 or (req_match.ip_proto == UDP_PROTOCOL))):
943 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
944 'Match failed: tcp_src: ' +
945 str(req_match.tcp_src) +
946 " != " + str(res_match.tcp_src))
947 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
948 'Match failed: tcp_dst: ' +
949 str(req_match.tcp_dst) +
950 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -0700951
Ed Swierk99a74de2012-08-22 06:40:54 -0700952def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -0700953 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -0700954 if ofp.OFP_VERSION in [1, 2]:
955 match.wildcards |= required_wildcards(parent)
956 else:
957 # TODO remove incompatible OXM entries
958 pass
Ed Swierk99a74de2012-08-22 06:40:54 -0700959 return match
960
961def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700962 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700963 """
964 Create a flow message
965
966 Match on packet with given wildcards.
967 See flow_match_test for other parameter descriptoins
968 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -0700969 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700970 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700971 """
Rich Lanef6883512013-03-11 17:00:09 -0700972 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -0700973 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -0700974 if wildcards is None:
975 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -0700976 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -0700977 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -0700978 match.wildcards = wildcards
979 match.in_port = ing_port
980
Dan Talaycof6e76c02012-03-23 10:56:12 -0700981 if type(egr_ports) == type([]):
982 egr_port_list = egr_ports
983 else:
984 egr_port_list = [egr_ports]
985
Rich Lanee717c6e2013-03-12 10:25:50 -0700986 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -0700987 request.match = match
988 request.buffer_id = 0xffffffff
989 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -0700990 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -0700991 request.hard_timeout = 1
992
Rich Lane400fb9b2013-10-10 17:20:54 -0700993 if ofp.OFP_VERSION == 1:
994 actions = request.actions
995 else:
996 actions = []
997 request.instructions.append(ofp.instruction.apply_actions(actions))
998
Dan Talayco551befa2010-07-15 17:05:32 -0700999 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001000 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001001
1002 # Set up output/enqueue action if directed
1003 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001004 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001005 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001006 for egr_port in egr_port_list:
1007 act.port = egr_port
1008 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001009 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001010 elif egr_ports is not None:
1011 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001012 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001013 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001014 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001015
Rich Lane9a003812012-10-04 17:17:59 -07001016 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001017
1018 return request
1019
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001020def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001021 """
1022 Install a flow mod message in the switch
1023
1024 @param parent Must implement controller, assertEqual, assertTrue
1025 @param request The request, all set to go
1026 @param clear_table If true, clear the flow table before installing
1027 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001028
Rich Lane2014f9b2012-10-05 15:29:40 -07001029 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001030 if(clear_table_override != None):
1031 clear_table = clear_table_override
1032
1033 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001034 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001035 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001036
Rich Lane9a003812012-10-04 17:17:59 -07001037 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001038 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001039
Rich Lane3a261d52013-01-03 17:45:08 -08001040 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001041
Ed Swierk99a74de2012-08-22 06:40:54 -07001042def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001043 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001044 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001045 """
1046 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001047 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001048
1049 Run test with packet through switch from ing_port to egr_port
1050 See flow_match_test for parameter descriptions
1051 """
1052
Ed Swierk99a74de2012-08-22 06:40:54 -07001053 if wildcards is None:
1054 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001055 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001056 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001057 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001058 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001059 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001060 if exp_pkt is None:
1061 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001062
1063 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001064 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001065 action_list=action_list)
1066
1067 flow_msg_install(parent, request)
1068
Rich Lane9a003812012-10-04 17:17:59 -07001069 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001070 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001071 parent.dataplane.send(ing_port, str(pkt))
1072
Rich Lane8f45e2d2013-10-01 16:06:54 -07001073 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001074 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001075
Rich Lane89725bb2012-12-03 16:23:27 -08001076def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001077 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001078 action_list=None):
1079 """
1080 Packet-out test on single TCP packet
1081 @param egr_ports A single port or list of ports
1082
1083 Run test sending packet-out to egr_ports. The goal is to test the actions
1084 taken on the packet, not the matching which is of course irrelevant.
1085 See flow_match_test for parameter descriptions
1086 """
1087
1088 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001089 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001090 if exp_pkt is None:
1091 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001092
Rich Lanee717c6e2013-03-12 10:25:50 -07001093 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001094 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001095 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001096 msg.data = str(pkt)
1097 if action_list is not None:
1098 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001099 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001100
1101 # Set up output action
1102 if egr_ports is not None:
1103 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001104 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001105 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001106 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001107
1108 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001109 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001110
Rich Lane8f45e2d2013-10-01 16:06:54 -07001111 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001112 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001113
Dan Talaycof6e76c02012-03-23 10:56:12 -07001114def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1115 """
1116 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001117 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001118 @param of_ports List of OF port numbers
1119 @param how_many Number of ports to be added to the list
1120 @param exclude_list List of ports not to be used
1121 @returns An empty list if unable to find enough ports
1122 """
1123
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001124 if how_many == 0:
1125 return []
1126
Dan Talaycof6e76c02012-03-23 10:56:12 -07001127 count = 0
1128 egr_ports = []
1129 for egr_idx in range(len(of_ports)):
1130 if of_ports[egr_idx] not in exclude_list:
1131 egr_ports.append(of_ports[egr_idx])
1132 count += 1
1133 if count >= how_many:
1134 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001135 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001136 return []
1137
Rich Laned0478ff2013-03-11 12:46:58 -07001138def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001139 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001140 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001141 """
Rich Lane89725bb2012-12-03 16:23:27 -08001142 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001143
1144 @param max_test If > 0 no more than this number of tests are executed.
1145 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001146 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001147 @param pkt If not None, use this packet for ingress
1148 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001149 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001150 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1151 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001152 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001153 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001154 if wildcards is None:
1155 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001156 of_ports = port_map.keys()
1157 of_ports.sort()
1158 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1159 test_count = 0
1160
Dan Talaycocfa172f2012-03-23 12:03:00 -07001161 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001162 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001163
Dan Talayco551befa2010-07-15 17:05:32 -07001164 for ing_idx in range(len(of_ports)):
1165 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001166 egr_ports = get_egr_list(parent, of_ports, egr_count,
1167 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001168 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001169 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001170 if len(egr_ports) == 0:
1171 parent.assertTrue(0, "Failed to generate egress port list")
1172
1173 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001174 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001175 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001176 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001177 test_count += 1
1178 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001179 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001180 break
1181
Ed Swierk38eea082013-01-02 19:46:20 -08001182 if not test_param_get('pktout_actions', default=True):
1183 return
Rich Lane89725bb2012-12-03 16:23:27 -08001184
1185 ingress_port = of_ports[0]
1186 egr_ports = get_egr_list(parent, of_ports, egr_count,
1187 exclude_list=[ingress_port])
1188 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001189 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001190 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001191 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001192 pkt=pkt, exp_pkt=exp_pkt,
1193 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001194
Rich Lane2014f9b2012-10-05 15:29:40 -07001195def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001196 """
1197 Return value passed via test-params if present
1198
Dan Talayco4b2bee62010-07-20 14:10:05 -07001199 @param key The lookup key
1200 @param default Default value to use if not found
1201
1202 If the pair 'key=val' appeared in the string passed to --test-params
1203 on the command line, return val (as interpreted by exec). Otherwise
1204 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001205
1206 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1207 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001208 """
1209 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001210 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001211 except:
1212 return default
1213
Dan Talayco4b2bee62010-07-20 14:10:05 -07001214 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001215 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001216 except:
1217 return default
1218
1219def action_generate(parent, field_to_mod, mod_field_vals):
1220 """
1221 Create an action to modify the field indicated in field_to_mod
1222
1223 @param parent Must implement, assertTrue
1224 @param field_to_mod The field to modify as a string name
1225 @param mod_field_vals Hash of values to use for modified values
1226 """
1227
1228 act = None
1229
1230 if field_to_mod in ['pktlen']:
1231 return None
1232
Rich Laned0478ff2013-03-11 12:46:58 -07001233 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001234 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001235 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001236 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001237 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001238 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001239 elif field_to_mod == 'dl_vlan_enable':
1240 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001241 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001242 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001243 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001244 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001245 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001246 act.vlan_vid = mod_field_vals['vlan_vid']
1247 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001248 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001249 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001250 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001251 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001252 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001253 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001254 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001255 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001256 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001257 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001258 act.nw_tos = mod_field_vals['ip_tos']
1259 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001260 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001261 act.tp_port = mod_field_vals['tcp_sport']
1262 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001263 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001264 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001265 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001266 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001267 act.tp_port = mod_field_vals['udp_sport']
1268 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001269 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001270 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001271 else:
1272 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1273
1274 return act
1275
1276def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001277 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001278 """
1279 Set up the ingress and expected packet and action list for a test
1280
Rich Lane2014f9b2012-10-05 15:29:40 -07001281 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001282 @param start_field_values Field values to use for ingress packet (optional)
1283 @param mod_field_values Field values to use for modified packet (optional)
1284 @param mod_fields The list of fields to be modified by the switch in the test.
1285 @params check_test_params If True, will check the parameters vid, add_vlan
1286 and strip_vlan from the command line.
1287
1288 Returns a triple: pkt-to-send, expected-pkt, action-list
1289 """
1290
1291 new_actions = []
1292
Dan Talayco4b2bee62010-07-20 14:10:05 -07001293 base_pkt_params = {}
1294 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001295 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1296 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001297 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001298 base_pkt_params['vlan_vid'] = 2
1299 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001300 base_pkt_params['ip_src'] = '192.168.0.1'
1301 base_pkt_params['ip_dst'] = '192.168.0.2'
1302 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001303 if tp == "tcp":
1304 base_pkt_params['tcp_sport'] = 1234
1305 base_pkt_params['tcp_dport'] = 80
1306 elif tp == "udp":
1307 base_pkt_params['udp_sport'] = 1234
1308 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001309 for keyname in start_field_vals.keys():
1310 base_pkt_params[keyname] = start_field_vals[keyname]
1311
1312 mod_pkt_params = {}
1313 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001314 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1315 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001316 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001317 mod_pkt_params['vlan_vid'] = 3
1318 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001319 mod_pkt_params['ip_src'] = '10.20.30.40'
1320 mod_pkt_params['ip_dst'] = '50.60.70.80'
1321 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001322 if tp == "tcp":
1323 mod_pkt_params['tcp_sport'] = 4321
1324 mod_pkt_params['tcp_dport'] = 8765
1325 elif tp == "udp":
1326 mod_pkt_params['udp_sport'] = 4321
1327 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001328 for keyname in mod_field_vals.keys():
1329 mod_pkt_params[keyname] = mod_field_vals[keyname]
1330
1331 # Check for test param modifications
1332 strip = False
1333 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001334 add_vlan = test_param_get('add_vlan')
1335 strip_vlan = test_param_get('strip_vlan')
1336 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001337
1338 if add_vlan and strip_vlan:
1339 parent.assertTrue(0, "Add and strip VLAN both specified")
1340
1341 if vid:
1342 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001343 base_pkt_params['vlan_vid'] = vid
1344 if 'vlan_vid' in mod_fields:
1345 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001346
1347 if add_vlan:
1348 base_pkt_params['dl_vlan_enable'] = False
1349 mod_pkt_params['dl_vlan_enable'] = True
1350 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1351 mod_fields.append('pktlen')
1352 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001353 if 'vlan_vid' not in mod_fields:
1354 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001355 elif strip_vlan:
1356 base_pkt_params['dl_vlan_enable'] = True
1357 mod_pkt_params['dl_vlan_enable'] = False
1358 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1359 mod_fields.append('dl_vlan_enable')
1360 mod_fields.append('pktlen')
1361
Rich Lane110e0e32012-10-26 16:21:46 -07001362 if tp == "tcp":
1363 packet_builder = simple_tcp_packet
1364 elif tp == "udp":
1365 packet_builder = simple_udp_packet
1366 else:
1367 raise NotImplementedError("unknown transport protocol %s" % tp)
1368
Dan Talayco4b2bee62010-07-20 14:10:05 -07001369 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001370 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001371
1372 # Build the expected packet, modifying the indicated fields
1373 for item in mod_fields:
1374 base_pkt_params[item] = mod_pkt_params[item]
1375 act = action_generate(parent, item, mod_pkt_params)
1376 if act:
1377 new_actions.append(act)
1378
Rich Lane110e0e32012-10-26 16:21:46 -07001379 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001380
1381 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001382
1383# Generate a simple "drop" flow mod
1384# If in_band is true, then only drop from first test port
1385def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001386 request = ofp.message.flow_add()
1387 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001388 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001389 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001390 for of_port, ifname in port_map.items(): # Grab first port
1391 break
1392 request.match.in_port = of_port
1393 request.buffer_id = 0xffffffff
1394 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001395
1396def skip_message_emit(parent, s):
1397 """
1398 Print out a 'skipped' message to stderr
1399
1400 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001401 """
1402 global skipped_test_count
1403
1404 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001405 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001406 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001407 sys.stderr.write("(skipped) ")
1408 else:
1409 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001410
Dan Talayco8a64e332012-03-28 14:53:20 -07001411
1412def all_stats_get(parent):
1413 """
1414 Get the aggregate stats for all flows in the table
1415 @param parent Test instance with controller connection and assert
1416 @returns dict with keys flows, packets, bytes, active (flows),
1417 lookups, matched
1418 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001419 stat_req = ofp.message.aggregate_stats_request()
1420 stat_req.match = ofp.match()
1421 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001422 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001423 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001424
1425 rv = {}
1426
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001427 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001428 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001429
Rich Lane5fd6faf2013-03-11 13:30:20 -07001430 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001431 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1432 obj.packet_count, obj.byte_count)
1433 break
1434
Rich Lanee717c6e2013-03-12 10:25:50 -07001435 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001436 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001437
1438
1439 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001440 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001441 rv["active"] += obj.active_count
1442 rv["lookups"] += obj.lookup_count
1443 rv["matched"] += obj.matched_count
1444
1445 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001446
Rich Lane7744e112013-01-11 17:23:57 -08001447_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001448FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1449 for x in range(256)])
1450
1451def hex_dump_buffer(src, length=16):
1452 """
1453 Convert src to a hex dump string and return the string
1454 @param src The source buffer
1455 @param length The number of bytes shown in each line
1456 @returns A string showing the hex dump
1457 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001458 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001459 for i in xrange(0, len(src), length):
1460 chars = src[i:i+length]
1461 hex = ' '.join(["%02x" % ord(x) for x in chars])
1462 printable = ''.join(["%s" % ((ord(x) <= 127 and
1463 FILTER[ord(x)]) or '.') for x in chars])
1464 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1465 return ''.join(result)
1466
1467def format_packet(pkt):
1468 return "Packet length %d \n%s" % (len(str(pkt)),
1469 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001470
1471def inspect_packet(pkt):
1472 """
1473 Wrapper around scapy's show() method.
1474 @returns A string showing the dissected packet.
1475 """
1476 from cStringIO import StringIO
1477 out = None
1478 backup = sys.stdout
1479 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001480 tmp = StringIO()
1481 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001482 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001483 out = tmp.getvalue()
1484 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001485 finally:
1486 sys.stdout = backup
1487 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001488
1489def nonstandard(cls):
1490 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001491 Testcase decorator that marks the test as being non-standard.
1492 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001493 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001494 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001495 return cls
1496
1497def disabled(cls):
1498 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001499 Testcase decorator that marks the test as being disabled.
1500 These tests are not automatically added to the "standard" group or
1501 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001502 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001503 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001504 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001505
1506def group(name):
1507 """
1508 Testcase decorator that adds the test to a group.
1509 """
1510 def fn(cls):
1511 if not hasattr(cls, "_groups"):
1512 cls._groups = []
1513 cls._groups.append(name)
1514 return cls
1515 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001516
1517def version(ver):
1518 """
1519 Testcase decorator that specifies which versions of OpenFlow the test
1520 supports. The default is 1.0+. This decorator may only be used once.
1521
1522 Supported syntax:
1523 1.0 -> 1.0
1524 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1525 1.0+ -> 1.0, 1.1, 1.2, 1.3
1526 """
1527 versions = parse_version(ver)
1528 def fn(cls):
1529 cls._versions = versions
1530 return cls
1531 return fn
1532
1533def parse_version(ver):
1534 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1535 if re.match("^1\.\d+$", ver):
1536 versions = set([ver])
1537 elif re.match("^(1\.\d+)\+$", ver):
1538 if not ver[:-1] in allowed_versions:
1539 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1540 versions = set()
1541 if ver != "1.1+": versions.add("1.0")
1542 if ver != "1.2+": versions.add("1.1")
1543 if ver != "1.3+": versions.add("1.2")
1544 versions.add("1.3")
1545 else:
1546 versions = set(ver.split(','))
1547
1548 for version in versions:
1549 if not version in allowed_versions:
1550 raise ValueError("invalid OpenFlow version %s" % version)
1551
1552 return versions
1553
1554assert(parse_version("1.0") == set(["1.0"]))
1555assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1556assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001557
Rich Laneae3428c2013-03-07 14:37:42 -08001558def get_stats(test, req):
1559 """
1560 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1561 """
Rich Lane609194f2013-10-21 06:17:37 -07001562 msgtype = ofp.OFPT_STATS_REPLY
1563 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001564 stats = []
1565 reply, _ = test.controller.transact(req)
1566 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001567 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001568 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001569 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001570 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001571 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001572 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001573 return stats
1574
Rich Lanebd56ed62013-07-10 15:49:44 -07001575def get_flow_stats(test, match, table_id=None,
1576 out_port=None, out_group=None,
1577 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001578 """
1579 Retrieve a list of flow stats entries.
1580 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001581
1582 if table_id == None:
1583 if ofp.OFP_VERSION <= 2:
1584 table_id = 0xff
1585 else:
1586 table_id = ofp.OFPTT_ALL
1587
Rich Lanef3bc48c2013-05-03 17:39:35 -07001588 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001589 if ofp.OFP_VERSION == 1:
1590 out_port = ofp.OFPP_NONE
1591 else:
1592 out_port = ofp.OFPP_ANY
1593
1594 if out_group == None:
1595 if ofp.OFP_VERSION > 1:
1596 out_group = ofp.OFPP_ANY
1597
Rich Lanee717c6e2013-03-12 10:25:50 -07001598 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001599 table_id=table_id,
1600 out_port=out_port)
1601 if ofp.OFP_VERSION > 1:
1602 req.out_group = out_group
1603 req.cookie = cookie
1604 req.cookie_mask = cookie_mask
1605
Rich Laneae3428c2013-03-07 14:37:42 -08001606 return get_stats(test, req)
1607
Rich Lane968b6192013-03-07 15:34:43 -08001608def get_port_stats(test, port_no):
1609 """
1610 Retrieve a list of port stats entries.
1611 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001612 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001613 return get_stats(test, req)
1614
Rich Lane6a334922013-03-07 16:14:52 -08001615def get_queue_stats(test, port_no, queue_id):
1616 """
1617 Retrieve a list of queue stats entries.
1618 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001619 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001620 return get_stats(test, req)
1621
Rich Laneae3428c2013-03-07 14:37:42 -08001622def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001623 initial=[],
1624 pkts=None, bytes=None):
1625 """
1626 Verify that flow stats changed as expected.
1627
1628 Optionally takes an 'initial' list of stats entries, as returned by
1629 get_flow_stats(). If 'initial' is not given the counters are assumed to
1630 begin at 0.
1631 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001632
Rich Laneae3428c2013-03-07 14:37:42 -08001633 def accumulate(stats):
1634 pkts_acc = bytes_acc = 0
1635 for stat in stats:
1636 pkts_acc += stat.packet_count
1637 bytes_acc += stat.byte_count
1638 return (pkts_acc, bytes_acc)
1639
1640 pkts_before, bytes_before = accumulate(initial)
1641
1642 # Wait 10s for counters to update
1643 pkt_diff = byte_diff = None
1644 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001645 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001646 pkts_after, bytes_after = accumulate(stats)
1647 pkt_diff = pkts_after - pkts_before
1648 byte_diff = bytes_after - bytes_before
1649 if (pkts == None or pkt_diff >= pkts) and \
1650 (bytes == None or byte_diff >= bytes):
1651 break
Dan Talayco53724732013-03-08 23:54:02 -08001652 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001653
1654 if pkts != None:
1655 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1656
1657 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001658 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1659 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001660
Rich Lane968b6192013-03-07 15:34:43 -08001661def verify_port_stats(test, port,
1662 initial=[],
1663 tx_pkts=None, rx_pkts=None,
1664 tx_bytes=None, rx_bytes=None):
1665 """
1666 Verify that port stats changed as expected.
1667
1668 Optionally takes an 'initial' list of stats entries, as returned by
1669 get_port_stats(). If 'initial' is not given the counters are assumed to
1670 begin at 0.
1671 """
1672 def accumulate(stats):
1673 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1674 for stat in stats:
1675 tx_pkts_acc += stat.tx_packets
1676 rx_pkts_acc += stat.rx_packets
1677 tx_bytes_acc += stat.tx_bytes
1678 rx_bytes_acc += stat.rx_bytes
1679 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1680
1681 tx_pkts_before, rx_pkts_before, \
1682 tx_bytes_before, rx_bytes_before = accumulate(initial)
1683
1684 # Wait 10s for counters to update
1685 for i in range(0, 100):
1686 stats = get_port_stats(test, port)
1687 tx_pkts_after, rx_pkts_after, \
1688 tx_bytes_after, rx_bytes_after = accumulate(stats)
1689 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1690 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1691 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1692 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001693 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1694 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001695 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1696 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001697 break
1698 time.sleep(0.1)
1699
1700 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001701 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1702 "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 -08001703 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001704 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1705 "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 -08001706 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001707 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1708 "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 -08001709 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001710 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1711 "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 -08001712
Rich Lane6a334922013-03-07 16:14:52 -08001713def verify_queue_stats(test, port_no, queue_id,
1714 initial=[],
1715 pkts=None, bytes=None):
1716 """
1717 Verify that queue stats changed as expected.
1718
1719 Optionally takes an 'initial' list of stats entries, as returned by
1720 get_queue_stats(). If 'initial' is not given the counters are assumed to
1721 begin at 0.
1722 """
1723 def accumulate(stats):
1724 pkts_acc = bytes_acc = 0
1725 for stat in stats:
1726 pkts_acc += stat.tx_packets
1727 bytes_acc += stat.tx_bytes
1728 return (pkts_acc, bytes_acc)
1729
1730 pkts_before, bytes_before = accumulate(initial)
1731
1732 # Wait 10s for counters to update
1733 pkt_diff = byte_diff = None
1734 for i in range(0, 100):
1735 stats = get_queue_stats(test, port_no, queue_id)
1736 pkts_after, bytes_after = accumulate(stats)
1737 pkt_diff = pkts_after - pkts_before
1738 byte_diff = bytes_after - bytes_before
1739 if (pkts == None or pkt_diff >= pkts) and \
1740 (bytes == None or byte_diff >= bytes):
1741 break
Dan Talayco53724732013-03-08 23:54:02 -08001742 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001743
1744 if pkts != None:
1745 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1746
1747 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001748 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1749 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001750
Rich Lane4c504f32013-06-07 17:24:14 -07001751def packet_in_match(msg, data, in_port=None, reason=None):
1752 """
1753 Check whether the packet_in message 'msg' has fields matching 'data',
1754 'in_port', and 'reason'.
1755
1756 This function handles truncated packet_in data. The 'in_port' and 'reason'
1757 parameters are optional.
1758
1759 @param msg packet_in message
1760 @param data Expected packet_in data
1761 @param in_port Expected packet_in in_port, or None
1762 @param reason Expected packet_in reason, or None
1763 """
1764
Rich Lanec0d26dd2013-07-10 12:46:03 -07001765 if ofp.OFP_VERSION <= 2:
1766 pkt_in_port = msg.in_port
1767 else:
1768 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1769 if ofp.oxm.in_port in oxms:
1770 pkt_in_port = oxms[ofp.oxm.in_port].value
1771 else:
1772 logging.warn("Missing in_port in packet-in message")
1773 pkt_in_port = None
1774
1775 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001776 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001777 return False
1778
Rich Lanec0d26dd2013-07-10 12:46:03 -07001779 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001780 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1781 return False
1782
1783 # Check that one of the packets is a prefix of the other.
1784 # The received packet may be either truncated or padded, but not both.
1785 # (Some of the padding may be truncated but that's irrelevant). We
1786 # need to check that the smaller packet is a prefix of the larger one.
1787 # Note that this check succeeds if the switch sends a zero-length
1788 # packet-in.
1789 compare_len = min(len(msg.data), len(data))
1790 if data[:compare_len] != msg.data[:compare_len]:
1791 logging.debug("Incorrect packet_in data")
1792 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1793 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1794 return False
1795
1796 return True
1797
1798def verify_packet_in(test, data, in_port, reason, controller=None):
1799 """
1800 Assert that the controller receives a packet_in message matching data 'data'
1801 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1802 itself, that's up to the test case.
1803
1804 @param test Instance of base_tests.SimpleProtocol
1805 @param pkt String to expect as the packet_in data
1806 @param in_port OpenFlow port number to expect as the packet_in in_port
1807 @param reason One of OFPR_* to expect as the packet_in reason
1808 @param controller Controller instance, defaults to test.controller
1809 @returns The received packet-in message
1810 """
1811
1812 if controller == None:
1813 controller = test.controller
1814
1815 end_time = time.time() + oftest.ofutils.default_timeout
1816
1817 while True:
1818 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1819 if not msg:
1820 # Timeout
1821 break
1822 elif packet_in_match(msg, data, in_port, reason):
1823 # Found a matching message
1824 break
1825
Kiran Poola58c5c042014-05-15 15:11:06 -07001826 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001827 return msg
1828
1829def verify_no_packet_in(test, data, in_port, controller=None):
1830 """
1831 Assert that the controller does not receive a packet_in message matching
1832 data 'data' from port 'in_port'.
1833
1834 @param test Instance of base_tests.SimpleProtocol
1835 @param pkt String to expect as the packet_in data
1836 @param in_port OpenFlow port number to expect as the packet_in in_port
1837 @param controller Controller instance, defaults to test.controller
1838 """
1839
1840 if controller == None:
1841 controller = test.controller
1842
1843 # Negative test, need to wait a short amount of time before checking we
1844 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07001845 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07001846
1847 # Check every packet_in queued in the controller
1848 while True:
1849 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
1850 if msg == None:
1851 # No more queued packet_in messages
1852 break
1853 elif packet_in_match(msg, data, in_port, None):
1854 # Found a matching message
1855 break
1856
Rich Lane82c882d2013-08-09 17:13:52 -07001857 if in_port == None:
1858 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
1859 else:
1860 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001861
Rich Lane045db072013-08-06 13:16:30 -07001862def openflow_ports(num=None):
1863 """
1864 Return a list of 'num' OpenFlow port numbers
1865
1866 If 'num' is None, return all available ports. Otherwise, limit the length
1867 of the result to 'num' and raise an exception if not enough ports are
1868 available.
1869 """
1870 ports = sorted(oftest.config["port_map"].keys())
1871 if num != None and len(ports) < num:
1872 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
1873 return ports[:num]
1874
Rich Lanee4b384d2013-09-13 14:33:40 -07001875def verify_packet(test, pkt, ofport):
1876 """
1877 Check that an expected packet is received
1878 """
1879 logging.debug("Checking for pkt on port %r", ofport)
1880 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
1881 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08001882 return (rcv_port, rcv_pkt, pkt_time)
1883
Rich Lanee4b384d2013-09-13 14:33:40 -07001884def verify_no_packet(test, pkt, ofport):
1885 """
1886 Check that a particular packet is not received
1887 """
1888 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07001889 (rcv_port, rcv_pkt, pkt_time) = \
1890 test.dataplane.poll(
1891 port_number=ofport, exp_pkt=str(pkt),
1892 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001893 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
1894
1895def verify_no_other_packets(test):
1896 """
1897 Check that no unexpected packets are received
1898
1899 This is a no-op if the --relax option is in effect.
1900 """
1901 if oftest.config["relax"]:
1902 return
1903 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07001904 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07001905 if rcv_pkt != None:
1906 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
1907 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
1908
1909def verify_packets(test, pkt, ofports):
1910 """
1911 Check that a packet is received on certain ports
1912
1913 Also verifies that the packet is not received on any other ports, and that no
1914 other packets are received (unless --relax is in effect).
1915
1916 This covers the common and simplest cases for checking dataplane outputs.
1917 For more complex usage, like multiple different packets being output, or
1918 multiple packets on the same port, use the primitive verify_packet,
1919 verify_no_packet, and verify_no_other_packets functions directly.
1920 """
1921 pkt = str(pkt)
1922 for ofport in openflow_ports():
1923 if ofport in ofports:
1924 verify_packet(test, pkt, ofport)
1925 else:
1926 verify_no_packet(test, pkt, ofport)
1927 verify_no_other_packets(test)
1928
Rich Lane12d04592013-10-10 17:21:07 -07001929def verify_no_errors(ctrl):
1930 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
1931 if error:
1932 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07001933
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001934def verify_capability(test, capability):
1935 """
Jonathan Stout073642d2014-02-04 13:41:48 -05001936 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001937
1938 @param test Instance of base_tests.SimpleProtocol
1939 @param capability One of ofp_capabilities.
1940 """
1941 logging.info("Verifing that capability code is valid.")
1942 test.assertIn(capability, ofp.const.ofp_capabilities_map,
1943 "Capability code %d does not exist." % capability)
1944 capability_str = ofp.const.ofp_capabilities_map[capability]
1945
1946 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05001947 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001948 req = ofp.message.features_request()
1949 res, raw = test.controller.transact(req)
1950 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
1951 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
1952 ("Unexpected packet type %d received in response to "
1953 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05001954 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001955
Jonathan Stout641167f2014-02-04 12:07:10 -05001956 if (res.capabilities & capability) > 0:
1957 logging.info("Switch capabilities bitmask claims to support %s",
1958 capability_str)
1959 return True, res.capabilities
1960 else:
1961 logging.info("Capabilities bitmask does not support %s.",
1962 capability_str)
1963 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05001964
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001965def verify_configuration_flag(test, flag):
1966 """
1967 Return True if DUT supports specified configuration flag.
1968
1969 @param test Instance of base_tests.SimpleProtocol
1970 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05001971 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05001972 """
1973 logging.info("Verifing that flag is valid.")
1974 test.assertIn(flag, ofp.const.ofp_config_flags_map,
1975 "flag %s does not exist." % flag)
1976 flag_str = ofp.const.ofp_config_flags_map[flag]
1977
1978 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
1979 req = ofp.message.get_config_request()
1980 rv = test.controller.message_send(req)
1981 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
1982
1983 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
1984 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
1985 timeout=2)
1986 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
1987 logging.info("Received OFPT_GET_CONFIG_REPLY ")
1988
1989 if res.flags == flag:
1990 logging.info("%s flag is set.", flag_str)
1991 return True, res.flags
1992 else:
1993 logging.info("%s flag is not set.", flag_str)
1994 return False, res.flags
1995
Rich Lane7744e112013-01-11 17:23:57 -08001996__all__ = list(set(locals()) - _import_blacklist)