blob: 57fe0b6147098549827c837216cd3e746b175d49 [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'):
Charles Chanc85f1562018-01-18 15:44:29 -0800115
macauley_cheng739f54b2015-11-09 13:52:59 +0800116 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
Charles Chanc85f1562018-01-18 15:44:29 -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,
Andreas Pantelopoulosf83e0212018-03-18 20:44:05 -0700128 outer_vlan=None,
Rich Laned0478ff2013-03-11 12:46:58 -0700129 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700130 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800131 ip_src='192.168.0.1',
132 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700133 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800134 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800135 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700136 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700137 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700138 ip_ihl=None,
139 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800140 ):
141 """
142 Return a simple dataplane TCP packet
143
144 Supports a few parameters:
145 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700146 @param eth_dst Destinatino MAC
147 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700148 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700149 @param vlan_vid VLAN ID
150 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800151 @param ip_src IP source
152 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700153 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800154 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800155 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700156 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800157 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800158
159 Generates a simple TCP request. Users
160 shouldn't assume anything about this packet other than that
161 it is a valid ethernet/IP/TCP frame.
162 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000163
164 if MINSIZE > pktlen:
165 pktlen = MINSIZE
166
Dan Talayco551befa2010-07-15 17:05:32 -0700167 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800168 if (dl_vlan_enable):
Andreas Pantelopoulosf83e0212018-03-18 20:44:05 -0700169 pkt = scapy.Ether( dst=eth_dst, src=eth_src )
170 if outer_vlan:
171 pkt = pkt/scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=outer_vlan)
172
173 pkt = pkt/scapy.Dot1Q( prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid )/ \
174 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
175 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700176 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700177 if not ip_options:
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)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700180 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700181 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700182 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800183 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 -0700184 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700185
Dan Talayco41eae8b2010-03-10 13:57:06 -0800186 pkt = pkt/("D" * (pktlen - len(pkt)))
187
188 return pkt
189
Rich Lane86aceb02013-07-17 18:45:38 -0700190def simple_tcpv6_packet(pktlen=100,
191 eth_dst='00:01:02:03:04:05',
192 eth_src='00:06:07:08:09:0a',
193 dl_vlan_enable=False,
194 vlan_vid=0,
195 vlan_pcp=0,
196 ipv6_src='2001:db8:85a3::8a2e:370:7334',
197 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
198 ipv6_tc=0,
199 ipv6_hlim=64,
200 ipv6_fl=0,
201 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700202 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700203 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700204 """
205 Return a simple IPv6/TCP packet
206
207 Supports a few parameters:
208 @param len Length of packet in bytes w/o CRC
209 @param eth_dst Destination MAC
210 @param eth_src Source MAC
211 @param dl_vlan_enable True if the packet is with vlan, False otherwise
212 @param vlan_vid VLAN ID
213 @param vlan_pcp VLAN priority
214 @param ipv6_src IPv6 source
215 @param ipv6_dst IPv6 destination
216 @param ipv6_tc IPv6 traffic class
217 @param ipv6_ttl IPv6 hop limit
218 @param ipv6_fl IPv6 flow label
219 @param tcp_dport TCP destination port
220 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800221 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700222
223 Generates a simple TCP request. Users shouldn't assume anything about this
224 packet other than that it is a valid ethernet/IPv6/TCP frame.
225 """
226
227 if MINSIZE > pktlen:
228 pktlen = MINSIZE
229
230 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
231 if dl_vlan_enable or vlan_vid or vlan_pcp:
232 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
233 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 -0700234 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700235 pkt /= ("D" * (pktlen - len(pkt)))
236
237 return pkt
238
Rich Lane6ee7bea2012-10-26 16:19:29 -0700239def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700240 eth_dst='00:01:02:03:04:05',
241 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700242 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700243 vlan_vid=0,
244 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700245 dl_vlan_cfi=0,
246 ip_src='192.168.0.1',
247 ip_dst='192.168.0.2',
248 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800249 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700250 udp_sport=1234,
251 udp_dport=80,
252 ip_ihl=None,
253 ip_options=False
254 ):
255 """
256 Return a simple dataplane UDP packet
257
258 Supports a few parameters:
259 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700260 @param eth_dst Destination MAC
261 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700262 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700263 @param vlan_vid VLAN ID
264 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700265 @param ip_src IP source
266 @param ip_dst IP destination
267 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800268 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700269 @param udp_dport UDP destination port
270 @param udp_sport UDP source port
271
272 Generates a simple UDP packet. Users shouldn't assume anything about
273 this packet other than that it is a valid ethernet/IP/UDP frame.
274 """
275
276 if MINSIZE > pktlen:
277 pktlen = MINSIZE
278
279 # Note Dot1Q.id is really CFI
280 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700281 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
282 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800283 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700284 scapy.UDP(sport=udp_sport, dport=udp_dport)
285 else:
286 if not ip_options:
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)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700289 scapy.UDP(sport=udp_sport, dport=udp_dport)
290 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700291 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800292 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 -0700293 scapy.UDP(sport=udp_sport, dport=udp_dport)
294
295 pkt = pkt/("D" * (pktlen - len(pkt)))
296
297 return pkt
298
macauley_chengb0ec33d2015-09-04 11:32:44 +0800299
Charles Chanc85f1562018-01-18 15:44:29 -0800300def simple_tcp_packet_two_vlan(pktlen=100,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800301 eth_dst='00:01:02:03:04:05',
302 eth_src='00:06:07:08:09:0a',
303 out_dl_vlan_enable=False,
304 in_dl_vlan_enable=False,
305 out_vlan_vid=0,
306 out_vlan_pcp=0,
Charles Chanc85f1562018-01-18 15:44:29 -0800307 out_dl_vlan_cfi=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800308 in_vlan_vid=0,
Charles Chanc85f1562018-01-18 15:44:29 -0800309 in_vlan_pcp=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800310 in_dl_vlan_cfi=0,
311 ip_src='192.168.0.1',
312 ip_dst='192.168.0.2',
313 ip_tos=0,
314 ip_ttl=64,
315 tcp_sport=1234,
316 tcp_dport=80,
317 tcp_flags="S",
318 ip_ihl=None,
319 ip_options=False
320 ):
321 """
322 Return a simple dataplane TCP packet
323
324 Supports a few parameters:
325 @param len Length of packet in bytes w/o CRC
326 @param eth_dst Destinatino MAC
327 @param eth_src Source MAC
328 @param dl_vlan_enable True if the packet is with vlan, False otherwise
329 @param vlan_vid VLAN ID
330 @param vlan_pcp VLAN priority
331 @param ip_src IP source
332 @param ip_dst IP destination
333 @param ip_tos IP ToS
334 @param ip_ttl IP TTL
335 @param tcp_dport TCP destination port
336 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800337 @param tcp_flags TCP Control flags
macauley_chengb0ec33d2015-09-04 11:32:44 +0800338
339 Generates a simple TCP request. Users
340 shouldn't assume anything about this packet other than that
341 it is a valid ethernet/IP/TCP frame.
342 """
343
344 if MINSIZE > pktlen:
345 pktlen = MINSIZE
346
347 # Note Dot1Q.id is really CFI
348 if (out_dl_vlan_enable and in_dl_vlan_enable):
349 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
350 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
351
352 if in_dl_vlan_enable:
353 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
354
355 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
356 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
357 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
358 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
359 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
360 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
361 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
362 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
363 assert(0) #shall not have this caes
364 else:
365 if not ip_options:
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)/ \
368 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
369 else:
370 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
371 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
372 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
373
374 pkt = pkt/("D" * (pktlen - len(pkt)))
375
376 return pkt
377
macauley17cd60d2015-07-27 17:41:18 +0800378def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
379 eth_src='00:06:07:08:09:0a',
380 dl_vlan_enable=False,
381 vlan_vid=0,
382 vlan_pcp=0,
383 dl_vlan_cfi=0,
384 ip_src='192.168.0.1',
385 ip_dst='192.168.0.2',
386 ip_tos=0,
387 ip_ttl=64,
388 udp_sport=1234,
389 udp_dport=4789,
390 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800391 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800392 ip_ihl=None,
393 ip_options=False
394 ):
395 """
396 Return a simple dataplane UDP packet
397
398 Supports a few parameters:
399 @param len Length of packet in bytes w/o CRC
400 @param eth_dst Destination MAC
401 @param eth_src Source MAC
402 @param dl_vlan_enable True if the packet is with vlan, False otherwise
403 @param vlan_vid VLAN ID
404 @param vlan_pcp VLAN priority
405 @param ip_src IP source
406 @param ip_dst IP destination
407 @param ip_tos IP ToS
408 @param ip_ttl IP TTL
409 @param udp_dport UDP destination port
410 @param udp_sport UDP source port
411 @param inner_pyload inner pacekt content
412 Generates a simple UDP packet. Users shouldn't assume anything about
413 this packet other than that it is a valid ethernet/IP/UDP frame.
414 """
415
416 # Note Dot1Q.id is really CFI
417 if (dl_vlan_enable):
418 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
419 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
420 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
421 scapy.UDP(sport=udp_sport, dport=udp_dport)
422 else:
423 if not ip_options:
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)/ \
426 scapy.UDP(sport=udp_sport, dport=udp_dport)
427 else:
428 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
429 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
430 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800431
macauley17cd60d2015-07-27 17:41:18 +0800432 #add vxlan header
433 pkt = pkt/scapy.VXLAN(vni=vnid)
434 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800435 if inner_payload!=None:
436 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800437
438 return pkt
439
Charles Chanc85f1562018-01-18 15:44:29 -0800440def mpls_packet(pktlen=100,
Flavio Castro72a45d52015-12-02 16:37:05 -0500441 eth_dst='00:01:02:03:04:05',
442 eth_src='00:06:07:08:09:0a',
443 dl_vlan_enable=False,
444 vlan_vid=0,
445 vlan_pcp=0,
446 dl_vlan_cfi=0,
447 ip_src='192.168.0.1',
448 ip_dst='192.168.0.2',
449 ip_tos=0,
450 ip_ttl=64,
451 tcp_sport=1234,
452 tcp_dport=80,
453 tcp_flags="S",
454 ip_ihl=None,
455 ip_options=False,
456 label=None,
Charles Chanc85f1562018-01-18 15:44:29 -0800457 inner_payload=True,
458 encapsulated_ethernet=False,
459 encapsulated_eth_src='01:02:03:04:05:11',
460 encapsulated_eth_dst='01:02:03:04:05:22'
Flavio Castro72a45d52015-12-02 16:37:05 -0500461 ):
462 if MINSIZE > pktlen:
463 pktlen = MINSIZE
464
465 # Note Dot1Q.id is really CFI
466 if (dl_vlan_enable):
467 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
468 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
469 else:
470 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
471
472 #add MPLS header
473 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800474 l,c,s,t=label[i]
Flavio Castro72a45d52015-12-02 16:37:05 -0500475 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
476
477 #add innder payload
478 if inner_payload!=None:
Charles Chanc85f1562018-01-18 15:44:29 -0800479 if not encapsulated_ethernet:
480 pkt=pkt / \
481 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
482 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
483 else:
484 pkt=pkt / \
485 scapy.Ether(dst=encapsulated_eth_dst, src=encapsulated_eth_src)/ \
486 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
487 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
488
Flavio Castro167f5bd2015-12-02 19:33:53 -0500489 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500490
491 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800492
Pier23784aa2016-09-19 20:08:21 -0700493def pw_packet(pktlen=100,
494 out_eth_dst='00:01:02:03:04:05',
495 out_eth_src='00:06:07:08:09:0a',
496 label=None,
497 cw=None,
498 in_eth_dst='00:01:02:03:04:05',
499 in_eth_src='00:06:07:08:09:0a',
500 out_dl_vlan_enable=False,
501 in_dl_vlan_enable=False,
502 out_vlan_vid=0,
503 out_vlan_pcp=0,
504 out_dl_vlan_cfi=0,
505 in_vlan_vid=0,
506 in_vlan_pcp=0,
507 in_dl_vlan_cfi=0,
508 ip_src='192.168.0.1',
509 ip_dst='192.168.0.2',
510 ip_tos=0,
511 ip_ttl=64,
512 tcp_sport=1234,
513 tcp_dport=80,
514 tcp_flags="S",
515 ip_ihl=None,
516 ip_options=False
517 ):
518 """
519 Return a simple dataplane TCP packet encapsulated
520 in a pw packet
521 """
522
523 # Add the outer ethernet header
524 if MINSIZE > pktlen:
525 pktlen = MINSIZE
526
527 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
528
529 #add MPLS header
530 for i in range(len(label)):
531 l,c,s,t=label[i]
532 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
533
534 #add the PW CW
535 l,c,s,t=cw
536 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
537
538 # Note Dot1Q.id is really CFI
539 if (out_dl_vlan_enable and in_dl_vlan_enable):
540
541 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
542 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
543
544 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
545
546 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
547 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
548
549 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
550
551 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
552 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
553 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
554 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
555
556 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
557
558 assert(0) #shall not have this caes
559
560 else:
561 if not ip_options:
562 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
563 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
564 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
565 else:
566 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
567 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
568 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
569
570 pkt = pkt/("D" * (pktlen - len(pkt)))
571
572 return pkt
573
Pier1e4e98e2016-10-26 14:36:05 -0700574def mplsv6_packet(pktlen=100,
575 eth_dst='00:01:02:03:04:05',
576 eth_src='00:06:07:08:09:0a',
577 dl_vlan_enable=False,
578 vlan_vid=0,
579 vlan_pcp=0,
580 dl_vlan_cfi=0,
581 ipv6_src='2001:db8:85a3::8a2e:370:7334',
582 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
583 ipv6_tc=0,
584 ipv6_hlim=64,
585 ipv6_fl=0,
586 tcp_sport=1234,
587 tcp_dport=80,
588 tcp_flags="S",
589 label=None,
590 inner_payload=True
591 ):
592 if MINSIZE > pktlen:
593 pktlen = MINSIZE
594
595 # Note Dot1Q.id is really CFI
596 if (dl_vlan_enable):
597 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
598 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
599 else:
600 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
601
602 #add MPLS header
603 for i in range(len(label)):
604 l,c,s,t=label[i]
605 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
606
607 #add innder payload
608 if inner_payload!=None:
609 pkt=pkt / \
610 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
611 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
612
613 pkt = pkt/("D" * (pktlen - len(pkt)))
614
615 return pkt
616
macauley_cheng45833df2015-08-31 15:19:07 +0800617def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
618 eth_src='00:06:07:08:09:0a',
619 dl_vlan_enable=False,
620 vlan_vid=0,
621 vlan_pcp=0,
622 dl_vlan_cfi=0,
623 label=None,
624 inner_payload=None
625 ):
626 """
627 Return a simple dataplane MPLS packet
628
629 Supports a few parameters:
630 @param len Length of packet in bytes w/o CRC
631 @param eth_dst Destination MAC
632 @param eth_src Source MAC
633 @param dl_vlan_enable True if the packet is with vlan, False otherwise
634 @param vlan_vid VLAN ID
635 @param vlan_pcp VLAN priority
636 @param inner_pyload inner pacekt content
637 Generates a simple MPLS packet. Users shouldn't assume anything about
638 this packet other than that it is a valid ethernet/IP/UDP frame.
639 """
640
641 # Note Dot1Q.id is really CFI
642 if (dl_vlan_enable):
643 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
644 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
645 else:
646 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
647
648 #add MPLS header
649 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800650 l,c,s,t=label[i]
macauley_cheng45833df2015-08-31 15:19:07 +0800651 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
652
653 #add innder payload
654 if inner_payload!=None:
655 pkt=pkt/inner_payload
656
657 return pkt
Charles Chanc85f1562018-01-18 15:44:29 -0800658
Rich Lane86aceb02013-07-17 18:45:38 -0700659def simple_udpv6_packet(pktlen=100,
660 eth_dst='00:01:02:03:04:05',
661 eth_src='00:06:07:08:09:0a',
662 dl_vlan_enable=False,
663 vlan_vid=0,
664 vlan_pcp=0,
665 ipv6_src='2001:db8:85a3::8a2e:370:7334',
666 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
667 ipv6_tc=0,
668 ipv6_hlim=64,
669 ipv6_fl=0,
670 udp_sport=1234,
671 udp_dport=80):
672 """
673 Return a simple IPv6/UDP packet
674
675 Supports a few parameters:
676 @param len Length of packet in bytes w/o CRC
677 @param eth_dst Destination MAC
678 @param eth_src Source MAC
679 @param dl_vlan_enable True if the packet is with vlan, False otherwise
680 @param vlan_vid VLAN ID
681 @param vlan_pcp VLAN priority
682 @param ipv6_src IPv6 source
683 @param ipv6_dst IPv6 destination
684 @param ipv6_tc IPv6 traffic class
685 @param ipv6_ttl IPv6 hop limit
686 @param ipv6_fl IPv6 flow label
687 @param udp_dport UDP destination port
688 @param udp_sport UDP source port
689
690 Generates a simple UDP request. Users shouldn't assume anything about this
691 packet other than that it is a valid ethernet/IPv6/UDP frame.
692 """
693
694 if MINSIZE > pktlen:
695 pktlen = MINSIZE
696
697 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
698 if dl_vlan_enable or vlan_vid or vlan_pcp:
699 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
700 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
701 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
702 pkt /= ("D" * (pktlen - len(pkt)))
703
704 return pkt
705
Charles Chanc85f1562018-01-18 15:44:29 -0800706def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700707 eth_dst='00:01:02:03:04:05',
708 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700709 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700710 vlan_vid=0,
711 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700712 ip_src='192.168.0.1',
713 ip_dst='192.168.0.2',
714 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800715 ip_ttl=64,
Charles Chanc85f1562018-01-18 15:44:29 -0800716 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700717 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600718 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600719 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700720 """
721 Return a simple ICMP packet
722
723 Supports a few parameters:
724 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700725 @param eth_dst Destinatino MAC
726 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700727 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700728 @param vlan_vid VLAN ID
729 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700730 @param ip_src IP source
731 @param ip_dst IP destination
732 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800733 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600734 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700735 @param icmp_type ICMP type
736 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600737 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700738
739 Generates a simple ICMP ECHO REQUEST. Users
740 shouldn't assume anything about this packet other than that
741 it is a valid ethernet/ICMP frame.
742 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000743
744 if MINSIZE > pktlen:
745 pktlen = MINSIZE
746
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700747 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700748 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
749 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600750 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600751 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700752 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700753 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600754 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600755 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700756
757 pkt = pkt/("0" * (pktlen - len(pkt)))
758
759 return pkt
760
Rich Lane86aceb02013-07-17 18:45:38 -0700761def simple_icmpv6_packet(pktlen=100,
762 eth_dst='00:01:02:03:04:05',
763 eth_src='00:06:07:08:09:0a',
764 dl_vlan_enable=False,
765 vlan_vid=0,
766 vlan_pcp=0,
767 ipv6_src='2001:db8:85a3::8a2e:370:7334',
768 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
769 ipv6_tc=0,
770 ipv6_hlim=64,
771 ipv6_fl=0,
772 icmp_type=8,
773 icmp_code=0):
774 """
775 Return a simple ICMPv6 packet
776
777 Supports a few parameters:
778 @param len Length of packet in bytes w/o CRC
779 @param eth_dst Destination MAC
780 @param eth_src Source MAC
781 @param dl_vlan_enable True if the packet is with vlan, False otherwise
782 @param vlan_vid VLAN ID
783 @param vlan_pcp VLAN priority
784 @param ipv6_src IPv6 source
785 @param ipv6_dst IPv6 destination
786 @param ipv6_tc IPv6 traffic class
787 @param ipv6_ttl IPv6 hop limit
788 @param ipv6_fl IPv6 flow label
789 @param icmp_type ICMP type
790 @param icmp_code ICMP code
791
792 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
793 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
794 """
795
796 if MINSIZE > pktlen:
797 pktlen = MINSIZE
798
799 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
800 if dl_vlan_enable or vlan_vid or vlan_pcp:
801 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
802 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
803 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
804 pkt /= ("D" * (pktlen - len(pkt)))
805
806 return pkt
807
Charles Chanc85f1562018-01-18 15:44:29 -0800808def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700809 eth_dst='ff:ff:ff:ff:ff:ff',
810 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800811 vlan_vid=0,
812 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800813 arp_op=1,
814 ip_snd='192.168.0.1',
815 ip_tgt='192.168.0.2',
816 hw_snd='00:06:07:08:09:0a',
817 hw_tgt='00:00:00:00:00:00',
818 ):
819 """
820 Return a simple ARP packet
821
822 Supports a few parameters:
823 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700824 @param eth_dst Destinatino MAC
825 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800826 @param arp_op Operation (1=request, 2=reply)
827 @param ip_snd Sender IP
828 @param ip_tgt Target IP
829 @param hw_snd Sender hardware address
830 @param hw_tgt Target hardware address
831
832 Generates a simple ARP REQUEST. Users
833 shouldn't assume anything about this packet other than that
834 it is a valid ethernet/ARP frame.
835 """
836
837 if MINSIZE > pktlen:
838 pktlen = MINSIZE
839
Rich Lanee01611f2014-01-15 14:55:11 -0800840 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
841 if vlan_vid or vlan_pcp:
842 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
843 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 -0800844
Rich Laned459ce52014-01-24 12:09:54 -0800845 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800846
847 return pkt
848
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700849def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800850 eth_dst='00:01:02:03:04:05',
851 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700852 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000853
854 if MINSIZE > pktlen:
855 pktlen = MINSIZE
856
Rich Laned0478ff2013-03-11 12:46:58 -0700857 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700858
859 pkt = pkt/("0" * (pktlen - len(pkt)))
860
861 return pkt
862
Charles Chanc85f1562018-01-18 15:44:29 -0800863def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700864 eth_dst='00:01:02:03:04:05',
865 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800866 dl_vlan_outer=20,
867 dl_vlan_pcp_outer=0,
868 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700869 vlan_vid=10,
870 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800871 dl_vlan_cfi=0,
872 ip_src='192.168.0.1',
873 ip_dst='192.168.0.2',
874 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800875 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800876 tcp_sport=1234,
877 tcp_dport=80,
878 ip_ihl=None,
879 ip_options=False
880 ):
881 """
882 Return a doubly tagged dataplane TCP packet
883
884 Supports a few parameters:
885 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700886 @param eth_dst Destinatino MAC
887 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800888 @param dl_vlan_outer Outer VLAN ID
889 @param dl_vlan_pcp_outer Outer VLAN priority
890 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700891 @param vlan_vid Inner VLAN ID
892 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800893 @param dl_vlan_cfi VLAN cfi bit
894 @param ip_src IP source
895 @param ip_dst IP destination
896 @param ip_tos IP ToS
897 @param tcp_dport TCP destination port
898 @param ip_sport TCP source port
899
900 Generates a TCP request. Users
901 shouldn't assume anything about this packet other than that
902 it is a valid ethernet/IP/TCP frame.
903 """
904
905 if MINSIZE > pktlen:
906 pktlen = MINSIZE
907
908 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700909 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800910 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700911 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800912 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800913 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
914
915 pkt = pkt/("D" * (pktlen - len(pkt)))
916
917 return pkt
918
Shudong Zhoub7f12462012-11-20 13:01:12 -0800919def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700920 """
921 Do a barrier command
922 Return 0 on success, -1 on error
923 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700924 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800925 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800926 if resp is None:
927 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700928 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800929 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700930
Rich Lane9a003812012-10-04 17:17:59 -0700931def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700932 """
933 Get a port's configuration
934
935 Gets the switch feature configuration and grabs one port's
936 configuration
937
938 @returns (hwaddr, config, advert) The hwaddress, configuration and
939 advertised values
940 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700941
942 if ofp.OFP_VERSION <= 3:
943 request = ofp.message.features_request()
944 reply, _ = controller.transact(request)
945 if reply is None:
946 logging.warn("Get feature request failed")
947 return None, None, None
948 logging.debug(reply.show())
949 ports = reply.ports
950 else:
951 request = ofp.message.port_desc_stats_request()
952 # TODO do multipart correctly
953 reply, _ = controller.transact(request)
954 if reply is None:
955 logging.warn("Port desc stats request failed")
956 return None, None, None
957 logging.debug(reply.show())
958 ports = reply.entries
959
960 for port in ports:
961 if port.port_no == port_no:
962 return (port.hw_addr, port.config, port.advertised)
Charles Chanc85f1562018-01-18 15:44:29 -0800963
Rich Lane9a003812012-10-04 17:17:59 -0700964 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700965 return None, None, None
966
Rich Lane9a003812012-10-04 17:17:59 -0700967def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700968 """
969 Set the port configuration according the given parameters
970
971 Gets the switch feature configuration and updates one port's
972 configuration value according to config and mask
973 """
Rich Lane9a003812012-10-04 17:17:59 -0700974 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700975
976 hw_addr, _, _ = port_config_get(controller, port_no)
977
Rich Lanee717c6e2013-03-12 10:25:50 -0700978 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700979 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700980 if hw_addr != None:
981 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700982 mod.config = config
983 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700984 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800985 controller.message_send(mod)
986 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700987
Rich Lane2014f9b2012-10-05 15:29:40 -0700988def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700989 """
990 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700991 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700992 @param pkt Expected packet; may be None if yes_ports is empty
993 @param yes_ports Set or list of ports that should recieve packet
994 @param no_ports Set or list of ports that should not receive packet
995 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700996
997 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700998 """
Rich Lane91765672012-12-06 16:33:04 -0800999
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001000 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001001 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001002 exp_pkt_arg = pkt
1003
Dan Talayco92c99122010-06-03 13:53:18 -07001004 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001005 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001006 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -08001007 port_number=ofport, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001008 assert_if.assertTrue(rcv_pkt is not None,
Dan Talayco92c99122010-06-03 13:53:18 -07001009 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001010 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -08001011 logging.debug("Expected %s" % format_packet(pkt))
1012 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001013 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -08001014 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -07001015 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -07001016 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -07001017 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -07001018 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001019 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001020 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -08001021 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001022 assert_if.assertTrue(rcv_pkt is None,
Dan Talayco92c99122010-06-03 13:53:18 -07001023 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -07001024
1025
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001026def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -07001027 """
1028 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -07001029 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001030
1031 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -07001032
1033 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -07001034 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001035 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001036 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001037 exp_pkt_arg = exp_pkt
1038
Dan Talaycof6e76c02012-03-23 10:56:12 -07001039 if type(egr_ports) == type([]):
1040 egr_port_list = egr_ports
1041 else:
1042 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001043
Dan Talaycof6e76c02012-03-23 10:56:12 -07001044 # Expect a packet from each port on egr port list
1045 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001046 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001047 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001048 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001049 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001050 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001051
Dan Talaycof6e76c02012-03-23 10:56:12 -07001052 if rcv_pkt is None:
Charles Chanc85f1562018-01-18 15:44:29 -08001053 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001054 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001055
Dan Talaycof6e76c02012-03-23 10:56:12 -07001056 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001057 "Did not receive packet port " + str(check_port))
Charles Chanc85f1562018-01-18 15:44:29 -08001058 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001059 str(rcv_port))
1060
1061 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001062 logging.error("ERROR: Packet match failed.")
1063 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001064 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001065 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001066 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001067 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1068 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001069 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001070 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001071
Dan Talayco551befa2010-07-15 17:05:32 -07001072def match_verify(parent, req_match, res_match):
1073 """
1074 Verify flow matches agree; if they disagree, report where
1075
1076 parent must implement assertEqual
1077 Use str() to ensure content is compared and not pointers
1078 """
1079
1080 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1081 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1082 " != " + hex(res_match.wildcards))
1083 parent.assertEqual(req_match.in_port, res_match.in_port,
1084 'Match failed: in_port: ' + str(req_match.in_port) +
1085 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001086 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1087 'Match failed: eth_src: ' + str(req_match.eth_src) +
1088 " != " + str(res_match.eth_src))
1089 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1090 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1091 " != " + str(res_match.eth_dst))
1092 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1093 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1094 " != " + str(res_match.vlan_vid))
1095 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
Charles Chanc85f1562018-01-18 15:44:29 -08001096 'Match failed: vlan_pcp: ' +
1097 str(req_match.vlan_pcp) + " != " +
Rich Laned0478ff2013-03-11 12:46:58 -07001098 str(res_match.vlan_pcp))
1099 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1100 'Match failed: eth_type: ' + str(req_match.eth_type) +
1101 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001102
Rich Lanee717c6e2013-03-12 10:25:50 -07001103 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001104 and (req_match.eth_type == IP_ETHERTYPE)):
1105 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1106 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1107 " != " + str(res_match.ip_dscp))
1108 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1109 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1110 " != " + str(res_match.ip_proto))
1111 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1112 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1113 " != " + str(res_match.ipv4_src))
1114 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1115 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1116 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001117
Rich Lanee717c6e2013-03-12 10:25:50 -07001118 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001119 and ((req_match.ip_proto == TCP_PROTOCOL)
1120 or (req_match.ip_proto == UDP_PROTOCOL))):
1121 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
Charles Chanc85f1562018-01-18 15:44:29 -08001122 'Match failed: tcp_src: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001123 str(req_match.tcp_src) +
1124 " != " + str(res_match.tcp_src))
1125 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
Charles Chanc85f1562018-01-18 15:44:29 -08001126 'Match failed: tcp_dst: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001127 str(req_match.tcp_dst) +
1128 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001129
Ed Swierk99a74de2012-08-22 06:40:54 -07001130def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001131 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001132 if ofp.OFP_VERSION in [1, 2]:
1133 match.wildcards |= required_wildcards(parent)
1134 else:
1135 # TODO remove incompatible OXM entries
1136 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001137 return match
1138
1139def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001140 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001141 """
1142 Create a flow message
1143
Charles Chanc85f1562018-01-18 15:44:29 -08001144 Match on packet with given wildcards.
Dan Talayco551befa2010-07-15 17:05:32 -07001145 See flow_match_test for other parameter descriptoins
1146 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001147 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001148 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001149 """
Rich Lanef6883512013-03-11 17:00:09 -07001150 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001151 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001152 if wildcards is None:
1153 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001154 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001155 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001156 match.wildcards = wildcards
1157 match.in_port = ing_port
1158
Dan Talaycof6e76c02012-03-23 10:56:12 -07001159 if type(egr_ports) == type([]):
1160 egr_port_list = egr_ports
1161 else:
1162 egr_port_list = [egr_ports]
1163
Rich Lanee717c6e2013-03-12 10:25:50 -07001164 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001165 request.match = match
1166 request.buffer_id = 0xffffffff
1167 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001168 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001169 request.hard_timeout = 1
1170
Rich Lane400fb9b2013-10-10 17:20:54 -07001171 if ofp.OFP_VERSION == 1:
1172 actions = request.actions
1173 else:
1174 actions = []
1175 request.instructions.append(ofp.instruction.apply_actions(actions))
1176
Dan Talayco551befa2010-07-15 17:05:32 -07001177 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001178 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001179
1180 # Set up output/enqueue action if directed
1181 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001182 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001183 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001184 for egr_port in egr_port_list:
1185 act.port = egr_port
1186 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001187 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001188 elif egr_ports is not None:
1189 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001190 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001191 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001192 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001193
Rich Lane9a003812012-10-04 17:17:59 -07001194 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001195
1196 return request
1197
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001198def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001199 """
1200 Install a flow mod message in the switch
1201
1202 @param parent Must implement controller, assertEqual, assertTrue
1203 @param request The request, all set to go
1204 @param clear_table If true, clear the flow table before installing
1205 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001206
Rich Lane2014f9b2012-10-05 15:29:40 -07001207 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001208 if(clear_table_override != None):
1209 clear_table = clear_table_override
1210
Charles Chanc85f1562018-01-18 15:44:29 -08001211 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001212 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001213 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001214
Rich Lane9a003812012-10-04 17:17:59 -07001215 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001216 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001217
Rich Lane3a261d52013-01-03 17:45:08 -08001218 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001219
Ed Swierk99a74de2012-08-22 06:40:54 -07001220def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001221 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001222 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001223 """
1224 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001225 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001226
1227 Run test with packet through switch from ing_port to egr_port
1228 See flow_match_test for parameter descriptions
1229 """
1230
Ed Swierk99a74de2012-08-22 06:40:54 -07001231 if wildcards is None:
1232 wildcards = required_wildcards(parent)
Charles Chanc85f1562018-01-18 15:44:29 -08001233 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001234 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001235 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001236 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001237 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001238 if exp_pkt is None:
1239 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001240
Charles Chanc85f1562018-01-18 15:44:29 -08001241 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001242 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001243 action_list=action_list)
1244
1245 flow_msg_install(parent, request)
1246
Charles Chanc85f1562018-01-18 15:44:29 -08001247 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001248 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001249 parent.dataplane.send(ing_port, str(pkt))
1250
Rich Lane8f45e2d2013-10-01 16:06:54 -07001251 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001252 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001253
Rich Lane89725bb2012-12-03 16:23:27 -08001254def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001255 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001256 action_list=None):
1257 """
1258 Packet-out test on single TCP packet
1259 @param egr_ports A single port or list of ports
1260
1261 Run test sending packet-out to egr_ports. The goal is to test the actions
1262 taken on the packet, not the matching which is of course irrelevant.
1263 See flow_match_test for parameter descriptions
1264 """
1265
1266 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001267 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001268 if exp_pkt is None:
1269 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001270
Rich Lanee717c6e2013-03-12 10:25:50 -07001271 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001272 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001273 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001274 msg.data = str(pkt)
1275 if action_list is not None:
1276 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001277 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001278
1279 # Set up output action
1280 if egr_ports is not None:
1281 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001282 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001283 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001284 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001285
1286 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001287 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001288
Rich Lane8f45e2d2013-10-01 16:06:54 -07001289 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001290 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001291
Dan Talaycof6e76c02012-03-23 10:56:12 -07001292def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1293 """
1294 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001295 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001296 @param of_ports List of OF port numbers
1297 @param how_many Number of ports to be added to the list
1298 @param exclude_list List of ports not to be used
1299 @returns An empty list if unable to find enough ports
1300 """
1301
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001302 if how_many == 0:
1303 return []
1304
Dan Talaycof6e76c02012-03-23 10:56:12 -07001305 count = 0
1306 egr_ports = []
Charles Chanc85f1562018-01-18 15:44:29 -08001307 for egr_idx in range(len(of_ports)):
Dan Talaycof6e76c02012-03-23 10:56:12 -07001308 if of_ports[egr_idx] not in exclude_list:
1309 egr_ports.append(of_ports[egr_idx])
1310 count += 1
1311 if count >= how_many:
1312 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001313 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001314 return []
Charles Chanc85f1562018-01-18 15:44:29 -08001315
1316def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001317 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001318 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001319 """
Rich Lane89725bb2012-12-03 16:23:27 -08001320 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001321
1322 @param max_test If > 0 no more than this number of tests are executed.
1323 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001324 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001325 @param pkt If not None, use this packet for ingress
1326 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001327 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001328 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1329 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001330 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001331 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001332 if wildcards is None:
1333 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001334 of_ports = port_map.keys()
1335 of_ports.sort()
1336 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1337 test_count = 0
1338
Dan Talaycocfa172f2012-03-23 12:03:00 -07001339 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001340 egr_count = test_param_get('egr_count', default=2)
Charles Chanc85f1562018-01-18 15:44:29 -08001341
Dan Talayco551befa2010-07-15 17:05:32 -07001342 for ing_idx in range(len(of_ports)):
1343 ingress_port = of_ports[ing_idx]
Charles Chanc85f1562018-01-18 15:44:29 -08001344 egr_ports = get_egr_list(parent, of_ports, egr_count,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001345 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001346 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001347 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001348 if len(egr_ports) == 0:
1349 parent.assertTrue(0, "Failed to generate egress port list")
1350
Charles Chanc85f1562018-01-18 15:44:29 -08001351 flow_match_test_port_pair(parent, ingress_port, egr_ports,
1352 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001353 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001354 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001355 test_count += 1
1356 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001357 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001358 break
1359
Ed Swierk38eea082013-01-02 19:46:20 -08001360 if not test_param_get('pktout_actions', default=True):
1361 return
Rich Lane89725bb2012-12-03 16:23:27 -08001362
1363 ingress_port = of_ports[0]
1364 egr_ports = get_egr_list(parent, of_ports, egr_count,
1365 exclude_list=[ingress_port])
1366 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001367 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001368 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001369 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001370 pkt=pkt, exp_pkt=exp_pkt,
1371 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001372
Rich Lane2014f9b2012-10-05 15:29:40 -07001373def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001374 """
1375 Return value passed via test-params if present
1376
Dan Talayco4b2bee62010-07-20 14:10:05 -07001377 @param key The lookup key
1378 @param default Default value to use if not found
1379
1380 If the pair 'key=val' appeared in the string passed to --test-params
1381 on the command line, return val (as interpreted by exec). Otherwise
1382 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001383
Charles Chanc85f1562018-01-18 15:44:29 -08001384 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
Dan Talaycof6e76c02012-03-23 10:56:12 -07001385 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001386 """
1387 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001388 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001389 except:
1390 return default
1391
Dan Talayco4b2bee62010-07-20 14:10:05 -07001392 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001393 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001394 except:
1395 return default
1396
1397def action_generate(parent, field_to_mod, mod_field_vals):
1398 """
1399 Create an action to modify the field indicated in field_to_mod
1400
1401 @param parent Must implement, assertTrue
1402 @param field_to_mod The field to modify as a string name
1403 @param mod_field_vals Hash of values to use for modified values
1404 """
1405
1406 act = None
1407
1408 if field_to_mod in ['pktlen']:
1409 return None
1410
Rich Laned0478ff2013-03-11 12:46:58 -07001411 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001412 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001413 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001414 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001415 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001416 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001417 elif field_to_mod == 'dl_vlan_enable':
1418 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001419 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001420 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001421 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001422 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001423 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001424 act.vlan_vid = mod_field_vals['vlan_vid']
1425 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001426 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001427 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001428 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001429 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001430 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001432 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001433 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001434 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001435 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001436 act.nw_tos = mod_field_vals['ip_tos']
1437 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001438 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001439 act.tp_port = mod_field_vals['tcp_sport']
1440 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001441 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001442 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001443 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001444 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001445 act.tp_port = mod_field_vals['udp_sport']
1446 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001447 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001448 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001449 else:
1450 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1451
1452 return act
1453
Charles Chanc85f1562018-01-18 15:44:29 -08001454def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001455 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001456 """
1457 Set up the ingress and expected packet and action list for a test
1458
Rich Lane2014f9b2012-10-05 15:29:40 -07001459 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001460 @param start_field_values Field values to use for ingress packet (optional)
1461 @param mod_field_values Field values to use for modified packet (optional)
1462 @param mod_fields The list of fields to be modified by the switch in the test.
1463 @params check_test_params If True, will check the parameters vid, add_vlan
1464 and strip_vlan from the command line.
1465
1466 Returns a triple: pkt-to-send, expected-pkt, action-list
1467 """
1468
1469 new_actions = []
1470
Dan Talayco4b2bee62010-07-20 14:10:05 -07001471 base_pkt_params = {}
1472 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001473 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1474 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001476 base_pkt_params['vlan_vid'] = 2
1477 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001478 base_pkt_params['ip_src'] = '192.168.0.1'
1479 base_pkt_params['ip_dst'] = '192.168.0.2'
1480 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001481 if tp == "tcp":
1482 base_pkt_params['tcp_sport'] = 1234
1483 base_pkt_params['tcp_dport'] = 80
1484 elif tp == "udp":
1485 base_pkt_params['udp_sport'] = 1234
1486 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001487 for keyname in start_field_vals.keys():
1488 base_pkt_params[keyname] = start_field_vals[keyname]
1489
1490 mod_pkt_params = {}
1491 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001492 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1493 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001494 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001495 mod_pkt_params['vlan_vid'] = 3
1496 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001497 mod_pkt_params['ip_src'] = '10.20.30.40'
1498 mod_pkt_params['ip_dst'] = '50.60.70.80'
1499 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001500 if tp == "tcp":
1501 mod_pkt_params['tcp_sport'] = 4321
1502 mod_pkt_params['tcp_dport'] = 8765
1503 elif tp == "udp":
1504 mod_pkt_params['udp_sport'] = 4321
1505 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001506 for keyname in mod_field_vals.keys():
1507 mod_pkt_params[keyname] = mod_field_vals[keyname]
1508
1509 # Check for test param modifications
1510 strip = False
1511 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001512 add_vlan = test_param_get('add_vlan')
1513 strip_vlan = test_param_get('strip_vlan')
1514 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001515
1516 if add_vlan and strip_vlan:
1517 parent.assertTrue(0, "Add and strip VLAN both specified")
1518
1519 if vid:
1520 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001521 base_pkt_params['vlan_vid'] = vid
1522 if 'vlan_vid' in mod_fields:
1523 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001524
1525 if add_vlan:
1526 base_pkt_params['dl_vlan_enable'] = False
1527 mod_pkt_params['dl_vlan_enable'] = True
1528 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1529 mod_fields.append('pktlen')
1530 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001531 if 'vlan_vid' not in mod_fields:
1532 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001533 elif strip_vlan:
1534 base_pkt_params['dl_vlan_enable'] = True
1535 mod_pkt_params['dl_vlan_enable'] = False
1536 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1537 mod_fields.append('dl_vlan_enable')
1538 mod_fields.append('pktlen')
1539
Rich Lane110e0e32012-10-26 16:21:46 -07001540 if tp == "tcp":
1541 packet_builder = simple_tcp_packet
1542 elif tp == "udp":
1543 packet_builder = simple_udp_packet
1544 else:
1545 raise NotImplementedError("unknown transport protocol %s" % tp)
1546
Dan Talayco4b2bee62010-07-20 14:10:05 -07001547 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001548 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001549
1550 # Build the expected packet, modifying the indicated fields
1551 for item in mod_fields:
1552 base_pkt_params[item] = mod_pkt_params[item]
1553 act = action_generate(parent, item, mod_pkt_params)
1554 if act:
1555 new_actions.append(act)
1556
Rich Lane110e0e32012-10-26 16:21:46 -07001557 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001558
1559 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001560
1561# Generate a simple "drop" flow mod
1562# If in_band is true, then only drop from first test port
1563def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001564 request = ofp.message.flow_add()
1565 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001566 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001567 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001568 for of_port, ifname in port_map.items(): # Grab first port
1569 break
1570 request.match.in_port = of_port
1571 request.buffer_id = 0xffffffff
1572 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001573
1574def skip_message_emit(parent, s):
1575 """
1576 Print out a 'skipped' message to stderr
1577
1578 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001579 """
1580 global skipped_test_count
1581
1582 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001583 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001584 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001585 sys.stderr.write("(skipped) ")
1586 else:
1587 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001588
Dan Talayco8a64e332012-03-28 14:53:20 -07001589
1590def all_stats_get(parent):
1591 """
1592 Get the aggregate stats for all flows in the table
1593 @param parent Test instance with controller connection and assert
Charles Chanc85f1562018-01-18 15:44:29 -08001594 @returns dict with keys flows, packets, bytes, active (flows),
Dan Talayco8a64e332012-03-28 14:53:20 -07001595 lookups, matched
1596 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001597 stat_req = ofp.message.aggregate_stats_request()
1598 stat_req.match = ofp.match()
1599 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001600 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001601 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001602
1603 rv = {}
1604
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001605 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001606 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001607
Rich Lane5fd6faf2013-03-11 13:30:20 -07001608 for obj in reply.entries:
Charles Chanc85f1562018-01-18 15:44:29 -08001609 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
Dan Talayco8a64e332012-03-28 14:53:20 -07001610 obj.packet_count, obj.byte_count)
1611 break
1612
Rich Lanee717c6e2013-03-12 10:25:50 -07001613 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001614 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001615
Charles Chanc85f1562018-01-18 15:44:29 -08001616
Dan Talayco8a64e332012-03-28 14:53:20 -07001617 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001618 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001619 rv["active"] += obj.active_count
1620 rv["lookups"] += obj.lookup_count
1621 rv["matched"] += obj.matched_count
1622
1623 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001624
Rich Lane7744e112013-01-11 17:23:57 -08001625_import_blacklist.add('FILTER')
Charles Chanc85f1562018-01-18 15:44:29 -08001626FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
Dan Talayco2baf8b52012-03-30 09:55:42 -07001627 for x in range(256)])
1628
1629def hex_dump_buffer(src, length=16):
1630 """
1631 Convert src to a hex dump string and return the string
1632 @param src The source buffer
1633 @param length The number of bytes shown in each line
1634 @returns A string showing the hex dump
1635 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001636 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001637 for i in xrange(0, len(src), length):
1638 chars = src[i:i+length]
1639 hex = ' '.join(["%02x" % ord(x) for x in chars])
1640 printable = ''.join(["%s" % ((ord(x) <= 127 and
1641 FILTER[ord(x)]) or '.') for x in chars])
1642 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1643 return ''.join(result)
1644
1645def format_packet(pkt):
Charles Chanc85f1562018-01-18 15:44:29 -08001646 return "Packet length %d \n%s" % (len(str(pkt)),
Dan Talayco2baf8b52012-03-30 09:55:42 -07001647 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001648
1649def inspect_packet(pkt):
1650 """
1651 Wrapper around scapy's show() method.
1652 @returns A string showing the dissected packet.
1653 """
1654 from cStringIO import StringIO
1655 out = None
1656 backup = sys.stdout
1657 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001658 tmp = StringIO()
1659 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001660 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001661 out = tmp.getvalue()
1662 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001663 finally:
1664 sys.stdout = backup
1665 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001666
1667def nonstandard(cls):
1668 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001669 Testcase decorator that marks the test as being non-standard.
1670 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001671 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001672 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001673 return cls
1674
1675def disabled(cls):
1676 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001677 Testcase decorator that marks the test as being disabled.
1678 These tests are not automatically added to the "standard" group or
1679 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001680 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001681 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001682 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001683
1684def group(name):
1685 """
1686 Testcase decorator that adds the test to a group.
1687 """
1688 def fn(cls):
1689 if not hasattr(cls, "_groups"):
1690 cls._groups = []
1691 cls._groups.append(name)
1692 return cls
1693 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001694
1695def version(ver):
1696 """
1697 Testcase decorator that specifies which versions of OpenFlow the test
1698 supports. The default is 1.0+. This decorator may only be used once.
1699
1700 Supported syntax:
1701 1.0 -> 1.0
1702 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1703 1.0+ -> 1.0, 1.1, 1.2, 1.3
1704 """
1705 versions = parse_version(ver)
1706 def fn(cls):
1707 cls._versions = versions
1708 return cls
1709 return fn
1710
1711def parse_version(ver):
1712 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1713 if re.match("^1\.\d+$", ver):
1714 versions = set([ver])
1715 elif re.match("^(1\.\d+)\+$", ver):
1716 if not ver[:-1] in allowed_versions:
1717 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1718 versions = set()
1719 if ver != "1.1+": versions.add("1.0")
1720 if ver != "1.2+": versions.add("1.1")
1721 if ver != "1.3+": versions.add("1.2")
1722 versions.add("1.3")
1723 else:
1724 versions = set(ver.split(','))
1725
1726 for version in versions:
1727 if not version in allowed_versions:
1728 raise ValueError("invalid OpenFlow version %s" % version)
1729
1730 return versions
1731
1732assert(parse_version("1.0") == set(["1.0"]))
1733assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1734assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001735
Rich Laneae3428c2013-03-07 14:37:42 -08001736def get_stats(test, req):
1737 """
1738 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1739 """
Rich Lane609194f2013-10-21 06:17:37 -07001740 msgtype = ofp.OFPT_STATS_REPLY
1741 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001742 stats = []
1743 reply, _ = test.controller.transact(req)
1744 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001745 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001746 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001747 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001748 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001749 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001750 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001751 return stats
1752
Rich Lanebd56ed62013-07-10 15:49:44 -07001753def get_flow_stats(test, match, table_id=None,
1754 out_port=None, out_group=None,
1755 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001756 """
1757 Retrieve a list of flow stats entries.
1758 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001759
1760 if table_id == None:
1761 if ofp.OFP_VERSION <= 2:
1762 table_id = 0xff
1763 else:
1764 table_id = ofp.OFPTT_ALL
1765
Rich Lanef3bc48c2013-05-03 17:39:35 -07001766 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001767 if ofp.OFP_VERSION == 1:
1768 out_port = ofp.OFPP_NONE
1769 else:
1770 out_port = ofp.OFPP_ANY
1771
1772 if out_group == None:
1773 if ofp.OFP_VERSION > 1:
1774 out_group = ofp.OFPP_ANY
1775
Rich Lanee717c6e2013-03-12 10:25:50 -07001776 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001777 table_id=table_id,
1778 out_port=out_port)
1779 if ofp.OFP_VERSION > 1:
1780 req.out_group = out_group
1781 req.cookie = cookie
1782 req.cookie_mask = cookie_mask
1783
Rich Laneae3428c2013-03-07 14:37:42 -08001784 return get_stats(test, req)
1785
Rich Lane968b6192013-03-07 15:34:43 -08001786def get_port_stats(test, port_no):
1787 """
1788 Retrieve a list of port stats entries.
1789 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001790 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001791 return get_stats(test, req)
1792
Rich Lane6a334922013-03-07 16:14:52 -08001793def get_queue_stats(test, port_no, queue_id):
1794 """
1795 Retrieve a list of queue stats entries.
1796 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001797 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001798 return get_stats(test, req)
1799
Rich Laneae3428c2013-03-07 14:37:42 -08001800def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001801 initial=[],
1802 pkts=None, bytes=None):
1803 """
1804 Verify that flow stats changed as expected.
1805
1806 Optionally takes an 'initial' list of stats entries, as returned by
1807 get_flow_stats(). If 'initial' is not given the counters are assumed to
1808 begin at 0.
1809 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001810
Rich Laneae3428c2013-03-07 14:37:42 -08001811 def accumulate(stats):
1812 pkts_acc = bytes_acc = 0
1813 for stat in stats:
1814 pkts_acc += stat.packet_count
1815 bytes_acc += stat.byte_count
1816 return (pkts_acc, bytes_acc)
1817
1818 pkts_before, bytes_before = accumulate(initial)
1819
1820 # Wait 10s for counters to update
1821 pkt_diff = byte_diff = None
1822 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001823 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001824 pkts_after, bytes_after = accumulate(stats)
1825 pkt_diff = pkts_after - pkts_before
1826 byte_diff = bytes_after - bytes_before
1827 if (pkts == None or pkt_diff >= pkts) and \
1828 (bytes == None or byte_diff >= bytes):
1829 break
Dan Talayco53724732013-03-08 23:54:02 -08001830 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001831
1832 if pkts != None:
1833 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1834
1835 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001836 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1837 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001838
Rich Lane968b6192013-03-07 15:34:43 -08001839def verify_port_stats(test, port,
1840 initial=[],
1841 tx_pkts=None, rx_pkts=None,
1842 tx_bytes=None, rx_bytes=None):
1843 """
1844 Verify that port stats changed as expected.
1845
1846 Optionally takes an 'initial' list of stats entries, as returned by
1847 get_port_stats(). If 'initial' is not given the counters are assumed to
1848 begin at 0.
1849 """
1850 def accumulate(stats):
1851 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1852 for stat in stats:
1853 tx_pkts_acc += stat.tx_packets
1854 rx_pkts_acc += stat.rx_packets
1855 tx_bytes_acc += stat.tx_bytes
1856 rx_bytes_acc += stat.rx_bytes
1857 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1858
1859 tx_pkts_before, rx_pkts_before, \
1860 tx_bytes_before, rx_bytes_before = accumulate(initial)
1861
1862 # Wait 10s for counters to update
1863 for i in range(0, 100):
1864 stats = get_port_stats(test, port)
1865 tx_pkts_after, rx_pkts_after, \
1866 tx_bytes_after, rx_bytes_after = accumulate(stats)
1867 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1868 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1869 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1870 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001871 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1872 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001873 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1874 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001875 break
1876 time.sleep(0.1)
1877
1878 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001879 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1880 "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 -08001881 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001882 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1883 "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 -08001884 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001885 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1886 "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 -08001887 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001888 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1889 "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 -08001890
Rich Lane6a334922013-03-07 16:14:52 -08001891def verify_queue_stats(test, port_no, queue_id,
1892 initial=[],
1893 pkts=None, bytes=None):
1894 """
1895 Verify that queue stats changed as expected.
1896
1897 Optionally takes an 'initial' list of stats entries, as returned by
1898 get_queue_stats(). If 'initial' is not given the counters are assumed to
1899 begin at 0.
1900 """
1901 def accumulate(stats):
1902 pkts_acc = bytes_acc = 0
1903 for stat in stats:
1904 pkts_acc += stat.tx_packets
1905 bytes_acc += stat.tx_bytes
1906 return (pkts_acc, bytes_acc)
1907
1908 pkts_before, bytes_before = accumulate(initial)
1909
1910 # Wait 10s for counters to update
1911 pkt_diff = byte_diff = None
1912 for i in range(0, 100):
1913 stats = get_queue_stats(test, port_no, queue_id)
1914 pkts_after, bytes_after = accumulate(stats)
1915 pkt_diff = pkts_after - pkts_before
1916 byte_diff = bytes_after - bytes_before
1917 if (pkts == None or pkt_diff >= pkts) and \
1918 (bytes == None or byte_diff >= bytes):
1919 break
Dan Talayco53724732013-03-08 23:54:02 -08001920 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001921
1922 if pkts != None:
1923 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1924
1925 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001926 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1927 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001928
Rich Lane4c504f32013-06-07 17:24:14 -07001929def packet_in_match(msg, data, in_port=None, reason=None):
1930 """
1931 Check whether the packet_in message 'msg' has fields matching 'data',
1932 'in_port', and 'reason'.
1933
1934 This function handles truncated packet_in data. The 'in_port' and 'reason'
1935 parameters are optional.
1936
1937 @param msg packet_in message
1938 @param data Expected packet_in data
1939 @param in_port Expected packet_in in_port, or None
1940 @param reason Expected packet_in reason, or None
1941 """
1942
Rich Lanec0d26dd2013-07-10 12:46:03 -07001943 if ofp.OFP_VERSION <= 2:
1944 pkt_in_port = msg.in_port
1945 else:
1946 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1947 if ofp.oxm.in_port in oxms:
1948 pkt_in_port = oxms[ofp.oxm.in_port].value
1949 else:
1950 logging.warn("Missing in_port in packet-in message")
1951 pkt_in_port = None
1952
1953 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001954 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001955 return False
1956
Rich Lanec0d26dd2013-07-10 12:46:03 -07001957 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001958 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1959 return False
1960
1961 # Check that one of the packets is a prefix of the other.
1962 # The received packet may be either truncated or padded, but not both.
1963 # (Some of the padding may be truncated but that's irrelevant). We
1964 # need to check that the smaller packet is a prefix of the larger one.
1965 # Note that this check succeeds if the switch sends a zero-length
1966 # packet-in.
1967 compare_len = min(len(msg.data), len(data))
1968 if data[:compare_len] != msg.data[:compare_len]:
1969 logging.debug("Incorrect packet_in data")
1970 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1971 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1972 return False
1973
1974 return True
1975
1976def verify_packet_in(test, data, in_port, reason, controller=None):
1977 """
1978 Assert that the controller receives a packet_in message matching data 'data'
1979 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1980 itself, that's up to the test case.
1981
1982 @param test Instance of base_tests.SimpleProtocol
1983 @param pkt String to expect as the packet_in data
1984 @param in_port OpenFlow port number to expect as the packet_in in_port
1985 @param reason One of OFPR_* to expect as the packet_in reason
1986 @param controller Controller instance, defaults to test.controller
1987 @returns The received packet-in message
1988 """
1989
1990 if controller == None:
1991 controller = test.controller
1992
1993 end_time = time.time() + oftest.ofutils.default_timeout
1994
1995 while True:
1996 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1997 if not msg:
1998 # Timeout
1999 break
2000 elif packet_in_match(msg, data, in_port, reason):
2001 # Found a matching message
2002 break
2003
Kiran Poola58c5c042014-05-15 15:11:06 -07002004 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002005 return msg
2006
2007def verify_no_packet_in(test, data, in_port, controller=None):
2008 """
2009 Assert that the controller does not receive a packet_in message matching
2010 data 'data' from port 'in_port'.
2011
2012 @param test Instance of base_tests.SimpleProtocol
2013 @param pkt String to expect as the packet_in data
2014 @param in_port OpenFlow port number to expect as the packet_in in_port
2015 @param controller Controller instance, defaults to test.controller
2016 """
2017
2018 if controller == None:
2019 controller = test.controller
2020
2021 # Negative test, need to wait a short amount of time before checking we
2022 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07002023 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07002024
2025 # Check every packet_in queued in the controller
2026 while True:
2027 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
2028 if msg == None:
2029 # No more queued packet_in messages
2030 break
2031 elif packet_in_match(msg, data, in_port, None):
2032 # Found a matching message
2033 break
2034
Rich Lane82c882d2013-08-09 17:13:52 -07002035 if in_port == None:
2036 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
2037 else:
2038 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002039
Rich Lane045db072013-08-06 13:16:30 -07002040def openflow_ports(num=None):
2041 """
2042 Return a list of 'num' OpenFlow port numbers
2043
2044 If 'num' is None, return all available ports. Otherwise, limit the length
2045 of the result to 'num' and raise an exception if not enough ports are
2046 available.
2047 """
2048 ports = sorted(oftest.config["port_map"].keys())
2049 if num != None and len(ports) < num:
2050 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2051 return ports[:num]
2052
Rich Lanee4b384d2013-09-13 14:33:40 -07002053def verify_packet(test, pkt, ofport):
2054 """
2055 Check that an expected packet is received
2056 """
2057 logging.debug("Checking for pkt on port %r", ofport)
2058 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2059 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002060 return (rcv_port, rcv_pkt, pkt_time)
Charles Chanc85f1562018-01-18 15:44:29 -08002061
Rich Lanee4b384d2013-09-13 14:33:40 -07002062def verify_no_packet(test, pkt, ofport):
2063 """
2064 Check that a particular packet is not received
2065 """
2066 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002067 (rcv_port, rcv_pkt, pkt_time) = \
2068 test.dataplane.poll(
2069 port_number=ofport, exp_pkt=str(pkt),
2070 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002071 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2072
2073def verify_no_other_packets(test):
2074 """
2075 Check that no unexpected packets are received
2076
2077 This is a no-op if the --relax option is in effect.
2078 """
2079 if oftest.config["relax"]:
2080 return
2081 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002082 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002083 if rcv_pkt != None:
2084 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2085 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2086
2087def verify_packets(test, pkt, ofports):
2088 """
2089 Check that a packet is received on certain ports
2090
2091 Also verifies that the packet is not received on any other ports, and that no
2092 other packets are received (unless --relax is in effect).
2093
2094 This covers the common and simplest cases for checking dataplane outputs.
2095 For more complex usage, like multiple different packets being output, or
2096 multiple packets on the same port, use the primitive verify_packet,
2097 verify_no_packet, and verify_no_other_packets functions directly.
2098 """
2099 pkt = str(pkt)
2100 for ofport in openflow_ports():
2101 if ofport in ofports:
2102 verify_packet(test, pkt, ofport)
2103 else:
2104 verify_no_packet(test, pkt, ofport)
2105 verify_no_other_packets(test)
2106
Rich Lane12d04592013-10-10 17:21:07 -07002107def verify_no_errors(ctrl):
2108 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2109 if error:
2110 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002111
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002112def verify_capability(test, capability):
2113 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002114 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002115
2116 @param test Instance of base_tests.SimpleProtocol
2117 @param capability One of ofp_capabilities.
2118 """
2119 logging.info("Verifing that capability code is valid.")
2120 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2121 "Capability code %d does not exist." % capability)
2122 capability_str = ofp.const.ofp_capabilities_map[capability]
Charles Chanc85f1562018-01-18 15:44:29 -08002123
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002124 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002125 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002126 req = ofp.message.features_request()
2127 res, raw = test.controller.transact(req)
2128 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2129 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2130 ("Unexpected packet type %d received in response to "
2131 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002132 logging.info("Received features_reply.")
Charles Chanc85f1562018-01-18 15:44:29 -08002133
Jonathan Stout641167f2014-02-04 12:07:10 -05002134 if (res.capabilities & capability) > 0:
2135 logging.info("Switch capabilities bitmask claims to support %s",
2136 capability_str)
2137 return True, res.capabilities
2138 else:
2139 logging.info("Capabilities bitmask does not support %s.",
2140 capability_str)
2141 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002142
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002143def verify_configuration_flag(test, flag):
2144 """
2145 Return True if DUT supports specified configuration flag.
2146
2147 @param test Instance of base_tests.SimpleProtocol
2148 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002149 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002150 """
2151 logging.info("Verifing that flag is valid.")
2152 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2153 "flag %s does not exist." % flag)
2154 flag_str = ofp.const.ofp_config_flags_map[flag]
2155
Charles Chanc85f1562018-01-18 15:44:29 -08002156 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002157 req = ofp.message.get_config_request()
2158 rv = test.controller.message_send(req)
2159 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2160
2161 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2162 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2163 timeout=2)
2164 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2165 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2166
2167 if res.flags == flag:
2168 logging.info("%s flag is set.", flag_str)
2169 return True, res.flags
2170 else:
2171 logging.info("%s flag is not set.", flag_str)
2172 return False, res.flags
2173
Rich Lane7744e112013-01-11 17:23:57 -08002174__all__ = list(set(locals()) - _import_blacklist)