blob: 5024d4aec176ceb0cdb7b741a273b445e31f0ed6 [file] [log] [blame]
Matteo Scandoloa229eca2017-08-08 13:05:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Dan Talaycod2ca1032010-03-10 14:40:26 -080017import sys
Dan Talayco92c99122010-06-03 13:53:18 -070018import copy
Rich Lane6242d9f2013-01-06 17:35:39 -080019import logging
20import types
21import time
Rich Lane5a9a1922013-01-11 14:29:30 -080022import re
Flavio Castro1c9b1252016-02-04 18:42:58 -050023from Queue import Queue
24
Rich Lanea68176f2013-08-09 17:41:05 -070025import packet as scapy
Dan Talayco41eae8b2010-03-10 13:57:06 -080026
Rich Lanecd97d3d2013-01-07 18:50:06 -080027import oftest
28import oftest.controller
29import oftest.dataplane
Rich Lanef6883512013-03-11 17:00:09 -070030import oftest.parse
Rich Lane4c504f32013-06-07 17:24:14 -070031import oftest.ofutils
Rich Lanee717c6e2013-03-12 10:25:50 -070032import ofp
Dan Talaycoc901f4d2010-03-07 21:55:45 -080033
Dan Talaycoba3745c2010-07-21 21:51:08 -070034global skipped_test_count
35skipped_test_count = 0
36
Rich Lane7744e112013-01-11 17:23:57 -080037_import_blacklist = set(locals().keys())
38
Dan Talayco551befa2010-07-15 17:05:32 -070039# Some useful defines
40IP_ETHERTYPE = 0x800
41TCP_PROTOCOL = 0x6
42UDP_PROTOCOL = 0x11
43
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000044MINSIZE = 0
45
Tony van der Peet80c5b202013-11-20 11:47:48 +130046def delete_all_flows(ctrl, send_barrier=True):
Dan Talayco41eae8b2010-03-10 13:57:06 -080047 """
48 Delete all flows on the switch
49 @param ctrl The controller object for the test
Tony van der Peet80c5b202013-11-20 11:47:48 +130050 @param send_barrier Whether or not to send a barrier message
Dan Talayco41eae8b2010-03-10 13:57:06 -080051 """
52
Rich Lane9a003812012-10-04 17:17:59 -070053 logging.info("Deleting all flows")
Rich Lanee717c6e2013-03-12 10:25:50 -070054 msg = ofp.message.flow_delete()
Rich Lanec717f442013-06-13 15:49:09 -070055 if ofp.OFP_VERSION in [1, 2]:
56 msg.match.wildcards = ofp.OFPFW_ALL
57 msg.out_port = ofp.OFPP_NONE
58 msg.buffer_id = 0xffffffff
59 elif ofp.OFP_VERSION >= 3:
60 msg.table_id = ofp.OFPTT_ALL
61 msg.buffer_id = ofp.OFP_NO_BUFFER
62 msg.out_port = ofp.OFPP_ANY
63 msg.out_group = ofp.OFPG_ANY
Rich Lane5c3151c2013-01-03 17:15:41 -080064 ctrl.message_send(msg)
Tony van der Peet80c5b202013-11-20 11:47:48 +130065 if send_barrier:
66 do_barrier(ctrl)
Rich Lane32bf9482013-01-03 17:26:30 -080067 return 0 # for backwards compatibility
Dan Talayco41eae8b2010-03-10 13:57:06 -080068
Rich Lane5f3c9b22013-10-10 17:20:30 -070069def delete_all_groups(ctrl):
70 """
71 Delete all groups on the switch
72 @param ctrl The controller object for the test
73 """
74
75 logging.info("Deleting all groups")
Rich Lane5de5e632013-11-24 10:15:25 -080076 msg = ofp.message.group_delete(group_id=ofp.OFPG_ALL)
Rich Lane5f3c9b22013-10-10 17:20:30 -070077 ctrl.message_send(msg)
78 do_barrier(ctrl)
79
Flavio Castro1c9b1252016-02-04 18:42:58 -050080def delete_groups(ctrl, group_queue=Queue()):
81 """
82 Delete all groups on list
83 @param ctrl The controller object for the test
84 :param group_queue:
85 """
86 logging.info("Deleting groups")
87 while (not group_queue.empty()):
Pier1e4e98e2016-10-26 14:36:05 -070088 msg = ofp.message.group_delete(group_id=group_queue.get())
Flavio Castro1c9b1252016-02-04 18:42:58 -050089 ctrl.message_send(msg)
90 do_barrier(ctrl)
91
Saurav Das34992182017-04-14 15:59:48 -070092def delete_group(ctrl, group_id):
93 """
94 Delete a single group
95 @param ctrl The controller object for the test
96 :param group_id
97 """
98 logging.info("Deleting a single group with groupId:" + str(group_id))
99 msg = ofp.message.group_delete(group_id=group_id)
100 ctrl.message_send(msg)
101 do_barrier(ctrl)
102
Ed Swierk99a74de2012-08-22 06:40:54 -0700103def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -0700104 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -0700105 if w == 'l3-l4':
Rich Lanee717c6e2013-03-12 10:25:50 -0700106 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
107 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
Ed Swierk99a74de2012-08-22 06:40:54 -0700108 else:
109 return 0
110
macauley_cheng0a0a7f62015-11-06 11:36:50 +0800111def simple_packet(content='00 00 00 11 33 55 00 00 00 11 22 33 81 00 00 03 '
112 '08 00 45 00 00 2e 04 d2 00 00 7f 00 b2 47 c0 a8 '
113 '01 64 c0 a8 02 02 00 00 00 00 00 00 00 00 00 00 '
114 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'):
macauley_cheng739f54b2015-11-09 13:52:59 +0800115
116 pkt = ''.join(content.split(" ")).decode('hex')
macauley_chengc80249d2015-11-09 14:11:18 +0800117 pkt = scapy.Ether(pkt)
macauley_cheng739f54b2015-11-09 13:52:59 +0800118 if len(pkt) < 64:
119 pkt = pkt/("D" * (64 - len(pkt)))
macauley_chengc80249d2015-11-09 14:11:18 +0800120 #scapy.hexdump(pkt)
macauley_cheng0a0a7f62015-11-06 11:36:50 +0800121 return pkt
122
Dan Talayco41eae8b2010-03-10 13:57:06 -0800123def simple_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700124 eth_dst='00:01:02:03:04:05',
125 eth_src='00:06:07:08:09:0a',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700126 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700127 vlan_vid=0,
128 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700129 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800130 ip_src='192.168.0.1',
131 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700132 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800133 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800134 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700135 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700136 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700137 ip_ihl=None,
138 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800139 ):
140 """
141 Return a simple dataplane TCP packet
142
143 Supports a few parameters:
144 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700145 @param eth_dst Destinatino MAC
146 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700147 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700148 @param vlan_vid VLAN ID
149 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800150 @param ip_src IP source
151 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700152 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800153 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800154 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700155 @param tcp_sport TCP source port
156 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800157
158 Generates a simple TCP request. Users
159 shouldn't assume anything about this packet other than that
160 it is a valid ethernet/IP/TCP frame.
161 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000162
163 if MINSIZE > pktlen:
164 pktlen = MINSIZE
165
Dan Talayco551befa2010-07-15 17:05:32 -0700166 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800167 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700168 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
169 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800170 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700171 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700172 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700173 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700174 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800175 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700176 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700177 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700178 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800179 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 -0700180 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700181
Dan Talayco41eae8b2010-03-10 13:57:06 -0800182 pkt = pkt/("D" * (pktlen - len(pkt)))
183
184 return pkt
185
Rich Lane86aceb02013-07-17 18:45:38 -0700186def simple_tcpv6_packet(pktlen=100,
187 eth_dst='00:01:02:03:04:05',
188 eth_src='00:06:07:08:09:0a',
189 dl_vlan_enable=False,
190 vlan_vid=0,
191 vlan_pcp=0,
192 ipv6_src='2001:db8:85a3::8a2e:370:7334',
193 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
194 ipv6_tc=0,
195 ipv6_hlim=64,
196 ipv6_fl=0,
197 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700198 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700199 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700200 """
201 Return a simple IPv6/TCP packet
202
203 Supports a few parameters:
204 @param len Length of packet in bytes w/o CRC
205 @param eth_dst Destination MAC
206 @param eth_src Source MAC
207 @param dl_vlan_enable True if the packet is with vlan, False otherwise
208 @param vlan_vid VLAN ID
209 @param vlan_pcp VLAN priority
210 @param ipv6_src IPv6 source
211 @param ipv6_dst IPv6 destination
212 @param ipv6_tc IPv6 traffic class
213 @param ipv6_ttl IPv6 hop limit
214 @param ipv6_fl IPv6 flow label
215 @param tcp_dport TCP destination port
216 @param tcp_sport TCP source port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700217 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700218
219 Generates a simple TCP request. Users shouldn't assume anything about this
220 packet other than that it is a valid ethernet/IPv6/TCP frame.
221 """
222
223 if MINSIZE > pktlen:
224 pktlen = MINSIZE
225
226 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
227 if dl_vlan_enable or vlan_vid or vlan_pcp:
228 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
229 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 -0700230 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700231 pkt /= ("D" * (pktlen - len(pkt)))
232
233 return pkt
234
Rich Lane6ee7bea2012-10-26 16:19:29 -0700235def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700236 eth_dst='00:01:02:03:04:05',
237 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700238 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700239 vlan_vid=0,
240 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700241 dl_vlan_cfi=0,
242 ip_src='192.168.0.1',
243 ip_dst='192.168.0.2',
244 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800245 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700246 udp_sport=1234,
247 udp_dport=80,
248 ip_ihl=None,
249 ip_options=False
250 ):
251 """
252 Return a simple dataplane UDP packet
253
254 Supports a few parameters:
255 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700256 @param eth_dst Destination MAC
257 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700258 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700259 @param vlan_vid VLAN ID
260 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700261 @param ip_src IP source
262 @param ip_dst IP destination
263 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800264 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700265 @param udp_dport UDP destination port
266 @param udp_sport UDP source port
267
268 Generates a simple UDP packet. Users shouldn't assume anything about
269 this packet other than that it is a valid ethernet/IP/UDP frame.
270 """
271
272 if MINSIZE > pktlen:
273 pktlen = MINSIZE
274
275 # Note Dot1Q.id is really CFI
276 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700277 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
278 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800279 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700280 scapy.UDP(sport=udp_sport, dport=udp_dport)
281 else:
282 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700283 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800284 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700285 scapy.UDP(sport=udp_sport, dport=udp_dport)
286 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700287 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800288 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 -0700289 scapy.UDP(sport=udp_sport, dport=udp_dport)
290
291 pkt = pkt/("D" * (pktlen - len(pkt)))
292
293 return pkt
294
macauley_chengb0ec33d2015-09-04 11:32:44 +0800295
296def simple_tcp_packet_two_vlan(pktlen=100,
297 eth_dst='00:01:02:03:04:05',
298 eth_src='00:06:07:08:09:0a',
299 out_dl_vlan_enable=False,
300 in_dl_vlan_enable=False,
301 out_vlan_vid=0,
302 out_vlan_pcp=0,
303 out_dl_vlan_cfi=0,
304 in_vlan_vid=0,
305 in_vlan_pcp=0,
306 in_dl_vlan_cfi=0,
307 ip_src='192.168.0.1',
308 ip_dst='192.168.0.2',
309 ip_tos=0,
310 ip_ttl=64,
311 tcp_sport=1234,
312 tcp_dport=80,
313 tcp_flags="S",
314 ip_ihl=None,
315 ip_options=False
316 ):
317 """
318 Return a simple dataplane TCP packet
319
320 Supports a few parameters:
321 @param len Length of packet in bytes w/o CRC
322 @param eth_dst Destinatino MAC
323 @param eth_src Source MAC
324 @param dl_vlan_enable True if the packet is with vlan, False otherwise
325 @param vlan_vid VLAN ID
326 @param vlan_pcp VLAN priority
327 @param ip_src IP source
328 @param ip_dst IP destination
329 @param ip_tos IP ToS
330 @param ip_ttl IP TTL
331 @param tcp_dport TCP destination port
332 @param tcp_sport TCP source port
333 @param tcp_flags TCP Control flags
334
335 Generates a simple TCP request. Users
336 shouldn't assume anything about this packet other than that
337 it is a valid ethernet/IP/TCP frame.
338 """
339
340 if MINSIZE > pktlen:
341 pktlen = MINSIZE
342
343 # Note Dot1Q.id is really CFI
344 if (out_dl_vlan_enable and in_dl_vlan_enable):
345 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
346 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
347
348 if in_dl_vlan_enable:
349 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
350
351 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
352 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
353 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
354 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
355 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
356 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
357 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
358 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
359 assert(0) #shall not have this caes
360 else:
361 if not ip_options:
362 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
363 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
364 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
365 else:
366 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
367 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
368 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
369
370 pkt = pkt/("D" * (pktlen - len(pkt)))
371
372 return pkt
373
macauley17cd60d2015-07-27 17:41:18 +0800374def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
375 eth_src='00:06:07:08:09:0a',
376 dl_vlan_enable=False,
377 vlan_vid=0,
378 vlan_pcp=0,
379 dl_vlan_cfi=0,
380 ip_src='192.168.0.1',
381 ip_dst='192.168.0.2',
382 ip_tos=0,
383 ip_ttl=64,
384 udp_sport=1234,
385 udp_dport=4789,
386 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800387 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800388 ip_ihl=None,
389 ip_options=False
390 ):
391 """
392 Return a simple dataplane UDP packet
393
394 Supports a few parameters:
395 @param len Length of packet in bytes w/o CRC
396 @param eth_dst Destination MAC
397 @param eth_src Source MAC
398 @param dl_vlan_enable True if the packet is with vlan, False otherwise
399 @param vlan_vid VLAN ID
400 @param vlan_pcp VLAN priority
401 @param ip_src IP source
402 @param ip_dst IP destination
403 @param ip_tos IP ToS
404 @param ip_ttl IP TTL
405 @param udp_dport UDP destination port
406 @param udp_sport UDP source port
407 @param inner_pyload inner pacekt content
408 Generates a simple UDP packet. Users shouldn't assume anything about
409 this packet other than that it is a valid ethernet/IP/UDP frame.
410 """
411
412 # Note Dot1Q.id is really CFI
413 if (dl_vlan_enable):
414 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
415 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
416 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
417 scapy.UDP(sport=udp_sport, dport=udp_dport)
418 else:
419 if not ip_options:
420 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
421 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
422 scapy.UDP(sport=udp_sport, dport=udp_dport)
423 else:
424 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
425 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
426 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800427
macauley17cd60d2015-07-27 17:41:18 +0800428 #add vxlan header
429 pkt = pkt/scapy.VXLAN(vni=vnid)
430 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800431 if inner_payload!=None:
432 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800433
434 return pkt
435
Flavio Castro72a45d52015-12-02 16:37:05 -0500436def mpls_packet(pktlen=100,
437 eth_dst='00:01:02:03:04:05',
438 eth_src='00:06:07:08:09:0a',
439 dl_vlan_enable=False,
440 vlan_vid=0,
441 vlan_pcp=0,
442 dl_vlan_cfi=0,
443 ip_src='192.168.0.1',
444 ip_dst='192.168.0.2',
445 ip_tos=0,
446 ip_ttl=64,
447 tcp_sport=1234,
448 tcp_dport=80,
449 tcp_flags="S",
450 ip_ihl=None,
451 ip_options=False,
452 label=None,
Flavio Castro167f5bd2015-12-02 19:33:53 -0500453 inner_payload=True
Flavio Castro72a45d52015-12-02 16:37:05 -0500454 ):
455 if MINSIZE > pktlen:
456 pktlen = MINSIZE
457
458 # Note Dot1Q.id is really CFI
459 if (dl_vlan_enable):
460 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
461 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
462 else:
463 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
464
465 #add MPLS header
466 for i in range(len(label)):
467 l,c,s,t=label[i]
468 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
469
470 #add innder payload
471 if inner_payload!=None:
472 pkt=pkt / \
473 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
474 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Flavio Castro167f5bd2015-12-02 19:33:53 -0500475
476 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500477
478 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800479
Pier23784aa2016-09-19 20:08:21 -0700480def pw_packet(pktlen=100,
481 out_eth_dst='00:01:02:03:04:05',
482 out_eth_src='00:06:07:08:09:0a',
483 label=None,
484 cw=None,
485 in_eth_dst='00:01:02:03:04:05',
486 in_eth_src='00:06:07:08:09:0a',
487 out_dl_vlan_enable=False,
488 in_dl_vlan_enable=False,
489 out_vlan_vid=0,
490 out_vlan_pcp=0,
491 out_dl_vlan_cfi=0,
492 in_vlan_vid=0,
493 in_vlan_pcp=0,
494 in_dl_vlan_cfi=0,
495 ip_src='192.168.0.1',
496 ip_dst='192.168.0.2',
497 ip_tos=0,
498 ip_ttl=64,
499 tcp_sport=1234,
500 tcp_dport=80,
501 tcp_flags="S",
502 ip_ihl=None,
503 ip_options=False
504 ):
505 """
506 Return a simple dataplane TCP packet encapsulated
507 in a pw packet
508 """
509
510 # Add the outer ethernet header
511 if MINSIZE > pktlen:
512 pktlen = MINSIZE
513
514 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
515
516 #add MPLS header
517 for i in range(len(label)):
518 l,c,s,t=label[i]
519 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
520
521 #add the PW CW
522 l,c,s,t=cw
523 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
524
525 # Note Dot1Q.id is really CFI
526 if (out_dl_vlan_enable and in_dl_vlan_enable):
527
528 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
529 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
530
531 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
532
533 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
534 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
535
536 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
537
538 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
539 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
540 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
541 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
542
543 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
544
545 assert(0) #shall not have this caes
546
547 else:
548 if not ip_options:
549 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
550 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
551 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
552 else:
553 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
554 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
555 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
556
557 pkt = pkt/("D" * (pktlen - len(pkt)))
558
559 return pkt
560
Pier1e4e98e2016-10-26 14:36:05 -0700561def mplsv6_packet(pktlen=100,
562 eth_dst='00:01:02:03:04:05',
563 eth_src='00:06:07:08:09:0a',
564 dl_vlan_enable=False,
565 vlan_vid=0,
566 vlan_pcp=0,
567 dl_vlan_cfi=0,
568 ipv6_src='2001:db8:85a3::8a2e:370:7334',
569 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
570 ipv6_tc=0,
571 ipv6_hlim=64,
572 ipv6_fl=0,
573 tcp_sport=1234,
574 tcp_dport=80,
575 tcp_flags="S",
576 label=None,
577 inner_payload=True
578 ):
579 if MINSIZE > pktlen:
580 pktlen = MINSIZE
581
582 # Note Dot1Q.id is really CFI
583 if (dl_vlan_enable):
584 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
585 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
586 else:
587 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
588
589 #add MPLS header
590 for i in range(len(label)):
591 l,c,s,t=label[i]
592 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
593
594 #add innder payload
595 if inner_payload!=None:
596 pkt=pkt / \
597 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
598 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
599
600 pkt = pkt/("D" * (pktlen - len(pkt)))
601
602 return pkt
603
macauley_cheng45833df2015-08-31 15:19:07 +0800604def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
605 eth_src='00:06:07:08:09:0a',
606 dl_vlan_enable=False,
607 vlan_vid=0,
608 vlan_pcp=0,
609 dl_vlan_cfi=0,
610 label=None,
611 inner_payload=None
612 ):
613 """
614 Return a simple dataplane MPLS packet
615
616 Supports a few parameters:
617 @param len Length of packet in bytes w/o CRC
618 @param eth_dst Destination MAC
619 @param eth_src Source MAC
620 @param dl_vlan_enable True if the packet is with vlan, False otherwise
621 @param vlan_vid VLAN ID
622 @param vlan_pcp VLAN priority
623 @param inner_pyload inner pacekt content
624 Generates a simple MPLS packet. Users shouldn't assume anything about
625 this packet other than that it is a valid ethernet/IP/UDP frame.
626 """
627
628 # Note Dot1Q.id is really CFI
629 if (dl_vlan_enable):
630 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
631 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
632 else:
633 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
634
635 #add MPLS header
636 for i in range(len(label)):
637 l,c,s,t=label[i]
638 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
639
640 #add innder payload
641 if inner_payload!=None:
642 pkt=pkt/inner_payload
643
644 return pkt
645
Rich Lane86aceb02013-07-17 18:45:38 -0700646def simple_udpv6_packet(pktlen=100,
647 eth_dst='00:01:02:03:04:05',
648 eth_src='00:06:07:08:09:0a',
649 dl_vlan_enable=False,
650 vlan_vid=0,
651 vlan_pcp=0,
652 ipv6_src='2001:db8:85a3::8a2e:370:7334',
653 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
654 ipv6_tc=0,
655 ipv6_hlim=64,
656 ipv6_fl=0,
657 udp_sport=1234,
658 udp_dport=80):
659 """
660 Return a simple IPv6/UDP packet
661
662 Supports a few parameters:
663 @param len Length of packet in bytes w/o CRC
664 @param eth_dst Destination MAC
665 @param eth_src Source MAC
666 @param dl_vlan_enable True if the packet is with vlan, False otherwise
667 @param vlan_vid VLAN ID
668 @param vlan_pcp VLAN priority
669 @param ipv6_src IPv6 source
670 @param ipv6_dst IPv6 destination
671 @param ipv6_tc IPv6 traffic class
672 @param ipv6_ttl IPv6 hop limit
673 @param ipv6_fl IPv6 flow label
674 @param udp_dport UDP destination port
675 @param udp_sport UDP source port
676
677 Generates a simple UDP request. Users shouldn't assume anything about this
678 packet other than that it is a valid ethernet/IPv6/UDP frame.
679 """
680
681 if MINSIZE > pktlen:
682 pktlen = MINSIZE
683
684 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
685 if dl_vlan_enable or vlan_vid or vlan_pcp:
686 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
687 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
688 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
689 pkt /= ("D" * (pktlen - len(pkt)))
690
691 return pkt
692
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700693def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700694 eth_dst='00:01:02:03:04:05',
695 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700696 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700697 vlan_vid=0,
698 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700699 ip_src='192.168.0.1',
700 ip_dst='192.168.0.2',
701 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800702 ip_ttl=64,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600703 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700704 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600705 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600706 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700707 """
708 Return a simple ICMP packet
709
710 Supports a few parameters:
711 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700712 @param eth_dst Destinatino MAC
713 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700714 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700715 @param vlan_vid VLAN ID
716 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700717 @param ip_src IP source
718 @param ip_dst IP destination
719 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800720 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600721 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700722 @param icmp_type ICMP type
723 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600724 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700725
726 Generates a simple ICMP ECHO REQUEST. Users
727 shouldn't assume anything about this packet other than that
728 it is a valid ethernet/ICMP frame.
729 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000730
731 if MINSIZE > pktlen:
732 pktlen = MINSIZE
733
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700734 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700735 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
736 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600737 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600738 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700739 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700740 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600741 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600742 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700743
744 pkt = pkt/("0" * (pktlen - len(pkt)))
745
746 return pkt
747
Rich Lane86aceb02013-07-17 18:45:38 -0700748def simple_icmpv6_packet(pktlen=100,
749 eth_dst='00:01:02:03:04:05',
750 eth_src='00:06:07:08:09:0a',
751 dl_vlan_enable=False,
752 vlan_vid=0,
753 vlan_pcp=0,
754 ipv6_src='2001:db8:85a3::8a2e:370:7334',
755 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
756 ipv6_tc=0,
757 ipv6_hlim=64,
758 ipv6_fl=0,
759 icmp_type=8,
760 icmp_code=0):
761 """
762 Return a simple ICMPv6 packet
763
764 Supports a few parameters:
765 @param len Length of packet in bytes w/o CRC
766 @param eth_dst Destination MAC
767 @param eth_src Source MAC
768 @param dl_vlan_enable True if the packet is with vlan, False otherwise
769 @param vlan_vid VLAN ID
770 @param vlan_pcp VLAN priority
771 @param ipv6_src IPv6 source
772 @param ipv6_dst IPv6 destination
773 @param ipv6_tc IPv6 traffic class
774 @param ipv6_ttl IPv6 hop limit
775 @param ipv6_fl IPv6 flow label
776 @param icmp_type ICMP type
777 @param icmp_code ICMP code
778
779 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
780 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
781 """
782
783 if MINSIZE > pktlen:
784 pktlen = MINSIZE
785
786 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
787 if dl_vlan_enable or vlan_vid or vlan_pcp:
788 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
789 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
790 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
791 pkt /= ("D" * (pktlen - len(pkt)))
792
793 return pkt
794
Shudong Zhouc7562b12013-02-06 01:12:18 -0800795def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700796 eth_dst='ff:ff:ff:ff:ff:ff',
797 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800798 vlan_vid=0,
799 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800800 arp_op=1,
801 ip_snd='192.168.0.1',
802 ip_tgt='192.168.0.2',
803 hw_snd='00:06:07:08:09:0a',
804 hw_tgt='00:00:00:00:00:00',
805 ):
806 """
807 Return a simple ARP packet
808
809 Supports a few parameters:
810 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700811 @param eth_dst Destinatino MAC
812 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800813 @param arp_op Operation (1=request, 2=reply)
814 @param ip_snd Sender IP
815 @param ip_tgt Target IP
816 @param hw_snd Sender hardware address
817 @param hw_tgt Target hardware address
818
819 Generates a simple ARP REQUEST. Users
820 shouldn't assume anything about this packet other than that
821 it is a valid ethernet/ARP frame.
822 """
823
824 if MINSIZE > pktlen:
825 pktlen = MINSIZE
826
Rich Lanee01611f2014-01-15 14:55:11 -0800827 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
828 if vlan_vid or vlan_pcp:
829 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
830 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 -0800831
Rich Laned459ce52014-01-24 12:09:54 -0800832 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800833
834 return pkt
835
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700836def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800837 eth_dst='00:01:02:03:04:05',
838 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700839 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000840
841 if MINSIZE > pktlen:
842 pktlen = MINSIZE
843
Rich Laned0478ff2013-03-11 12:46:58 -0700844 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700845
846 pkt = pkt/("0" * (pktlen - len(pkt)))
847
848 return pkt
849
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800850def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700851 eth_dst='00:01:02:03:04:05',
852 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800853 dl_vlan_outer=20,
854 dl_vlan_pcp_outer=0,
855 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700856 vlan_vid=10,
857 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800858 dl_vlan_cfi=0,
859 ip_src='192.168.0.1',
860 ip_dst='192.168.0.2',
861 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800862 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800863 tcp_sport=1234,
864 tcp_dport=80,
865 ip_ihl=None,
866 ip_options=False
867 ):
868 """
869 Return a doubly tagged dataplane TCP packet
870
871 Supports a few parameters:
872 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700873 @param eth_dst Destinatino MAC
874 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800875 @param dl_vlan_outer Outer VLAN ID
876 @param dl_vlan_pcp_outer Outer VLAN priority
877 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700878 @param vlan_vid Inner VLAN ID
879 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800880 @param dl_vlan_cfi VLAN cfi bit
881 @param ip_src IP source
882 @param ip_dst IP destination
883 @param ip_tos IP ToS
884 @param tcp_dport TCP destination port
885 @param ip_sport TCP source port
886
887 Generates a TCP request. Users
888 shouldn't assume anything about this packet other than that
889 it is a valid ethernet/IP/TCP frame.
890 """
891
892 if MINSIZE > pktlen:
893 pktlen = MINSIZE
894
895 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700896 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800897 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700898 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800899 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800900 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
901
902 pkt = pkt/("D" * (pktlen - len(pkt)))
903
904 return pkt
905
Shudong Zhoub7f12462012-11-20 13:01:12 -0800906def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700907 """
908 Do a barrier command
909 Return 0 on success, -1 on error
910 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700911 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800912 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800913 if resp is None:
914 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700915 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800916 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700917
Rich Lane9a003812012-10-04 17:17:59 -0700918def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700919 """
920 Get a port's configuration
921
922 Gets the switch feature configuration and grabs one port's
923 configuration
924
925 @returns (hwaddr, config, advert) The hwaddress, configuration and
926 advertised values
927 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700928
929 if ofp.OFP_VERSION <= 3:
930 request = ofp.message.features_request()
931 reply, _ = controller.transact(request)
932 if reply is None:
933 logging.warn("Get feature request failed")
934 return None, None, None
935 logging.debug(reply.show())
936 ports = reply.ports
937 else:
938 request = ofp.message.port_desc_stats_request()
939 # TODO do multipart correctly
940 reply, _ = controller.transact(request)
941 if reply is None:
942 logging.warn("Port desc stats request failed")
943 return None, None, None
944 logging.debug(reply.show())
945 ports = reply.entries
946
947 for port in ports:
948 if port.port_no == port_no:
949 return (port.hw_addr, port.config, port.advertised)
Dan Talayco92c99122010-06-03 13:53:18 -0700950
Rich Lane9a003812012-10-04 17:17:59 -0700951 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700952 return None, None, None
953
Rich Lane9a003812012-10-04 17:17:59 -0700954def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700955 """
956 Set the port configuration according the given parameters
957
958 Gets the switch feature configuration and updates one port's
959 configuration value according to config and mask
960 """
Rich Lane9a003812012-10-04 17:17:59 -0700961 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700962
963 hw_addr, _, _ = port_config_get(controller, port_no)
964
Rich Lanee717c6e2013-03-12 10:25:50 -0700965 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700966 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700967 if hw_addr != None:
968 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700969 mod.config = config
970 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700971 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800972 controller.message_send(mod)
973 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700974
Rich Lane2014f9b2012-10-05 15:29:40 -0700975def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700976 """
977 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700978 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700979 @param pkt Expected packet; may be None if yes_ports is empty
980 @param yes_ports Set or list of ports that should recieve packet
981 @param no_ports Set or list of ports that should not receive packet
982 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700983
984 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700985 """
Rich Lane91765672012-12-06 16:33:04 -0800986
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700987 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800988 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700989 exp_pkt_arg = pkt
990
Dan Talayco92c99122010-06-03 13:53:18 -0700991 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700992 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700993 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -0800994 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700995 assert_if.assertTrue(rcv_pkt is not None,
996 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -0800997 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -0800998 logging.debug("Expected %s" % format_packet(pkt))
999 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001000 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -08001001 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -07001002 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -07001003 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -07001004 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -07001005 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001006 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001007 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -08001008 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -07001009 assert_if.assertTrue(rcv_pkt is None,
1010 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -07001011
1012
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001013def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -07001014 """
1015 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -07001016 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001017
1018 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -07001019
1020 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -07001021 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001022 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001023 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001024 exp_pkt_arg = exp_pkt
1025
Dan Talaycof6e76c02012-03-23 10:56:12 -07001026 if type(egr_ports) == type([]):
1027 egr_port_list = egr_ports
1028 else:
1029 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001030
Dan Talaycof6e76c02012-03-23 10:56:12 -07001031 # Expect a packet from each port on egr port list
1032 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001033 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001034 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001035 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001036 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001037 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001038
Dan Talaycof6e76c02012-03-23 10:56:12 -07001039 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -07001040 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001041 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001042
Dan Talaycof6e76c02012-03-23 10:56:12 -07001043 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001044 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -07001045 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001046 str(rcv_port))
1047
1048 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001049 logging.error("ERROR: Packet match failed.")
1050 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001051 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001052 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001053 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001054 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1055 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001056 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001057 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001058
Dan Talayco551befa2010-07-15 17:05:32 -07001059def match_verify(parent, req_match, res_match):
1060 """
1061 Verify flow matches agree; if they disagree, report where
1062
1063 parent must implement assertEqual
1064 Use str() to ensure content is compared and not pointers
1065 """
1066
1067 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1068 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1069 " != " + hex(res_match.wildcards))
1070 parent.assertEqual(req_match.in_port, res_match.in_port,
1071 'Match failed: in_port: ' + str(req_match.in_port) +
1072 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001073 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1074 'Match failed: eth_src: ' + str(req_match.eth_src) +
1075 " != " + str(res_match.eth_src))
1076 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1077 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1078 " != " + str(res_match.eth_dst))
1079 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1080 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1081 " != " + str(res_match.vlan_vid))
1082 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
1083 'Match failed: vlan_pcp: ' +
1084 str(req_match.vlan_pcp) + " != " +
1085 str(res_match.vlan_pcp))
1086 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1087 'Match failed: eth_type: ' + str(req_match.eth_type) +
1088 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001089
Rich Lanee717c6e2013-03-12 10:25:50 -07001090 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001091 and (req_match.eth_type == IP_ETHERTYPE)):
1092 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1093 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1094 " != " + str(res_match.ip_dscp))
1095 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1096 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1097 " != " + str(res_match.ip_proto))
1098 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1099 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1100 " != " + str(res_match.ipv4_src))
1101 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1102 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1103 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001104
Rich Lanee717c6e2013-03-12 10:25:50 -07001105 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001106 and ((req_match.ip_proto == TCP_PROTOCOL)
1107 or (req_match.ip_proto == UDP_PROTOCOL))):
1108 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
1109 'Match failed: tcp_src: ' +
1110 str(req_match.tcp_src) +
1111 " != " + str(res_match.tcp_src))
1112 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
1113 'Match failed: tcp_dst: ' +
1114 str(req_match.tcp_dst) +
1115 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001116
Ed Swierk99a74de2012-08-22 06:40:54 -07001117def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001118 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001119 if ofp.OFP_VERSION in [1, 2]:
1120 match.wildcards |= required_wildcards(parent)
1121 else:
1122 # TODO remove incompatible OXM entries
1123 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001124 return match
1125
1126def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001127 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001128 """
1129 Create a flow message
1130
1131 Match on packet with given wildcards.
1132 See flow_match_test for other parameter descriptoins
1133 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001134 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001135 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001136 """
Rich Lanef6883512013-03-11 17:00:09 -07001137 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001138 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001139 if wildcards is None:
1140 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001141 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001142 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001143 match.wildcards = wildcards
1144 match.in_port = ing_port
1145
Dan Talaycof6e76c02012-03-23 10:56:12 -07001146 if type(egr_ports) == type([]):
1147 egr_port_list = egr_ports
1148 else:
1149 egr_port_list = [egr_ports]
1150
Rich Lanee717c6e2013-03-12 10:25:50 -07001151 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001152 request.match = match
1153 request.buffer_id = 0xffffffff
1154 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001155 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001156 request.hard_timeout = 1
1157
Rich Lane400fb9b2013-10-10 17:20:54 -07001158 if ofp.OFP_VERSION == 1:
1159 actions = request.actions
1160 else:
1161 actions = []
1162 request.instructions.append(ofp.instruction.apply_actions(actions))
1163
Dan Talayco551befa2010-07-15 17:05:32 -07001164 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001165 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001166
1167 # Set up output/enqueue action if directed
1168 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001169 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001170 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001171 for egr_port in egr_port_list:
1172 act.port = egr_port
1173 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001174 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001175 elif egr_ports is not None:
1176 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001177 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001178 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001179 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001180
Rich Lane9a003812012-10-04 17:17:59 -07001181 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001182
1183 return request
1184
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001185def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001186 """
1187 Install a flow mod message in the switch
1188
1189 @param parent Must implement controller, assertEqual, assertTrue
1190 @param request The request, all set to go
1191 @param clear_table If true, clear the flow table before installing
1192 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001193
Rich Lane2014f9b2012-10-05 15:29:40 -07001194 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001195 if(clear_table_override != None):
1196 clear_table = clear_table_override
1197
1198 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001199 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001200 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001201
Rich Lane9a003812012-10-04 17:17:59 -07001202 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001203 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001204
Rich Lane3a261d52013-01-03 17:45:08 -08001205 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001206
Ed Swierk99a74de2012-08-22 06:40:54 -07001207def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001208 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001209 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001210 """
1211 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001212 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001213
1214 Run test with packet through switch from ing_port to egr_port
1215 See flow_match_test for parameter descriptions
1216 """
1217
Ed Swierk99a74de2012-08-22 06:40:54 -07001218 if wildcards is None:
1219 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -07001220 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001221 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001222 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001223 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001224 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001225 if exp_pkt is None:
1226 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001227
1228 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001229 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001230 action_list=action_list)
1231
1232 flow_msg_install(parent, request)
1233
Rich Lane9a003812012-10-04 17:17:59 -07001234 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001235 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001236 parent.dataplane.send(ing_port, str(pkt))
1237
Rich Lane8f45e2d2013-10-01 16:06:54 -07001238 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001239 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001240
Rich Lane89725bb2012-12-03 16:23:27 -08001241def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001242 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001243 action_list=None):
1244 """
1245 Packet-out test on single TCP packet
1246 @param egr_ports A single port or list of ports
1247
1248 Run test sending packet-out to egr_ports. The goal is to test the actions
1249 taken on the packet, not the matching which is of course irrelevant.
1250 See flow_match_test for parameter descriptions
1251 """
1252
1253 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001254 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001255 if exp_pkt is None:
1256 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001257
Rich Lanee717c6e2013-03-12 10:25:50 -07001258 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001259 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001260 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001261 msg.data = str(pkt)
1262 if action_list is not None:
1263 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001264 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001265
1266 # Set up output action
1267 if egr_ports is not None:
1268 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001269 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001270 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001271 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001272
1273 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001274 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001275
Rich Lane8f45e2d2013-10-01 16:06:54 -07001276 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001277 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001278
Dan Talaycof6e76c02012-03-23 10:56:12 -07001279def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1280 """
1281 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001282 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001283 @param of_ports List of OF port numbers
1284 @param how_many Number of ports to be added to the list
1285 @param exclude_list List of ports not to be used
1286 @returns An empty list if unable to find enough ports
1287 """
1288
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001289 if how_many == 0:
1290 return []
1291
Dan Talaycof6e76c02012-03-23 10:56:12 -07001292 count = 0
1293 egr_ports = []
1294 for egr_idx in range(len(of_ports)):
1295 if of_ports[egr_idx] not in exclude_list:
1296 egr_ports.append(of_ports[egr_idx])
1297 count += 1
1298 if count >= how_many:
1299 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001300 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001301 return []
1302
Rich Laned0478ff2013-03-11 12:46:58 -07001303def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001304 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001305 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001306 """
Rich Lane89725bb2012-12-03 16:23:27 -08001307 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001308
1309 @param max_test If > 0 no more than this number of tests are executed.
1310 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001311 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001312 @param pkt If not None, use this packet for ingress
1313 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001314 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001315 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1316 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001317 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001318 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001319 if wildcards is None:
1320 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001321 of_ports = port_map.keys()
1322 of_ports.sort()
1323 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1324 test_count = 0
1325
Dan Talaycocfa172f2012-03-23 12:03:00 -07001326 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001327 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001328
Dan Talayco551befa2010-07-15 17:05:32 -07001329 for ing_idx in range(len(of_ports)):
1330 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -07001331 egr_ports = get_egr_list(parent, of_ports, egr_count,
1332 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001333 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001334 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001335 if len(egr_ports) == 0:
1336 parent.assertTrue(0, "Failed to generate egress port list")
1337
1338 flow_match_test_port_pair(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001339 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001340 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001341 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001342 test_count += 1
1343 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001344 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001345 break
1346
Ed Swierk38eea082013-01-02 19:46:20 -08001347 if not test_param_get('pktout_actions', default=True):
1348 return
Rich Lane89725bb2012-12-03 16:23:27 -08001349
1350 ingress_port = of_ports[0]
1351 egr_ports = get_egr_list(parent, of_ports, egr_count,
1352 exclude_list=[ingress_port])
1353 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001354 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001355 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001356 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001357 pkt=pkt, exp_pkt=exp_pkt,
1358 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001359
Rich Lane2014f9b2012-10-05 15:29:40 -07001360def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001361 """
1362 Return value passed via test-params if present
1363
Dan Talayco4b2bee62010-07-20 14:10:05 -07001364 @param key The lookup key
1365 @param default Default value to use if not found
1366
1367 If the pair 'key=val' appeared in the string passed to --test-params
1368 on the command line, return val (as interpreted by exec). Otherwise
1369 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001370
1371 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
1372 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001373 """
1374 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001375 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001376 except:
1377 return default
1378
Dan Talayco4b2bee62010-07-20 14:10:05 -07001379 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001380 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001381 except:
1382 return default
1383
1384def action_generate(parent, field_to_mod, mod_field_vals):
1385 """
1386 Create an action to modify the field indicated in field_to_mod
1387
1388 @param parent Must implement, assertTrue
1389 @param field_to_mod The field to modify as a string name
1390 @param mod_field_vals Hash of values to use for modified values
1391 """
1392
1393 act = None
1394
1395 if field_to_mod in ['pktlen']:
1396 return None
1397
Rich Laned0478ff2013-03-11 12:46:58 -07001398 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001399 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001400 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001401 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001402 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001403 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001404 elif field_to_mod == 'dl_vlan_enable':
1405 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001406 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001407 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001408 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001409 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001410 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001411 act.vlan_vid = mod_field_vals['vlan_vid']
1412 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001413 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001414 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001415 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001416 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001417 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001418 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001419 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001420 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001421 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001422 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001423 act.nw_tos = mod_field_vals['ip_tos']
1424 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001425 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001426 act.tp_port = mod_field_vals['tcp_sport']
1427 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001428 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001429 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001430 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001431 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001432 act.tp_port = mod_field_vals['udp_sport']
1433 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001434 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001435 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001436 else:
1437 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1438
1439 return act
1440
1441def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001442 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001443 """
1444 Set up the ingress and expected packet and action list for a test
1445
Rich Lane2014f9b2012-10-05 15:29:40 -07001446 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001447 @param start_field_values Field values to use for ingress packet (optional)
1448 @param mod_field_values Field values to use for modified packet (optional)
1449 @param mod_fields The list of fields to be modified by the switch in the test.
1450 @params check_test_params If True, will check the parameters vid, add_vlan
1451 and strip_vlan from the command line.
1452
1453 Returns a triple: pkt-to-send, expected-pkt, action-list
1454 """
1455
1456 new_actions = []
1457
Dan Talayco4b2bee62010-07-20 14:10:05 -07001458 base_pkt_params = {}
1459 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001460 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1461 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001462 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001463 base_pkt_params['vlan_vid'] = 2
1464 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001465 base_pkt_params['ip_src'] = '192.168.0.1'
1466 base_pkt_params['ip_dst'] = '192.168.0.2'
1467 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001468 if tp == "tcp":
1469 base_pkt_params['tcp_sport'] = 1234
1470 base_pkt_params['tcp_dport'] = 80
1471 elif tp == "udp":
1472 base_pkt_params['udp_sport'] = 1234
1473 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001474 for keyname in start_field_vals.keys():
1475 base_pkt_params[keyname] = start_field_vals[keyname]
1476
1477 mod_pkt_params = {}
1478 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001479 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1480 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001481 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001482 mod_pkt_params['vlan_vid'] = 3
1483 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484 mod_pkt_params['ip_src'] = '10.20.30.40'
1485 mod_pkt_params['ip_dst'] = '50.60.70.80'
1486 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001487 if tp == "tcp":
1488 mod_pkt_params['tcp_sport'] = 4321
1489 mod_pkt_params['tcp_dport'] = 8765
1490 elif tp == "udp":
1491 mod_pkt_params['udp_sport'] = 4321
1492 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493 for keyname in mod_field_vals.keys():
1494 mod_pkt_params[keyname] = mod_field_vals[keyname]
1495
1496 # Check for test param modifications
1497 strip = False
1498 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001499 add_vlan = test_param_get('add_vlan')
1500 strip_vlan = test_param_get('strip_vlan')
1501 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502
1503 if add_vlan and strip_vlan:
1504 parent.assertTrue(0, "Add and strip VLAN both specified")
1505
1506 if vid:
1507 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001508 base_pkt_params['vlan_vid'] = vid
1509 if 'vlan_vid' in mod_fields:
1510 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001511
1512 if add_vlan:
1513 base_pkt_params['dl_vlan_enable'] = False
1514 mod_pkt_params['dl_vlan_enable'] = True
1515 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1516 mod_fields.append('pktlen')
1517 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001518 if 'vlan_vid' not in mod_fields:
1519 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520 elif strip_vlan:
1521 base_pkt_params['dl_vlan_enable'] = True
1522 mod_pkt_params['dl_vlan_enable'] = False
1523 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1524 mod_fields.append('dl_vlan_enable')
1525 mod_fields.append('pktlen')
1526
Rich Lane110e0e32012-10-26 16:21:46 -07001527 if tp == "tcp":
1528 packet_builder = simple_tcp_packet
1529 elif tp == "udp":
1530 packet_builder = simple_udp_packet
1531 else:
1532 raise NotImplementedError("unknown transport protocol %s" % tp)
1533
Dan Talayco4b2bee62010-07-20 14:10:05 -07001534 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001535 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001536
1537 # Build the expected packet, modifying the indicated fields
1538 for item in mod_fields:
1539 base_pkt_params[item] = mod_pkt_params[item]
1540 act = action_generate(parent, item, mod_pkt_params)
1541 if act:
1542 new_actions.append(act)
1543
Rich Lane110e0e32012-10-26 16:21:46 -07001544 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001545
1546 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001547
1548# Generate a simple "drop" flow mod
1549# If in_band is true, then only drop from first test port
1550def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001551 request = ofp.message.flow_add()
1552 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001553 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001554 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001555 for of_port, ifname in port_map.items(): # Grab first port
1556 break
1557 request.match.in_port = of_port
1558 request.buffer_id = 0xffffffff
1559 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001560
1561def skip_message_emit(parent, s):
1562 """
1563 Print out a 'skipped' message to stderr
1564
1565 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001566 """
1567 global skipped_test_count
1568
1569 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001570 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001571 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001572 sys.stderr.write("(skipped) ")
1573 else:
1574 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001575
Dan Talayco8a64e332012-03-28 14:53:20 -07001576
1577def all_stats_get(parent):
1578 """
1579 Get the aggregate stats for all flows in the table
1580 @param parent Test instance with controller connection and assert
1581 @returns dict with keys flows, packets, bytes, active (flows),
1582 lookups, matched
1583 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001584 stat_req = ofp.message.aggregate_stats_request()
1585 stat_req.match = ofp.match()
1586 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001587 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001588 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001589
1590 rv = {}
1591
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001592 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001593 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001594
Rich Lane5fd6faf2013-03-11 13:30:20 -07001595 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001596 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
1597 obj.packet_count, obj.byte_count)
1598 break
1599
Rich Lanee717c6e2013-03-12 10:25:50 -07001600 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001601 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001602
1603
1604 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001605 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001606 rv["active"] += obj.active_count
1607 rv["lookups"] += obj.lookup_count
1608 rv["matched"] += obj.matched_count
1609
1610 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001611
Rich Lane7744e112013-01-11 17:23:57 -08001612_import_blacklist.add('FILTER')
Dan Talayco2baf8b52012-03-30 09:55:42 -07001613FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
1614 for x in range(256)])
1615
1616def hex_dump_buffer(src, length=16):
1617 """
1618 Convert src to a hex dump string and return the string
1619 @param src The source buffer
1620 @param length The number of bytes shown in each line
1621 @returns A string showing the hex dump
1622 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001623 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001624 for i in xrange(0, len(src), length):
1625 chars = src[i:i+length]
1626 hex = ' '.join(["%02x" % ord(x) for x in chars])
1627 printable = ''.join(["%s" % ((ord(x) <= 127 and
1628 FILTER[ord(x)]) or '.') for x in chars])
1629 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1630 return ''.join(result)
1631
1632def format_packet(pkt):
1633 return "Packet length %d \n%s" % (len(str(pkt)),
1634 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001635
1636def inspect_packet(pkt):
1637 """
1638 Wrapper around scapy's show() method.
1639 @returns A string showing the dissected packet.
1640 """
1641 from cStringIO import StringIO
1642 out = None
1643 backup = sys.stdout
1644 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001645 tmp = StringIO()
1646 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001647 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001648 out = tmp.getvalue()
1649 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001650 finally:
1651 sys.stdout = backup
1652 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001653
1654def nonstandard(cls):
1655 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001656 Testcase decorator that marks the test as being non-standard.
1657 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001658 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001659 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001660 return cls
1661
1662def disabled(cls):
1663 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001664 Testcase decorator that marks the test as being disabled.
1665 These tests are not automatically added to the "standard" group or
1666 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001667 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001668 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001669 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001670
1671def group(name):
1672 """
1673 Testcase decorator that adds the test to a group.
1674 """
1675 def fn(cls):
1676 if not hasattr(cls, "_groups"):
1677 cls._groups = []
1678 cls._groups.append(name)
1679 return cls
1680 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001681
1682def version(ver):
1683 """
1684 Testcase decorator that specifies which versions of OpenFlow the test
1685 supports. The default is 1.0+. This decorator may only be used once.
1686
1687 Supported syntax:
1688 1.0 -> 1.0
1689 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1690 1.0+ -> 1.0, 1.1, 1.2, 1.3
1691 """
1692 versions = parse_version(ver)
1693 def fn(cls):
1694 cls._versions = versions
1695 return cls
1696 return fn
1697
1698def parse_version(ver):
1699 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1700 if re.match("^1\.\d+$", ver):
1701 versions = set([ver])
1702 elif re.match("^(1\.\d+)\+$", ver):
1703 if not ver[:-1] in allowed_versions:
1704 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1705 versions = set()
1706 if ver != "1.1+": versions.add("1.0")
1707 if ver != "1.2+": versions.add("1.1")
1708 if ver != "1.3+": versions.add("1.2")
1709 versions.add("1.3")
1710 else:
1711 versions = set(ver.split(','))
1712
1713 for version in versions:
1714 if not version in allowed_versions:
1715 raise ValueError("invalid OpenFlow version %s" % version)
1716
1717 return versions
1718
1719assert(parse_version("1.0") == set(["1.0"]))
1720assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1721assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001722
Rich Laneae3428c2013-03-07 14:37:42 -08001723def get_stats(test, req):
1724 """
1725 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1726 """
Rich Lane609194f2013-10-21 06:17:37 -07001727 msgtype = ofp.OFPT_STATS_REPLY
1728 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001729 stats = []
1730 reply, _ = test.controller.transact(req)
1731 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001732 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001733 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001734 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001735 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001736 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001737 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001738 return stats
1739
Rich Lanebd56ed62013-07-10 15:49:44 -07001740def get_flow_stats(test, match, table_id=None,
1741 out_port=None, out_group=None,
1742 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001743 """
1744 Retrieve a list of flow stats entries.
1745 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001746
1747 if table_id == None:
1748 if ofp.OFP_VERSION <= 2:
1749 table_id = 0xff
1750 else:
1751 table_id = ofp.OFPTT_ALL
1752
Rich Lanef3bc48c2013-05-03 17:39:35 -07001753 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001754 if ofp.OFP_VERSION == 1:
1755 out_port = ofp.OFPP_NONE
1756 else:
1757 out_port = ofp.OFPP_ANY
1758
1759 if out_group == None:
1760 if ofp.OFP_VERSION > 1:
1761 out_group = ofp.OFPP_ANY
1762
Rich Lanee717c6e2013-03-12 10:25:50 -07001763 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001764 table_id=table_id,
1765 out_port=out_port)
1766 if ofp.OFP_VERSION > 1:
1767 req.out_group = out_group
1768 req.cookie = cookie
1769 req.cookie_mask = cookie_mask
1770
Rich Laneae3428c2013-03-07 14:37:42 -08001771 return get_stats(test, req)
1772
Rich Lane968b6192013-03-07 15:34:43 -08001773def get_port_stats(test, port_no):
1774 """
1775 Retrieve a list of port stats entries.
1776 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001777 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001778 return get_stats(test, req)
1779
Rich Lane6a334922013-03-07 16:14:52 -08001780def get_queue_stats(test, port_no, queue_id):
1781 """
1782 Retrieve a list of queue stats entries.
1783 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001784 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001785 return get_stats(test, req)
1786
Rich Laneae3428c2013-03-07 14:37:42 -08001787def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001788 initial=[],
1789 pkts=None, bytes=None):
1790 """
1791 Verify that flow stats changed as expected.
1792
1793 Optionally takes an 'initial' list of stats entries, as returned by
1794 get_flow_stats(). If 'initial' is not given the counters are assumed to
1795 begin at 0.
1796 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001797
Rich Laneae3428c2013-03-07 14:37:42 -08001798 def accumulate(stats):
1799 pkts_acc = bytes_acc = 0
1800 for stat in stats:
1801 pkts_acc += stat.packet_count
1802 bytes_acc += stat.byte_count
1803 return (pkts_acc, bytes_acc)
1804
1805 pkts_before, bytes_before = accumulate(initial)
1806
1807 # Wait 10s for counters to update
1808 pkt_diff = byte_diff = None
1809 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001810 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001811 pkts_after, bytes_after = accumulate(stats)
1812 pkt_diff = pkts_after - pkts_before
1813 byte_diff = bytes_after - bytes_before
1814 if (pkts == None or pkt_diff >= pkts) and \
1815 (bytes == None or byte_diff >= bytes):
1816 break
Dan Talayco53724732013-03-08 23:54:02 -08001817 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001818
1819 if pkts != None:
1820 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1821
1822 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001823 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1824 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001825
Rich Lane968b6192013-03-07 15:34:43 -08001826def verify_port_stats(test, port,
1827 initial=[],
1828 tx_pkts=None, rx_pkts=None,
1829 tx_bytes=None, rx_bytes=None):
1830 """
1831 Verify that port stats changed as expected.
1832
1833 Optionally takes an 'initial' list of stats entries, as returned by
1834 get_port_stats(). If 'initial' is not given the counters are assumed to
1835 begin at 0.
1836 """
1837 def accumulate(stats):
1838 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1839 for stat in stats:
1840 tx_pkts_acc += stat.tx_packets
1841 rx_pkts_acc += stat.rx_packets
1842 tx_bytes_acc += stat.tx_bytes
1843 rx_bytes_acc += stat.rx_bytes
1844 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1845
1846 tx_pkts_before, rx_pkts_before, \
1847 tx_bytes_before, rx_bytes_before = accumulate(initial)
1848
1849 # Wait 10s for counters to update
1850 for i in range(0, 100):
1851 stats = get_port_stats(test, port)
1852 tx_pkts_after, rx_pkts_after, \
1853 tx_bytes_after, rx_bytes_after = accumulate(stats)
1854 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1855 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1856 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1857 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001858 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1859 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001860 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1861 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001862 break
1863 time.sleep(0.1)
1864
1865 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001866 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1867 "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 -08001868 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001869 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1870 "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 -08001871 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001872 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1873 "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 -08001874 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001875 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1876 "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 -08001877
Rich Lane6a334922013-03-07 16:14:52 -08001878def verify_queue_stats(test, port_no, queue_id,
1879 initial=[],
1880 pkts=None, bytes=None):
1881 """
1882 Verify that queue stats changed as expected.
1883
1884 Optionally takes an 'initial' list of stats entries, as returned by
1885 get_queue_stats(). If 'initial' is not given the counters are assumed to
1886 begin at 0.
1887 """
1888 def accumulate(stats):
1889 pkts_acc = bytes_acc = 0
1890 for stat in stats:
1891 pkts_acc += stat.tx_packets
1892 bytes_acc += stat.tx_bytes
1893 return (pkts_acc, bytes_acc)
1894
1895 pkts_before, bytes_before = accumulate(initial)
1896
1897 # Wait 10s for counters to update
1898 pkt_diff = byte_diff = None
1899 for i in range(0, 100):
1900 stats = get_queue_stats(test, port_no, queue_id)
1901 pkts_after, bytes_after = accumulate(stats)
1902 pkt_diff = pkts_after - pkts_before
1903 byte_diff = bytes_after - bytes_before
1904 if (pkts == None or pkt_diff >= pkts) and \
1905 (bytes == None or byte_diff >= bytes):
1906 break
Dan Talayco53724732013-03-08 23:54:02 -08001907 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001908
1909 if pkts != None:
1910 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1911
1912 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001913 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1914 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001915
Rich Lane4c504f32013-06-07 17:24:14 -07001916def packet_in_match(msg, data, in_port=None, reason=None):
1917 """
1918 Check whether the packet_in message 'msg' has fields matching 'data',
1919 'in_port', and 'reason'.
1920
1921 This function handles truncated packet_in data. The 'in_port' and 'reason'
1922 parameters are optional.
1923
1924 @param msg packet_in message
1925 @param data Expected packet_in data
1926 @param in_port Expected packet_in in_port, or None
1927 @param reason Expected packet_in reason, or None
1928 """
1929
Rich Lanec0d26dd2013-07-10 12:46:03 -07001930 if ofp.OFP_VERSION <= 2:
1931 pkt_in_port = msg.in_port
1932 else:
1933 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1934 if ofp.oxm.in_port in oxms:
1935 pkt_in_port = oxms[ofp.oxm.in_port].value
1936 else:
1937 logging.warn("Missing in_port in packet-in message")
1938 pkt_in_port = None
1939
1940 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001941 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001942 return False
1943
Rich Lanec0d26dd2013-07-10 12:46:03 -07001944 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001945 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1946 return False
1947
1948 # Check that one of the packets is a prefix of the other.
1949 # The received packet may be either truncated or padded, but not both.
1950 # (Some of the padding may be truncated but that's irrelevant). We
1951 # need to check that the smaller packet is a prefix of the larger one.
1952 # Note that this check succeeds if the switch sends a zero-length
1953 # packet-in.
1954 compare_len = min(len(msg.data), len(data))
1955 if data[:compare_len] != msg.data[:compare_len]:
1956 logging.debug("Incorrect packet_in data")
1957 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1958 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1959 return False
1960
1961 return True
1962
1963def verify_packet_in(test, data, in_port, reason, controller=None):
1964 """
1965 Assert that the controller receives a packet_in message matching data 'data'
1966 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1967 itself, that's up to the test case.
1968
1969 @param test Instance of base_tests.SimpleProtocol
1970 @param pkt String to expect as the packet_in data
1971 @param in_port OpenFlow port number to expect as the packet_in in_port
1972 @param reason One of OFPR_* to expect as the packet_in reason
1973 @param controller Controller instance, defaults to test.controller
1974 @returns The received packet-in message
1975 """
1976
1977 if controller == None:
1978 controller = test.controller
1979
1980 end_time = time.time() + oftest.ofutils.default_timeout
1981
1982 while True:
1983 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1984 if not msg:
1985 # Timeout
1986 break
1987 elif packet_in_match(msg, data, in_port, reason):
1988 # Found a matching message
1989 break
1990
Kiran Poola58c5c042014-05-15 15:11:06 -07001991 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001992 return msg
1993
1994def verify_no_packet_in(test, data, in_port, controller=None):
1995 """
1996 Assert that the controller does not receive a packet_in message matching
1997 data 'data' from port 'in_port'.
1998
1999 @param test Instance of base_tests.SimpleProtocol
2000 @param pkt String to expect as the packet_in data
2001 @param in_port OpenFlow port number to expect as the packet_in in_port
2002 @param controller Controller instance, defaults to test.controller
2003 """
2004
2005 if controller == None:
2006 controller = test.controller
2007
2008 # Negative test, need to wait a short amount of time before checking we
2009 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07002010 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07002011
2012 # Check every packet_in queued in the controller
2013 while True:
2014 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
2015 if msg == None:
2016 # No more queued packet_in messages
2017 break
2018 elif packet_in_match(msg, data, in_port, None):
2019 # Found a matching message
2020 break
2021
Rich Lane82c882d2013-08-09 17:13:52 -07002022 if in_port == None:
2023 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
2024 else:
2025 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002026
Rich Lane045db072013-08-06 13:16:30 -07002027def openflow_ports(num=None):
2028 """
2029 Return a list of 'num' OpenFlow port numbers
2030
2031 If 'num' is None, return all available ports. Otherwise, limit the length
2032 of the result to 'num' and raise an exception if not enough ports are
2033 available.
2034 """
2035 ports = sorted(oftest.config["port_map"].keys())
2036 if num != None and len(ports) < num:
2037 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2038 return ports[:num]
2039
Rich Lanee4b384d2013-09-13 14:33:40 -07002040def verify_packet(test, pkt, ofport):
2041 """
2042 Check that an expected packet is received
2043 """
2044 logging.debug("Checking for pkt on port %r", ofport)
2045 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2046 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002047 return (rcv_port, rcv_pkt, pkt_time)
2048
Rich Lanee4b384d2013-09-13 14:33:40 -07002049def verify_no_packet(test, pkt, ofport):
2050 """
2051 Check that a particular packet is not received
2052 """
2053 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002054 (rcv_port, rcv_pkt, pkt_time) = \
2055 test.dataplane.poll(
2056 port_number=ofport, exp_pkt=str(pkt),
2057 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002058 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2059
2060def verify_no_other_packets(test):
2061 """
2062 Check that no unexpected packets are received
2063
2064 This is a no-op if the --relax option is in effect.
2065 """
2066 if oftest.config["relax"]:
2067 return
2068 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002069 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002070 if rcv_pkt != None:
2071 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2072 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2073
2074def verify_packets(test, pkt, ofports):
2075 """
2076 Check that a packet is received on certain ports
2077
2078 Also verifies that the packet is not received on any other ports, and that no
2079 other packets are received (unless --relax is in effect).
2080
2081 This covers the common and simplest cases for checking dataplane outputs.
2082 For more complex usage, like multiple different packets being output, or
2083 multiple packets on the same port, use the primitive verify_packet,
2084 verify_no_packet, and verify_no_other_packets functions directly.
2085 """
2086 pkt = str(pkt)
2087 for ofport in openflow_ports():
2088 if ofport in ofports:
2089 verify_packet(test, pkt, ofport)
2090 else:
2091 verify_no_packet(test, pkt, ofport)
2092 verify_no_other_packets(test)
2093
Rich Lane12d04592013-10-10 17:21:07 -07002094def verify_no_errors(ctrl):
2095 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2096 if error:
2097 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002098
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002099def verify_capability(test, capability):
2100 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002101 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002102
2103 @param test Instance of base_tests.SimpleProtocol
2104 @param capability One of ofp_capabilities.
2105 """
2106 logging.info("Verifing that capability code is valid.")
2107 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2108 "Capability code %d does not exist." % capability)
2109 capability_str = ofp.const.ofp_capabilities_map[capability]
2110
2111 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002112 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002113 req = ofp.message.features_request()
2114 res, raw = test.controller.transact(req)
2115 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2116 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2117 ("Unexpected packet type %d received in response to "
2118 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002119 logging.info("Received features_reply.")
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002120
Jonathan Stout641167f2014-02-04 12:07:10 -05002121 if (res.capabilities & capability) > 0:
2122 logging.info("Switch capabilities bitmask claims to support %s",
2123 capability_str)
2124 return True, res.capabilities
2125 else:
2126 logging.info("Capabilities bitmask does not support %s.",
2127 capability_str)
2128 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002129
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002130def verify_configuration_flag(test, flag):
2131 """
2132 Return True if DUT supports specified configuration flag.
2133
2134 @param test Instance of base_tests.SimpleProtocol
2135 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002136 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002137 """
2138 logging.info("Verifing that flag is valid.")
2139 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2140 "flag %s does not exist." % flag)
2141 flag_str = ofp.const.ofp_config_flags_map[flag]
2142
2143 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
2144 req = ofp.message.get_config_request()
2145 rv = test.controller.message_send(req)
2146 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2147
2148 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2149 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2150 timeout=2)
2151 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2152 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2153
2154 if res.flags == flag:
2155 logging.info("%s flag is set.", flag_str)
2156 return True, res.flags
2157 else:
2158 logging.info("%s flag is not set.", flag_str)
2159 return False, res.flags
2160
Rich Lane7744e112013-01-11 17:23:57 -08002161__all__ = list(set(locals()) - _import_blacklist)