blob: abf4a27122a10bb6055c77a065adf3e07569b485 [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,
Jonghwan Hyunff0dfd52018-03-20 15:04:35 -0700307 out_vlan_tpid=0x8100,
Charles Chanc85f1562018-01-18 15:44:29 -0800308 out_dl_vlan_cfi=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800309 in_vlan_vid=0,
Charles Chanc85f1562018-01-18 15:44:29 -0800310 in_vlan_pcp=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800311 in_dl_vlan_cfi=0,
312 ip_src='192.168.0.1',
313 ip_dst='192.168.0.2',
314 ip_tos=0,
315 ip_ttl=64,
316 tcp_sport=1234,
317 tcp_dport=80,
318 tcp_flags="S",
319 ip_ihl=None,
320 ip_options=False
321 ):
322 """
323 Return a simple dataplane TCP packet
324
325 Supports a few parameters:
326 @param len Length of packet in bytes w/o CRC
327 @param eth_dst Destinatino MAC
328 @param eth_src Source MAC
329 @param dl_vlan_enable True if the packet is with vlan, False otherwise
330 @param vlan_vid VLAN ID
331 @param vlan_pcp VLAN priority
332 @param ip_src IP source
333 @param ip_dst IP destination
334 @param ip_tos IP ToS
335 @param ip_ttl IP TTL
336 @param tcp_dport TCP destination port
337 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800338 @param tcp_flags TCP Control flags
macauley_chengb0ec33d2015-09-04 11:32:44 +0800339
340 Generates a simple TCP request. Users
341 shouldn't assume anything about this packet other than that
342 it is a valid ethernet/IP/TCP frame.
343 """
344
345 if MINSIZE > pktlen:
346 pktlen = MINSIZE
347
348 # Note Dot1Q.id is really CFI
349 if (out_dl_vlan_enable and in_dl_vlan_enable):
Jonghwan Hyunff0dfd52018-03-20 15:04:35 -0700350 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=out_vlan_tpid)/ \
macauley_chengb0ec33d2015-09-04 11:32:44 +0800351 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
352
353 if in_dl_vlan_enable:
354 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
355
356 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
357 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
358 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
359 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
360 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
361 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
362 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
363 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
364 assert(0) #shall not have this caes
365 else:
366 if not ip_options:
367 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
368 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
369 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
370 else:
371 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
372 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
373 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
374
375 pkt = pkt/("D" * (pktlen - len(pkt)))
376
377 return pkt
378
macauley17cd60d2015-07-27 17:41:18 +0800379def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
380 eth_src='00:06:07:08:09:0a',
381 dl_vlan_enable=False,
382 vlan_vid=0,
383 vlan_pcp=0,
384 dl_vlan_cfi=0,
385 ip_src='192.168.0.1',
386 ip_dst='192.168.0.2',
387 ip_tos=0,
388 ip_ttl=64,
389 udp_sport=1234,
390 udp_dport=4789,
391 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800392 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800393 ip_ihl=None,
394 ip_options=False
395 ):
396 """
397 Return a simple dataplane UDP packet
398
399 Supports a few parameters:
400 @param len Length of packet in bytes w/o CRC
401 @param eth_dst Destination MAC
402 @param eth_src Source MAC
403 @param dl_vlan_enable True if the packet is with vlan, False otherwise
404 @param vlan_vid VLAN ID
405 @param vlan_pcp VLAN priority
406 @param ip_src IP source
407 @param ip_dst IP destination
408 @param ip_tos IP ToS
409 @param ip_ttl IP TTL
410 @param udp_dport UDP destination port
411 @param udp_sport UDP source port
412 @param inner_pyload inner pacekt content
413 Generates a simple UDP packet. Users shouldn't assume anything about
414 this packet other than that it is a valid ethernet/IP/UDP frame.
415 """
416
417 # Note Dot1Q.id is really CFI
418 if (dl_vlan_enable):
419 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
420 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
421 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
422 scapy.UDP(sport=udp_sport, dport=udp_dport)
423 else:
424 if not ip_options:
425 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
426 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
427 scapy.UDP(sport=udp_sport, dport=udp_dport)
428 else:
429 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
430 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
431 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800432
macauley17cd60d2015-07-27 17:41:18 +0800433 #add vxlan header
434 pkt = pkt/scapy.VXLAN(vni=vnid)
435 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800436 if inner_payload!=None:
437 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800438
439 return pkt
440
Charles Chanc85f1562018-01-18 15:44:29 -0800441def mpls_packet(pktlen=100,
Flavio Castro72a45d52015-12-02 16:37:05 -0500442 eth_dst='00:01:02:03:04:05',
443 eth_src='00:06:07:08:09:0a',
444 dl_vlan_enable=False,
445 vlan_vid=0,
446 vlan_pcp=0,
447 dl_vlan_cfi=0,
448 ip_src='192.168.0.1',
449 ip_dst='192.168.0.2',
450 ip_tos=0,
451 ip_ttl=64,
452 tcp_sport=1234,
453 tcp_dport=80,
454 tcp_flags="S",
455 ip_ihl=None,
456 ip_options=False,
457 label=None,
Charles Chanc85f1562018-01-18 15:44:29 -0800458 inner_payload=True,
459 encapsulated_ethernet=False,
460 encapsulated_eth_src='01:02:03:04:05:11',
461 encapsulated_eth_dst='01:02:03:04:05:22'
Flavio Castro72a45d52015-12-02 16:37:05 -0500462 ):
463 if MINSIZE > pktlen:
464 pktlen = MINSIZE
465
466 # Note Dot1Q.id is really CFI
467 if (dl_vlan_enable):
468 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
469 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
470 else:
471 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
472
473 #add MPLS header
474 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800475 l,c,s,t=label[i]
Flavio Castro72a45d52015-12-02 16:37:05 -0500476 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
477
478 #add innder payload
479 if inner_payload!=None:
Charles Chanc85f1562018-01-18 15:44:29 -0800480 if not encapsulated_ethernet:
481 pkt=pkt / \
482 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
483 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
484 else:
485 pkt=pkt / \
486 scapy.Ether(dst=encapsulated_eth_dst, src=encapsulated_eth_src)/ \
487 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
488 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
489
Flavio Castro167f5bd2015-12-02 19:33:53 -0500490 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500491
492 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800493
Pier23784aa2016-09-19 20:08:21 -0700494def pw_packet(pktlen=100,
495 out_eth_dst='00:01:02:03:04:05',
496 out_eth_src='00:06:07:08:09:0a',
497 label=None,
498 cw=None,
499 in_eth_dst='00:01:02:03:04:05',
500 in_eth_src='00:06:07:08:09:0a',
501 out_dl_vlan_enable=False,
502 in_dl_vlan_enable=False,
503 out_vlan_vid=0,
504 out_vlan_pcp=0,
505 out_dl_vlan_cfi=0,
506 in_vlan_vid=0,
507 in_vlan_pcp=0,
508 in_dl_vlan_cfi=0,
509 ip_src='192.168.0.1',
510 ip_dst='192.168.0.2',
511 ip_tos=0,
512 ip_ttl=64,
513 tcp_sport=1234,
514 tcp_dport=80,
515 tcp_flags="S",
516 ip_ihl=None,
517 ip_options=False
518 ):
519 """
520 Return a simple dataplane TCP packet encapsulated
521 in a pw packet
522 """
523
524 # Add the outer ethernet header
525 if MINSIZE > pktlen:
526 pktlen = MINSIZE
527
528 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
529
530 #add MPLS header
531 for i in range(len(label)):
532 l,c,s,t=label[i]
533 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
534
535 #add the PW CW
536 l,c,s,t=cw
537 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
538
539 # Note Dot1Q.id is really CFI
540 if (out_dl_vlan_enable and in_dl_vlan_enable):
541
542 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
543 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
544
545 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
546
547 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
548 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
549
550 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
551
552 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
553 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
554 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
555 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
556
557 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
558
559 assert(0) #shall not have this caes
560
561 else:
562 if not ip_options:
563 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
564 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
565 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
566 else:
567 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
568 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
569 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
570
571 pkt = pkt/("D" * (pktlen - len(pkt)))
572
573 return pkt
574
Pier1e4e98e2016-10-26 14:36:05 -0700575def mplsv6_packet(pktlen=100,
576 eth_dst='00:01:02:03:04:05',
577 eth_src='00:06:07:08:09:0a',
578 dl_vlan_enable=False,
579 vlan_vid=0,
580 vlan_pcp=0,
581 dl_vlan_cfi=0,
582 ipv6_src='2001:db8:85a3::8a2e:370:7334',
583 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
584 ipv6_tc=0,
585 ipv6_hlim=64,
586 ipv6_fl=0,
587 tcp_sport=1234,
588 tcp_dport=80,
589 tcp_flags="S",
590 label=None,
591 inner_payload=True
592 ):
593 if MINSIZE > pktlen:
594 pktlen = MINSIZE
595
596 # Note Dot1Q.id is really CFI
597 if (dl_vlan_enable):
598 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
599 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
600 else:
601 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
602
603 #add MPLS header
604 for i in range(len(label)):
605 l,c,s,t=label[i]
606 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
607
608 #add innder payload
609 if inner_payload!=None:
610 pkt=pkt / \
611 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
612 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
613
614 pkt = pkt/("D" * (pktlen - len(pkt)))
615
616 return pkt
617
macauley_cheng45833df2015-08-31 15:19:07 +0800618def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
619 eth_src='00:06:07:08:09:0a',
620 dl_vlan_enable=False,
621 vlan_vid=0,
622 vlan_pcp=0,
623 dl_vlan_cfi=0,
624 label=None,
625 inner_payload=None
626 ):
627 """
628 Return a simple dataplane MPLS packet
629
630 Supports a few parameters:
631 @param len Length of packet in bytes w/o CRC
632 @param eth_dst Destination MAC
633 @param eth_src Source MAC
634 @param dl_vlan_enable True if the packet is with vlan, False otherwise
635 @param vlan_vid VLAN ID
636 @param vlan_pcp VLAN priority
637 @param inner_pyload inner pacekt content
638 Generates a simple MPLS packet. Users shouldn't assume anything about
639 this packet other than that it is a valid ethernet/IP/UDP frame.
640 """
641
642 # Note Dot1Q.id is really CFI
643 if (dl_vlan_enable):
644 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
645 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
646 else:
647 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
648
649 #add MPLS header
650 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800651 l,c,s,t=label[i]
macauley_cheng45833df2015-08-31 15:19:07 +0800652 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
653
654 #add innder payload
655 if inner_payload!=None:
656 pkt=pkt/inner_payload
657
658 return pkt
Charles Chanc85f1562018-01-18 15:44:29 -0800659
Rich Lane86aceb02013-07-17 18:45:38 -0700660def simple_udpv6_packet(pktlen=100,
661 eth_dst='00:01:02:03:04:05',
662 eth_src='00:06:07:08:09:0a',
663 dl_vlan_enable=False,
664 vlan_vid=0,
665 vlan_pcp=0,
666 ipv6_src='2001:db8:85a3::8a2e:370:7334',
667 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
668 ipv6_tc=0,
669 ipv6_hlim=64,
670 ipv6_fl=0,
671 udp_sport=1234,
672 udp_dport=80):
673 """
674 Return a simple IPv6/UDP packet
675
676 Supports a few parameters:
677 @param len Length of packet in bytes w/o CRC
678 @param eth_dst Destination MAC
679 @param eth_src Source MAC
680 @param dl_vlan_enable True if the packet is with vlan, False otherwise
681 @param vlan_vid VLAN ID
682 @param vlan_pcp VLAN priority
683 @param ipv6_src IPv6 source
684 @param ipv6_dst IPv6 destination
685 @param ipv6_tc IPv6 traffic class
686 @param ipv6_ttl IPv6 hop limit
687 @param ipv6_fl IPv6 flow label
688 @param udp_dport UDP destination port
689 @param udp_sport UDP source port
690
691 Generates a simple UDP request. Users shouldn't assume anything about this
692 packet other than that it is a valid ethernet/IPv6/UDP frame.
693 """
694
695 if MINSIZE > pktlen:
696 pktlen = MINSIZE
697
698 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
699 if dl_vlan_enable or vlan_vid or vlan_pcp:
700 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
701 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
702 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
703 pkt /= ("D" * (pktlen - len(pkt)))
704
705 return pkt
706
Charles Chanc85f1562018-01-18 15:44:29 -0800707def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700708 eth_dst='00:01:02:03:04:05',
709 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700710 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700711 vlan_vid=0,
712 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700713 ip_src='192.168.0.1',
714 ip_dst='192.168.0.2',
715 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800716 ip_ttl=64,
Charles Chanc85f1562018-01-18 15:44:29 -0800717 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700718 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600719 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600720 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700721 """
722 Return a simple ICMP packet
723
724 Supports a few parameters:
725 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700726 @param eth_dst Destinatino MAC
727 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700728 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700729 @param vlan_vid VLAN ID
730 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700731 @param ip_src IP source
732 @param ip_dst IP destination
733 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800734 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600735 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700736 @param icmp_type ICMP type
737 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600738 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700739
740 Generates a simple ICMP ECHO REQUEST. Users
741 shouldn't assume anything about this packet other than that
742 it is a valid ethernet/ICMP frame.
743 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000744
745 if MINSIZE > pktlen:
746 pktlen = MINSIZE
747
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700748 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700749 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
750 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600751 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600752 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700753 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700754 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600755 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600756 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700757
758 pkt = pkt/("0" * (pktlen - len(pkt)))
759
760 return pkt
761
Rich Lane86aceb02013-07-17 18:45:38 -0700762def simple_icmpv6_packet(pktlen=100,
763 eth_dst='00:01:02:03:04:05',
764 eth_src='00:06:07:08:09:0a',
765 dl_vlan_enable=False,
766 vlan_vid=0,
767 vlan_pcp=0,
768 ipv6_src='2001:db8:85a3::8a2e:370:7334',
769 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
770 ipv6_tc=0,
771 ipv6_hlim=64,
772 ipv6_fl=0,
773 icmp_type=8,
774 icmp_code=0):
775 """
776 Return a simple ICMPv6 packet
777
778 Supports a few parameters:
779 @param len Length of packet in bytes w/o CRC
780 @param eth_dst Destination MAC
781 @param eth_src Source MAC
782 @param dl_vlan_enable True if the packet is with vlan, False otherwise
783 @param vlan_vid VLAN ID
784 @param vlan_pcp VLAN priority
785 @param ipv6_src IPv6 source
786 @param ipv6_dst IPv6 destination
787 @param ipv6_tc IPv6 traffic class
788 @param ipv6_ttl IPv6 hop limit
789 @param ipv6_fl IPv6 flow label
790 @param icmp_type ICMP type
791 @param icmp_code ICMP code
792
793 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
794 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
795 """
796
797 if MINSIZE > pktlen:
798 pktlen = MINSIZE
799
800 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
801 if dl_vlan_enable or vlan_vid or vlan_pcp:
802 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
803 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
804 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
805 pkt /= ("D" * (pktlen - len(pkt)))
806
807 return pkt
808
Charles Chanc85f1562018-01-18 15:44:29 -0800809def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700810 eth_dst='ff:ff:ff:ff:ff:ff',
811 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800812 vlan_vid=0,
813 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800814 arp_op=1,
815 ip_snd='192.168.0.1',
816 ip_tgt='192.168.0.2',
817 hw_snd='00:06:07:08:09:0a',
818 hw_tgt='00:00:00:00:00:00',
819 ):
820 """
821 Return a simple ARP packet
822
823 Supports a few parameters:
824 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700825 @param eth_dst Destinatino MAC
826 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800827 @param arp_op Operation (1=request, 2=reply)
828 @param ip_snd Sender IP
829 @param ip_tgt Target IP
830 @param hw_snd Sender hardware address
831 @param hw_tgt Target hardware address
832
833 Generates a simple ARP REQUEST. Users
834 shouldn't assume anything about this packet other than that
835 it is a valid ethernet/ARP frame.
836 """
837
838 if MINSIZE > pktlen:
839 pktlen = MINSIZE
840
Rich Lanee01611f2014-01-15 14:55:11 -0800841 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
842 if vlan_vid or vlan_pcp:
843 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
844 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 -0800845
Rich Laned459ce52014-01-24 12:09:54 -0800846 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800847
848 return pkt
849
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700850def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800851 eth_dst='00:01:02:03:04:05',
852 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700853 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000854
855 if MINSIZE > pktlen:
856 pktlen = MINSIZE
857
Rich Laned0478ff2013-03-11 12:46:58 -0700858 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700859
860 pkt = pkt/("0" * (pktlen - len(pkt)))
861
862 return pkt
863
Charles Chanc85f1562018-01-18 15:44:29 -0800864def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700865 eth_dst='00:01:02:03:04:05',
866 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800867 dl_vlan_outer=20,
868 dl_vlan_pcp_outer=0,
869 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700870 vlan_vid=10,
871 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800872 dl_vlan_cfi=0,
873 ip_src='192.168.0.1',
874 ip_dst='192.168.0.2',
875 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800876 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800877 tcp_sport=1234,
878 tcp_dport=80,
879 ip_ihl=None,
880 ip_options=False
881 ):
882 """
883 Return a doubly tagged dataplane TCP packet
884
885 Supports a few parameters:
886 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700887 @param eth_dst Destinatino MAC
888 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800889 @param dl_vlan_outer Outer VLAN ID
890 @param dl_vlan_pcp_outer Outer VLAN priority
891 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700892 @param vlan_vid Inner VLAN ID
893 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800894 @param dl_vlan_cfi VLAN cfi bit
895 @param ip_src IP source
896 @param ip_dst IP destination
897 @param ip_tos IP ToS
898 @param tcp_dport TCP destination port
899 @param ip_sport TCP source port
900
901 Generates a TCP request. Users
902 shouldn't assume anything about this packet other than that
903 it is a valid ethernet/IP/TCP frame.
904 """
905
906 if MINSIZE > pktlen:
907 pktlen = MINSIZE
908
909 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700910 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800911 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700912 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800913 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800914 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
915
916 pkt = pkt/("D" * (pktlen - len(pkt)))
917
918 return pkt
919
Shudong Zhoub7f12462012-11-20 13:01:12 -0800920def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700921 """
922 Do a barrier command
923 Return 0 on success, -1 on error
924 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700925 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800926 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800927 if resp is None:
928 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700929 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800930 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700931
Rich Lane9a003812012-10-04 17:17:59 -0700932def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700933 """
934 Get a port's configuration
935
936 Gets the switch feature configuration and grabs one port's
937 configuration
938
939 @returns (hwaddr, config, advert) The hwaddress, configuration and
940 advertised values
941 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700942
943 if ofp.OFP_VERSION <= 3:
944 request = ofp.message.features_request()
945 reply, _ = controller.transact(request)
946 if reply is None:
947 logging.warn("Get feature request failed")
948 return None, None, None
949 logging.debug(reply.show())
950 ports = reply.ports
951 else:
952 request = ofp.message.port_desc_stats_request()
953 # TODO do multipart correctly
954 reply, _ = controller.transact(request)
955 if reply is None:
956 logging.warn("Port desc stats request failed")
957 return None, None, None
958 logging.debug(reply.show())
959 ports = reply.entries
960
961 for port in ports:
962 if port.port_no == port_no:
963 return (port.hw_addr, port.config, port.advertised)
Charles Chanc85f1562018-01-18 15:44:29 -0800964
Rich Lane9a003812012-10-04 17:17:59 -0700965 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700966 return None, None, None
967
Rich Lane9a003812012-10-04 17:17:59 -0700968def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700969 """
970 Set the port configuration according the given parameters
971
972 Gets the switch feature configuration and updates one port's
973 configuration value according to config and mask
974 """
Rich Lane9a003812012-10-04 17:17:59 -0700975 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700976
977 hw_addr, _, _ = port_config_get(controller, port_no)
978
Rich Lanee717c6e2013-03-12 10:25:50 -0700979 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700980 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700981 if hw_addr != None:
982 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700983 mod.config = config
984 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700985 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800986 controller.message_send(mod)
987 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700988
Rich Lane2014f9b2012-10-05 15:29:40 -0700989def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700990 """
991 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700992 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700993 @param pkt Expected packet; may be None if yes_ports is empty
994 @param yes_ports Set or list of ports that should recieve packet
995 @param no_ports Set or list of ports that should not receive packet
996 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700997
998 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700999 """
Rich Lane91765672012-12-06 16:33:04 -08001000
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001001 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001002 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001003 exp_pkt_arg = pkt
1004
Dan Talayco92c99122010-06-03 13:53:18 -07001005 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001006 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001007 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -08001008 port_number=ofport, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001009 assert_if.assertTrue(rcv_pkt is not None,
Dan Talayco92c99122010-06-03 13:53:18 -07001010 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001011 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -08001012 logging.debug("Expected %s" % format_packet(pkt))
1013 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001014 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -08001015 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -07001016 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -07001017 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -07001018 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -07001019 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001020 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001021 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -08001022 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001023 assert_if.assertTrue(rcv_pkt is None,
Dan Talayco92c99122010-06-03 13:53:18 -07001024 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -07001025
1026
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001027def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -07001028 """
1029 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -07001030 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001031
1032 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -07001033
1034 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -07001035 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001036 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001037 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001038 exp_pkt_arg = exp_pkt
1039
Dan Talaycof6e76c02012-03-23 10:56:12 -07001040 if type(egr_ports) == type([]):
1041 egr_port_list = egr_ports
1042 else:
1043 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001044
Dan Talaycof6e76c02012-03-23 10:56:12 -07001045 # Expect a packet from each port on egr port list
1046 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001047 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001048 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001049 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001050 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001051 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001052
Dan Talaycof6e76c02012-03-23 10:56:12 -07001053 if rcv_pkt is None:
Charles Chanc85f1562018-01-18 15:44:29 -08001054 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001055 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001056
Dan Talaycof6e76c02012-03-23 10:56:12 -07001057 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001058 "Did not receive packet port " + str(check_port))
Charles Chanc85f1562018-01-18 15:44:29 -08001059 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001060 str(rcv_port))
1061
1062 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001063 logging.error("ERROR: Packet match failed.")
1064 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001065 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001066 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001067 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001068 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1069 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001070 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001071 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001072
Dan Talayco551befa2010-07-15 17:05:32 -07001073def match_verify(parent, req_match, res_match):
1074 """
1075 Verify flow matches agree; if they disagree, report where
1076
1077 parent must implement assertEqual
1078 Use str() to ensure content is compared and not pointers
1079 """
1080
1081 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1082 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1083 " != " + hex(res_match.wildcards))
1084 parent.assertEqual(req_match.in_port, res_match.in_port,
1085 'Match failed: in_port: ' + str(req_match.in_port) +
1086 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001087 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1088 'Match failed: eth_src: ' + str(req_match.eth_src) +
1089 " != " + str(res_match.eth_src))
1090 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1091 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1092 " != " + str(res_match.eth_dst))
1093 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1094 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1095 " != " + str(res_match.vlan_vid))
1096 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
Charles Chanc85f1562018-01-18 15:44:29 -08001097 'Match failed: vlan_pcp: ' +
1098 str(req_match.vlan_pcp) + " != " +
Rich Laned0478ff2013-03-11 12:46:58 -07001099 str(res_match.vlan_pcp))
1100 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1101 'Match failed: eth_type: ' + str(req_match.eth_type) +
1102 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001103
Rich Lanee717c6e2013-03-12 10:25:50 -07001104 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001105 and (req_match.eth_type == IP_ETHERTYPE)):
1106 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1107 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1108 " != " + str(res_match.ip_dscp))
1109 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1110 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1111 " != " + str(res_match.ip_proto))
1112 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1113 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1114 " != " + str(res_match.ipv4_src))
1115 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1116 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1117 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001118
Rich Lanee717c6e2013-03-12 10:25:50 -07001119 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001120 and ((req_match.ip_proto == TCP_PROTOCOL)
1121 or (req_match.ip_proto == UDP_PROTOCOL))):
1122 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
Charles Chanc85f1562018-01-18 15:44:29 -08001123 'Match failed: tcp_src: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001124 str(req_match.tcp_src) +
1125 " != " + str(res_match.tcp_src))
1126 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
Charles Chanc85f1562018-01-18 15:44:29 -08001127 'Match failed: tcp_dst: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001128 str(req_match.tcp_dst) +
1129 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001130
Ed Swierk99a74de2012-08-22 06:40:54 -07001131def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001132 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001133 if ofp.OFP_VERSION in [1, 2]:
1134 match.wildcards |= required_wildcards(parent)
1135 else:
1136 # TODO remove incompatible OXM entries
1137 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001138 return match
1139
1140def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001141 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001142 """
1143 Create a flow message
1144
Charles Chanc85f1562018-01-18 15:44:29 -08001145 Match on packet with given wildcards.
Dan Talayco551befa2010-07-15 17:05:32 -07001146 See flow_match_test for other parameter descriptoins
1147 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001148 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001149 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001150 """
Rich Lanef6883512013-03-11 17:00:09 -07001151 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001152 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001153 if wildcards is None:
1154 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001155 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001156 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001157 match.wildcards = wildcards
1158 match.in_port = ing_port
1159
Dan Talaycof6e76c02012-03-23 10:56:12 -07001160 if type(egr_ports) == type([]):
1161 egr_port_list = egr_ports
1162 else:
1163 egr_port_list = [egr_ports]
1164
Rich Lanee717c6e2013-03-12 10:25:50 -07001165 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001166 request.match = match
1167 request.buffer_id = 0xffffffff
1168 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001169 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001170 request.hard_timeout = 1
1171
Rich Lane400fb9b2013-10-10 17:20:54 -07001172 if ofp.OFP_VERSION == 1:
1173 actions = request.actions
1174 else:
1175 actions = []
1176 request.instructions.append(ofp.instruction.apply_actions(actions))
1177
Dan Talayco551befa2010-07-15 17:05:32 -07001178 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001179 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001180
1181 # Set up output/enqueue action if directed
1182 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001183 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001184 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001185 for egr_port in egr_port_list:
1186 act.port = egr_port
1187 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001188 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001189 elif egr_ports is not None:
1190 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001191 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001192 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001193 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001194
Rich Lane9a003812012-10-04 17:17:59 -07001195 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001196
1197 return request
1198
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001199def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001200 """
1201 Install a flow mod message in the switch
1202
1203 @param parent Must implement controller, assertEqual, assertTrue
1204 @param request The request, all set to go
1205 @param clear_table If true, clear the flow table before installing
1206 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001207
Rich Lane2014f9b2012-10-05 15:29:40 -07001208 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001209 if(clear_table_override != None):
1210 clear_table = clear_table_override
1211
Charles Chanc85f1562018-01-18 15:44:29 -08001212 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001213 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001214 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001215
Rich Lane9a003812012-10-04 17:17:59 -07001216 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001217 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001218
Rich Lane3a261d52013-01-03 17:45:08 -08001219 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001220
Ed Swierk99a74de2012-08-22 06:40:54 -07001221def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001222 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001223 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001224 """
1225 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001226 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001227
1228 Run test with packet through switch from ing_port to egr_port
1229 See flow_match_test for parameter descriptions
1230 """
1231
Ed Swierk99a74de2012-08-22 06:40:54 -07001232 if wildcards is None:
1233 wildcards = required_wildcards(parent)
Charles Chanc85f1562018-01-18 15:44:29 -08001234 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001235 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001236 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001237 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001238 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001239 if exp_pkt is None:
1240 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001241
Charles Chanc85f1562018-01-18 15:44:29 -08001242 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001243 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001244 action_list=action_list)
1245
1246 flow_msg_install(parent, request)
1247
Charles Chanc85f1562018-01-18 15:44:29 -08001248 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001249 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001250 parent.dataplane.send(ing_port, str(pkt))
1251
Rich Lane8f45e2d2013-10-01 16:06:54 -07001252 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001253 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001254
Rich Lane89725bb2012-12-03 16:23:27 -08001255def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001256 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001257 action_list=None):
1258 """
1259 Packet-out test on single TCP packet
1260 @param egr_ports A single port or list of ports
1261
1262 Run test sending packet-out to egr_ports. The goal is to test the actions
1263 taken on the packet, not the matching which is of course irrelevant.
1264 See flow_match_test for parameter descriptions
1265 """
1266
1267 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001268 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001269 if exp_pkt is None:
1270 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001271
Rich Lanee717c6e2013-03-12 10:25:50 -07001272 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001273 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001274 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001275 msg.data = str(pkt)
1276 if action_list is not None:
1277 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001278 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001279
1280 # Set up output action
1281 if egr_ports is not None:
1282 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001283 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001284 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001285 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001286
1287 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001288 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001289
Rich Lane8f45e2d2013-10-01 16:06:54 -07001290 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001291 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001292
Dan Talaycof6e76c02012-03-23 10:56:12 -07001293def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1294 """
1295 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001296 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001297 @param of_ports List of OF port numbers
1298 @param how_many Number of ports to be added to the list
1299 @param exclude_list List of ports not to be used
1300 @returns An empty list if unable to find enough ports
1301 """
1302
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001303 if how_many == 0:
1304 return []
1305
Dan Talaycof6e76c02012-03-23 10:56:12 -07001306 count = 0
1307 egr_ports = []
Charles Chanc85f1562018-01-18 15:44:29 -08001308 for egr_idx in range(len(of_ports)):
Dan Talaycof6e76c02012-03-23 10:56:12 -07001309 if of_ports[egr_idx] not in exclude_list:
1310 egr_ports.append(of_ports[egr_idx])
1311 count += 1
1312 if count >= how_many:
1313 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001314 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001315 return []
Charles Chanc85f1562018-01-18 15:44:29 -08001316
1317def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001318 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001319 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001320 """
Rich Lane89725bb2012-12-03 16:23:27 -08001321 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001322
1323 @param max_test If > 0 no more than this number of tests are executed.
1324 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001325 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001326 @param pkt If not None, use this packet for ingress
1327 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001328 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001329 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1330 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001331 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001332 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001333 if wildcards is None:
1334 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001335 of_ports = port_map.keys()
1336 of_ports.sort()
1337 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1338 test_count = 0
1339
Dan Talaycocfa172f2012-03-23 12:03:00 -07001340 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001341 egr_count = test_param_get('egr_count', default=2)
Charles Chanc85f1562018-01-18 15:44:29 -08001342
Dan Talayco551befa2010-07-15 17:05:32 -07001343 for ing_idx in range(len(of_ports)):
1344 ingress_port = of_ports[ing_idx]
Charles Chanc85f1562018-01-18 15:44:29 -08001345 egr_ports = get_egr_list(parent, of_ports, egr_count,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001346 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001347 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001348 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001349 if len(egr_ports) == 0:
1350 parent.assertTrue(0, "Failed to generate egress port list")
1351
Charles Chanc85f1562018-01-18 15:44:29 -08001352 flow_match_test_port_pair(parent, ingress_port, egr_ports,
1353 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001354 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001355 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001356 test_count += 1
1357 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001358 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001359 break
1360
Ed Swierk38eea082013-01-02 19:46:20 -08001361 if not test_param_get('pktout_actions', default=True):
1362 return
Rich Lane89725bb2012-12-03 16:23:27 -08001363
1364 ingress_port = of_ports[0]
1365 egr_ports = get_egr_list(parent, of_ports, egr_count,
1366 exclude_list=[ingress_port])
1367 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001368 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001369 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001370 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001371 pkt=pkt, exp_pkt=exp_pkt,
1372 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001373
Rich Lane2014f9b2012-10-05 15:29:40 -07001374def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001375 """
1376 Return value passed via test-params if present
1377
Dan Talayco4b2bee62010-07-20 14:10:05 -07001378 @param key The lookup key
1379 @param default Default value to use if not found
1380
1381 If the pair 'key=val' appeared in the string passed to --test-params
1382 on the command line, return val (as interpreted by exec). Otherwise
1383 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001384
Charles Chanc85f1562018-01-18 15:44:29 -08001385 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
Dan Talaycof6e76c02012-03-23 10:56:12 -07001386 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001387 """
1388 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001389 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001390 except:
1391 return default
1392
Dan Talayco4b2bee62010-07-20 14:10:05 -07001393 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001394 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001395 except:
1396 return default
1397
1398def action_generate(parent, field_to_mod, mod_field_vals):
1399 """
1400 Create an action to modify the field indicated in field_to_mod
1401
1402 @param parent Must implement, assertTrue
1403 @param field_to_mod The field to modify as a string name
1404 @param mod_field_vals Hash of values to use for modified values
1405 """
1406
1407 act = None
1408
1409 if field_to_mod in ['pktlen']:
1410 return None
1411
Rich Laned0478ff2013-03-11 12:46:58 -07001412 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001413 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001414 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001415 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001416 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001417 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001418 elif field_to_mod == 'dl_vlan_enable':
1419 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001420 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001421 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001422 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001423 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001424 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001425 act.vlan_vid = mod_field_vals['vlan_vid']
1426 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001427 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001428 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001429 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001430 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001431 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001432 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001433 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001434 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001435 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001436 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001437 act.nw_tos = mod_field_vals['ip_tos']
1438 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001439 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001440 act.tp_port = mod_field_vals['tcp_sport']
1441 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001442 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001443 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001444 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001445 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001446 act.tp_port = mod_field_vals['udp_sport']
1447 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001448 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001449 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001450 else:
1451 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1452
1453 return act
1454
Charles Chanc85f1562018-01-18 15:44:29 -08001455def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001456 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001457 """
1458 Set up the ingress and expected packet and action list for a test
1459
Rich Lane2014f9b2012-10-05 15:29:40 -07001460 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001461 @param start_field_values Field values to use for ingress packet (optional)
1462 @param mod_field_values Field values to use for modified packet (optional)
1463 @param mod_fields The list of fields to be modified by the switch in the test.
1464 @params check_test_params If True, will check the parameters vid, add_vlan
1465 and strip_vlan from the command line.
1466
1467 Returns a triple: pkt-to-send, expected-pkt, action-list
1468 """
1469
1470 new_actions = []
1471
Dan Talayco4b2bee62010-07-20 14:10:05 -07001472 base_pkt_params = {}
1473 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001474 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1475 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001476 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001477 base_pkt_params['vlan_vid'] = 2
1478 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001479 base_pkt_params['ip_src'] = '192.168.0.1'
1480 base_pkt_params['ip_dst'] = '192.168.0.2'
1481 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001482 if tp == "tcp":
1483 base_pkt_params['tcp_sport'] = 1234
1484 base_pkt_params['tcp_dport'] = 80
1485 elif tp == "udp":
1486 base_pkt_params['udp_sport'] = 1234
1487 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001488 for keyname in start_field_vals.keys():
1489 base_pkt_params[keyname] = start_field_vals[keyname]
1490
1491 mod_pkt_params = {}
1492 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001493 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1494 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001496 mod_pkt_params['vlan_vid'] = 3
1497 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001498 mod_pkt_params['ip_src'] = '10.20.30.40'
1499 mod_pkt_params['ip_dst'] = '50.60.70.80'
1500 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001501 if tp == "tcp":
1502 mod_pkt_params['tcp_sport'] = 4321
1503 mod_pkt_params['tcp_dport'] = 8765
1504 elif tp == "udp":
1505 mod_pkt_params['udp_sport'] = 4321
1506 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 for keyname in mod_field_vals.keys():
1508 mod_pkt_params[keyname] = mod_field_vals[keyname]
1509
1510 # Check for test param modifications
1511 strip = False
1512 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001513 add_vlan = test_param_get('add_vlan')
1514 strip_vlan = test_param_get('strip_vlan')
1515 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001516
1517 if add_vlan and strip_vlan:
1518 parent.assertTrue(0, "Add and strip VLAN both specified")
1519
1520 if vid:
1521 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001522 base_pkt_params['vlan_vid'] = vid
1523 if 'vlan_vid' in mod_fields:
1524 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001525
1526 if add_vlan:
1527 base_pkt_params['dl_vlan_enable'] = False
1528 mod_pkt_params['dl_vlan_enable'] = True
1529 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1530 mod_fields.append('pktlen')
1531 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001532 if 'vlan_vid' not in mod_fields:
1533 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001534 elif strip_vlan:
1535 base_pkt_params['dl_vlan_enable'] = True
1536 mod_pkt_params['dl_vlan_enable'] = False
1537 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1538 mod_fields.append('dl_vlan_enable')
1539 mod_fields.append('pktlen')
1540
Rich Lane110e0e32012-10-26 16:21:46 -07001541 if tp == "tcp":
1542 packet_builder = simple_tcp_packet
1543 elif tp == "udp":
1544 packet_builder = simple_udp_packet
1545 else:
1546 raise NotImplementedError("unknown transport protocol %s" % tp)
1547
Dan Talayco4b2bee62010-07-20 14:10:05 -07001548 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001549 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001550
1551 # Build the expected packet, modifying the indicated fields
1552 for item in mod_fields:
1553 base_pkt_params[item] = mod_pkt_params[item]
1554 act = action_generate(parent, item, mod_pkt_params)
1555 if act:
1556 new_actions.append(act)
1557
Rich Lane110e0e32012-10-26 16:21:46 -07001558 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001559
1560 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001561
1562# Generate a simple "drop" flow mod
1563# If in_band is true, then only drop from first test port
1564def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001565 request = ofp.message.flow_add()
1566 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001567 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001568 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001569 for of_port, ifname in port_map.items(): # Grab first port
1570 break
1571 request.match.in_port = of_port
1572 request.buffer_id = 0xffffffff
1573 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001574
1575def skip_message_emit(parent, s):
1576 """
1577 Print out a 'skipped' message to stderr
1578
1579 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001580 """
1581 global skipped_test_count
1582
1583 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001584 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001585 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001586 sys.stderr.write("(skipped) ")
1587 else:
1588 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001589
Dan Talayco8a64e332012-03-28 14:53:20 -07001590
1591def all_stats_get(parent):
1592 """
1593 Get the aggregate stats for all flows in the table
1594 @param parent Test instance with controller connection and assert
Charles Chanc85f1562018-01-18 15:44:29 -08001595 @returns dict with keys flows, packets, bytes, active (flows),
Dan Talayco8a64e332012-03-28 14:53:20 -07001596 lookups, matched
1597 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001598 stat_req = ofp.message.aggregate_stats_request()
1599 stat_req.match = ofp.match()
1600 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001601 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001602 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001603
1604 rv = {}
1605
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001606 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001607 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001608
Rich Lane5fd6faf2013-03-11 13:30:20 -07001609 for obj in reply.entries:
Charles Chanc85f1562018-01-18 15:44:29 -08001610 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
Dan Talayco8a64e332012-03-28 14:53:20 -07001611 obj.packet_count, obj.byte_count)
1612 break
1613
Rich Lanee717c6e2013-03-12 10:25:50 -07001614 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001615 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001616
Charles Chanc85f1562018-01-18 15:44:29 -08001617
Dan Talayco8a64e332012-03-28 14:53:20 -07001618 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001619 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001620 rv["active"] += obj.active_count
1621 rv["lookups"] += obj.lookup_count
1622 rv["matched"] += obj.matched_count
1623
1624 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001625
Rich Lane7744e112013-01-11 17:23:57 -08001626_import_blacklist.add('FILTER')
Charles Chanc85f1562018-01-18 15:44:29 -08001627FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
Dan Talayco2baf8b52012-03-30 09:55:42 -07001628 for x in range(256)])
1629
1630def hex_dump_buffer(src, length=16):
1631 """
1632 Convert src to a hex dump string and return the string
1633 @param src The source buffer
1634 @param length The number of bytes shown in each line
1635 @returns A string showing the hex dump
1636 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001637 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001638 for i in xrange(0, len(src), length):
1639 chars = src[i:i+length]
1640 hex = ' '.join(["%02x" % ord(x) for x in chars])
1641 printable = ''.join(["%s" % ((ord(x) <= 127 and
1642 FILTER[ord(x)]) or '.') for x in chars])
1643 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1644 return ''.join(result)
1645
1646def format_packet(pkt):
Charles Chanc85f1562018-01-18 15:44:29 -08001647 return "Packet length %d \n%s" % (len(str(pkt)),
Dan Talayco2baf8b52012-03-30 09:55:42 -07001648 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001649
1650def inspect_packet(pkt):
1651 """
1652 Wrapper around scapy's show() method.
1653 @returns A string showing the dissected packet.
1654 """
1655 from cStringIO import StringIO
1656 out = None
1657 backup = sys.stdout
1658 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001659 tmp = StringIO()
1660 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001661 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001662 out = tmp.getvalue()
1663 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001664 finally:
1665 sys.stdout = backup
1666 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001667
1668def nonstandard(cls):
1669 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001670 Testcase decorator that marks the test as being non-standard.
1671 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001672 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001673 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001674 return cls
1675
1676def disabled(cls):
1677 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001678 Testcase decorator that marks the test as being disabled.
1679 These tests are not automatically added to the "standard" group or
1680 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001681 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001682 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001683 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001684
1685def group(name):
1686 """
1687 Testcase decorator that adds the test to a group.
1688 """
1689 def fn(cls):
1690 if not hasattr(cls, "_groups"):
1691 cls._groups = []
1692 cls._groups.append(name)
1693 return cls
1694 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001695
1696def version(ver):
1697 """
1698 Testcase decorator that specifies which versions of OpenFlow the test
1699 supports. The default is 1.0+. This decorator may only be used once.
1700
1701 Supported syntax:
1702 1.0 -> 1.0
1703 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1704 1.0+ -> 1.0, 1.1, 1.2, 1.3
1705 """
1706 versions = parse_version(ver)
1707 def fn(cls):
1708 cls._versions = versions
1709 return cls
1710 return fn
1711
1712def parse_version(ver):
1713 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1714 if re.match("^1\.\d+$", ver):
1715 versions = set([ver])
1716 elif re.match("^(1\.\d+)\+$", ver):
1717 if not ver[:-1] in allowed_versions:
1718 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1719 versions = set()
1720 if ver != "1.1+": versions.add("1.0")
1721 if ver != "1.2+": versions.add("1.1")
1722 if ver != "1.3+": versions.add("1.2")
1723 versions.add("1.3")
1724 else:
1725 versions = set(ver.split(','))
1726
1727 for version in versions:
1728 if not version in allowed_versions:
1729 raise ValueError("invalid OpenFlow version %s" % version)
1730
1731 return versions
1732
1733assert(parse_version("1.0") == set(["1.0"]))
1734assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1735assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001736
Rich Laneae3428c2013-03-07 14:37:42 -08001737def get_stats(test, req):
1738 """
1739 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1740 """
Rich Lane609194f2013-10-21 06:17:37 -07001741 msgtype = ofp.OFPT_STATS_REPLY
1742 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001743 stats = []
1744 reply, _ = test.controller.transact(req)
1745 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001746 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001747 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001748 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001749 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001750 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001751 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001752 return stats
1753
Rich Lanebd56ed62013-07-10 15:49:44 -07001754def get_flow_stats(test, match, table_id=None,
1755 out_port=None, out_group=None,
1756 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001757 """
1758 Retrieve a list of flow stats entries.
1759 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001760
1761 if table_id == None:
1762 if ofp.OFP_VERSION <= 2:
1763 table_id = 0xff
1764 else:
1765 table_id = ofp.OFPTT_ALL
1766
Rich Lanef3bc48c2013-05-03 17:39:35 -07001767 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001768 if ofp.OFP_VERSION == 1:
1769 out_port = ofp.OFPP_NONE
1770 else:
1771 out_port = ofp.OFPP_ANY
1772
1773 if out_group == None:
1774 if ofp.OFP_VERSION > 1:
1775 out_group = ofp.OFPP_ANY
1776
Rich Lanee717c6e2013-03-12 10:25:50 -07001777 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001778 table_id=table_id,
1779 out_port=out_port)
1780 if ofp.OFP_VERSION > 1:
1781 req.out_group = out_group
1782 req.cookie = cookie
1783 req.cookie_mask = cookie_mask
1784
Rich Laneae3428c2013-03-07 14:37:42 -08001785 return get_stats(test, req)
1786
Rich Lane968b6192013-03-07 15:34:43 -08001787def get_port_stats(test, port_no):
1788 """
1789 Retrieve a list of port stats entries.
1790 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001791 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001792 return get_stats(test, req)
1793
Rich Lane6a334922013-03-07 16:14:52 -08001794def get_queue_stats(test, port_no, queue_id):
1795 """
1796 Retrieve a list of queue stats entries.
1797 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001798 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001799 return get_stats(test, req)
1800
Rich Laneae3428c2013-03-07 14:37:42 -08001801def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001802 initial=[],
1803 pkts=None, bytes=None):
1804 """
1805 Verify that flow stats changed as expected.
1806
1807 Optionally takes an 'initial' list of stats entries, as returned by
1808 get_flow_stats(). If 'initial' is not given the counters are assumed to
1809 begin at 0.
1810 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001811
Rich Laneae3428c2013-03-07 14:37:42 -08001812 def accumulate(stats):
1813 pkts_acc = bytes_acc = 0
1814 for stat in stats:
1815 pkts_acc += stat.packet_count
1816 bytes_acc += stat.byte_count
1817 return (pkts_acc, bytes_acc)
1818
1819 pkts_before, bytes_before = accumulate(initial)
1820
1821 # Wait 10s for counters to update
1822 pkt_diff = byte_diff = None
1823 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001824 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001825 pkts_after, bytes_after = accumulate(stats)
1826 pkt_diff = pkts_after - pkts_before
1827 byte_diff = bytes_after - bytes_before
1828 if (pkts == None or pkt_diff >= pkts) and \
1829 (bytes == None or byte_diff >= bytes):
1830 break
Dan Talayco53724732013-03-08 23:54:02 -08001831 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001832
1833 if pkts != None:
1834 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1835
1836 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001837 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1838 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001839
Rich Lane968b6192013-03-07 15:34:43 -08001840def verify_port_stats(test, port,
1841 initial=[],
1842 tx_pkts=None, rx_pkts=None,
1843 tx_bytes=None, rx_bytes=None):
1844 """
1845 Verify that port stats changed as expected.
1846
1847 Optionally takes an 'initial' list of stats entries, as returned by
1848 get_port_stats(). If 'initial' is not given the counters are assumed to
1849 begin at 0.
1850 """
1851 def accumulate(stats):
1852 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1853 for stat in stats:
1854 tx_pkts_acc += stat.tx_packets
1855 rx_pkts_acc += stat.rx_packets
1856 tx_bytes_acc += stat.tx_bytes
1857 rx_bytes_acc += stat.rx_bytes
1858 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1859
1860 tx_pkts_before, rx_pkts_before, \
1861 tx_bytes_before, rx_bytes_before = accumulate(initial)
1862
1863 # Wait 10s for counters to update
1864 for i in range(0, 100):
1865 stats = get_port_stats(test, port)
1866 tx_pkts_after, rx_pkts_after, \
1867 tx_bytes_after, rx_bytes_after = accumulate(stats)
1868 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1869 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1870 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1871 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001872 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1873 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001874 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1875 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001876 break
1877 time.sleep(0.1)
1878
1879 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001880 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1881 "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 -08001882 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001883 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1884 "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 -08001885 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001886 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1887 "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 -08001888 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001889 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1890 "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 -08001891
Rich Lane6a334922013-03-07 16:14:52 -08001892def verify_queue_stats(test, port_no, queue_id,
1893 initial=[],
1894 pkts=None, bytes=None):
1895 """
1896 Verify that queue stats changed as expected.
1897
1898 Optionally takes an 'initial' list of stats entries, as returned by
1899 get_queue_stats(). If 'initial' is not given the counters are assumed to
1900 begin at 0.
1901 """
1902 def accumulate(stats):
1903 pkts_acc = bytes_acc = 0
1904 for stat in stats:
1905 pkts_acc += stat.tx_packets
1906 bytes_acc += stat.tx_bytes
1907 return (pkts_acc, bytes_acc)
1908
1909 pkts_before, bytes_before = accumulate(initial)
1910
1911 # Wait 10s for counters to update
1912 pkt_diff = byte_diff = None
1913 for i in range(0, 100):
1914 stats = get_queue_stats(test, port_no, queue_id)
1915 pkts_after, bytes_after = accumulate(stats)
1916 pkt_diff = pkts_after - pkts_before
1917 byte_diff = bytes_after - bytes_before
1918 if (pkts == None or pkt_diff >= pkts) and \
1919 (bytes == None or byte_diff >= bytes):
1920 break
Dan Talayco53724732013-03-08 23:54:02 -08001921 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001922
1923 if pkts != None:
1924 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1925
1926 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001927 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1928 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001929
Rich Lane4c504f32013-06-07 17:24:14 -07001930def packet_in_match(msg, data, in_port=None, reason=None):
1931 """
1932 Check whether the packet_in message 'msg' has fields matching 'data',
1933 'in_port', and 'reason'.
1934
1935 This function handles truncated packet_in data. The 'in_port' and 'reason'
1936 parameters are optional.
1937
1938 @param msg packet_in message
1939 @param data Expected packet_in data
1940 @param in_port Expected packet_in in_port, or None
1941 @param reason Expected packet_in reason, or None
1942 """
1943
Rich Lanec0d26dd2013-07-10 12:46:03 -07001944 if ofp.OFP_VERSION <= 2:
1945 pkt_in_port = msg.in_port
1946 else:
1947 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1948 if ofp.oxm.in_port in oxms:
1949 pkt_in_port = oxms[ofp.oxm.in_port].value
1950 else:
1951 logging.warn("Missing in_port in packet-in message")
1952 pkt_in_port = None
1953
1954 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001955 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001956 return False
1957
Rich Lanec0d26dd2013-07-10 12:46:03 -07001958 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001959 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1960 return False
1961
1962 # Check that one of the packets is a prefix of the other.
1963 # The received packet may be either truncated or padded, but not both.
1964 # (Some of the padding may be truncated but that's irrelevant). We
1965 # need to check that the smaller packet is a prefix of the larger one.
1966 # Note that this check succeeds if the switch sends a zero-length
1967 # packet-in.
1968 compare_len = min(len(msg.data), len(data))
1969 if data[:compare_len] != msg.data[:compare_len]:
1970 logging.debug("Incorrect packet_in data")
1971 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1972 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1973 return False
1974
1975 return True
1976
1977def verify_packet_in(test, data, in_port, reason, controller=None):
1978 """
1979 Assert that the controller receives a packet_in message matching data 'data'
1980 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1981 itself, that's up to the test case.
1982
1983 @param test Instance of base_tests.SimpleProtocol
1984 @param pkt String to expect as the packet_in data
1985 @param in_port OpenFlow port number to expect as the packet_in in_port
1986 @param reason One of OFPR_* to expect as the packet_in reason
1987 @param controller Controller instance, defaults to test.controller
1988 @returns The received packet-in message
1989 """
1990
1991 if controller == None:
1992 controller = test.controller
1993
1994 end_time = time.time() + oftest.ofutils.default_timeout
1995
1996 while True:
1997 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1998 if not msg:
1999 # Timeout
2000 break
2001 elif packet_in_match(msg, data, in_port, reason):
2002 # Found a matching message
2003 break
2004
Kiran Poola58c5c042014-05-15 15:11:06 -07002005 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002006 return msg
2007
2008def verify_no_packet_in(test, data, in_port, controller=None):
2009 """
2010 Assert that the controller does not receive a packet_in message matching
2011 data 'data' from port 'in_port'.
2012
2013 @param test Instance of base_tests.SimpleProtocol
2014 @param pkt String to expect as the packet_in data
2015 @param in_port OpenFlow port number to expect as the packet_in in_port
2016 @param controller Controller instance, defaults to test.controller
2017 """
2018
2019 if controller == None:
2020 controller = test.controller
2021
2022 # Negative test, need to wait a short amount of time before checking we
2023 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07002024 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07002025
2026 # Check every packet_in queued in the controller
2027 while True:
2028 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
2029 if msg == None:
2030 # No more queued packet_in messages
2031 break
2032 elif packet_in_match(msg, data, in_port, None):
2033 # Found a matching message
2034 break
2035
Rich Lane82c882d2013-08-09 17:13:52 -07002036 if in_port == None:
2037 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
2038 else:
2039 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002040
Rich Lane045db072013-08-06 13:16:30 -07002041def openflow_ports(num=None):
2042 """
2043 Return a list of 'num' OpenFlow port numbers
2044
2045 If 'num' is None, return all available ports. Otherwise, limit the length
2046 of the result to 'num' and raise an exception if not enough ports are
2047 available.
2048 """
2049 ports = sorted(oftest.config["port_map"].keys())
2050 if num != None and len(ports) < num:
2051 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2052 return ports[:num]
2053
Rich Lanee4b384d2013-09-13 14:33:40 -07002054def verify_packet(test, pkt, ofport):
2055 """
2056 Check that an expected packet is received
2057 """
2058 logging.debug("Checking for pkt on port %r", ofport)
2059 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2060 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002061 return (rcv_port, rcv_pkt, pkt_time)
Charles Chanc85f1562018-01-18 15:44:29 -08002062
Rich Lanee4b384d2013-09-13 14:33:40 -07002063def verify_no_packet(test, pkt, ofport):
2064 """
2065 Check that a particular packet is not received
2066 """
2067 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002068 (rcv_port, rcv_pkt, pkt_time) = \
2069 test.dataplane.poll(
2070 port_number=ofport, exp_pkt=str(pkt),
2071 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002072 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2073
2074def verify_no_other_packets(test):
2075 """
2076 Check that no unexpected packets are received
2077
2078 This is a no-op if the --relax option is in effect.
2079 """
2080 if oftest.config["relax"]:
2081 return
2082 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002083 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002084 if rcv_pkt != None:
2085 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2086 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2087
2088def verify_packets(test, pkt, ofports):
2089 """
2090 Check that a packet is received on certain ports
2091
2092 Also verifies that the packet is not received on any other ports, and that no
2093 other packets are received (unless --relax is in effect).
2094
2095 This covers the common and simplest cases for checking dataplane outputs.
2096 For more complex usage, like multiple different packets being output, or
2097 multiple packets on the same port, use the primitive verify_packet,
2098 verify_no_packet, and verify_no_other_packets functions directly.
2099 """
2100 pkt = str(pkt)
2101 for ofport in openflow_ports():
2102 if ofport in ofports:
2103 verify_packet(test, pkt, ofport)
2104 else:
2105 verify_no_packet(test, pkt, ofport)
2106 verify_no_other_packets(test)
2107
Rich Lane12d04592013-10-10 17:21:07 -07002108def verify_no_errors(ctrl):
2109 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2110 if error:
2111 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002112
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002113def verify_capability(test, capability):
2114 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002115 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002116
2117 @param test Instance of base_tests.SimpleProtocol
2118 @param capability One of ofp_capabilities.
2119 """
2120 logging.info("Verifing that capability code is valid.")
2121 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2122 "Capability code %d does not exist." % capability)
2123 capability_str = ofp.const.ofp_capabilities_map[capability]
Charles Chanc85f1562018-01-18 15:44:29 -08002124
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002125 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002126 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002127 req = ofp.message.features_request()
2128 res, raw = test.controller.transact(req)
2129 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2130 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2131 ("Unexpected packet type %d received in response to "
2132 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002133 logging.info("Received features_reply.")
Charles Chanc85f1562018-01-18 15:44:29 -08002134
Jonathan Stout641167f2014-02-04 12:07:10 -05002135 if (res.capabilities & capability) > 0:
2136 logging.info("Switch capabilities bitmask claims to support %s",
2137 capability_str)
2138 return True, res.capabilities
2139 else:
2140 logging.info("Capabilities bitmask does not support %s.",
2141 capability_str)
2142 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002143
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002144def verify_configuration_flag(test, flag):
2145 """
2146 Return True if DUT supports specified configuration flag.
2147
2148 @param test Instance of base_tests.SimpleProtocol
2149 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002150 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002151 """
2152 logging.info("Verifing that flag is valid.")
2153 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2154 "flag %s does not exist." % flag)
2155 flag_str = ofp.const.ofp_config_flags_map[flag]
2156
Charles Chanc85f1562018-01-18 15:44:29 -08002157 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002158 req = ofp.message.get_config_request()
2159 rv = test.controller.message_send(req)
2160 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2161
2162 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2163 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2164 timeout=2)
2165 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2166 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2167
2168 if res.flags == flag:
2169 logging.info("%s flag is set.", flag_str)
2170 return True, res.flags
2171 else:
2172 logging.info("%s flag is not set.", flag_str)
2173 return False, res.flags
2174
Rich Lane7744e112013-01-11 17:23:57 -08002175__all__ = list(set(locals()) - _import_blacklist)