blob: 7953bfe956fa492a1e0d2db9984e23d1e10265b9 [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,
128 vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -0700129 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800130 ip_src='192.168.0.1',
131 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700132 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800133 ip_ttl=64,
Dan Talayco41eae8b2010-03-10 13:57:06 -0800134 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700135 tcp_dport=80,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700136 tcp_flags="S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700137 ip_ihl=None,
138 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -0800139 ):
140 """
141 Return a simple dataplane TCP packet
142
143 Supports a few parameters:
144 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700145 @param eth_dst Destinatino MAC
146 @param eth_src Source MAC
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700147 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700148 @param vlan_vid VLAN ID
149 @param vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -0800150 @param ip_src IP source
151 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700152 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800153 @param ip_ttl IP TTL
Dan Talayco41eae8b2010-03-10 13:57:06 -0800154 @param tcp_dport TCP destination port
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700155 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800156 @param tcp_flags TCP Control flags
Dan Talayco41eae8b2010-03-10 13:57:06 -0800157
158 Generates a simple TCP request. Users
159 shouldn't assume anything about this packet other than that
160 it is a valid ethernet/IP/TCP frame.
161 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000162
163 if MINSIZE > pktlen:
164 pktlen = MINSIZE
165
Dan Talayco551befa2010-07-15 17:05:32 -0700166 # Note Dot1Q.id is really CFI
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800167 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700168 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
169 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800170 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700171 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700172 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700173 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700174 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800175 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700176 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700177 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700178 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800179 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700180 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700181
Dan Talayco41eae8b2010-03-10 13:57:06 -0800182 pkt = pkt/("D" * (pktlen - len(pkt)))
183
184 return pkt
185
Rich Lane86aceb02013-07-17 18:45:38 -0700186def simple_tcpv6_packet(pktlen=100,
187 eth_dst='00:01:02:03:04:05',
188 eth_src='00:06:07:08:09:0a',
189 dl_vlan_enable=False,
190 vlan_vid=0,
191 vlan_pcp=0,
192 ipv6_src='2001:db8:85a3::8a2e:370:7334',
193 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
194 ipv6_tc=0,
195 ipv6_hlim=64,
196 ipv6_fl=0,
197 tcp_sport=1234,
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700198 tcp_dport=80,
Harshmeet Singh31ba3312014-05-21 13:48:35 -0700199 tcp_flags="S"):
Rich Lane86aceb02013-07-17 18:45:38 -0700200 """
201 Return a simple IPv6/TCP packet
202
203 Supports a few parameters:
204 @param len Length of packet in bytes w/o CRC
205 @param eth_dst Destination MAC
206 @param eth_src Source MAC
207 @param dl_vlan_enable True if the packet is with vlan, False otherwise
208 @param vlan_vid VLAN ID
209 @param vlan_pcp VLAN priority
210 @param ipv6_src IPv6 source
211 @param ipv6_dst IPv6 destination
212 @param ipv6_tc IPv6 traffic class
213 @param ipv6_ttl IPv6 hop limit
214 @param ipv6_fl IPv6 flow label
215 @param tcp_dport TCP destination port
216 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800217 @param tcp_flags TCP Control flags
Rich Lane86aceb02013-07-17 18:45:38 -0700218
219 Generates a simple TCP request. Users shouldn't assume anything about this
220 packet other than that it is a valid ethernet/IPv6/TCP frame.
221 """
222
223 if MINSIZE > pktlen:
224 pktlen = MINSIZE
225
226 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
227 if dl_vlan_enable or vlan_vid or vlan_pcp:
228 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
229 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
Harshmeet Singhc51f4042014-05-21 13:32:52 -0700230 pkt /= scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
Rich Lane86aceb02013-07-17 18:45:38 -0700231 pkt /= ("D" * (pktlen - len(pkt)))
232
233 return pkt
234
Rich Lane6ee7bea2012-10-26 16:19:29 -0700235def simple_udp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700236 eth_dst='00:01:02:03:04:05',
237 eth_src='00:06:07:08:09:0a',
Rich Lane6ee7bea2012-10-26 16:19:29 -0700238 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700239 vlan_vid=0,
240 vlan_pcp=0,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700241 dl_vlan_cfi=0,
242 ip_src='192.168.0.1',
243 ip_dst='192.168.0.2',
244 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800245 ip_ttl=64,
Rich Lane6ee7bea2012-10-26 16:19:29 -0700246 udp_sport=1234,
247 udp_dport=80,
248 ip_ihl=None,
249 ip_options=False
250 ):
251 """
252 Return a simple dataplane UDP packet
253
254 Supports a few parameters:
255 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700256 @param eth_dst Destination MAC
257 @param eth_src Source MAC
Rich Lane6ee7bea2012-10-26 16:19:29 -0700258 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700259 @param vlan_vid VLAN ID
260 @param vlan_pcp VLAN priority
Rich Lane6ee7bea2012-10-26 16:19:29 -0700261 @param ip_src IP source
262 @param ip_dst IP destination
263 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800264 @param ip_ttl IP TTL
Rich Lane6ee7bea2012-10-26 16:19:29 -0700265 @param udp_dport UDP destination port
266 @param udp_sport UDP source port
267
268 Generates a simple UDP packet. Users shouldn't assume anything about
269 this packet other than that it is a valid ethernet/IP/UDP frame.
270 """
271
272 if MINSIZE > pktlen:
273 pktlen = MINSIZE
274
275 # Note Dot1Q.id is really CFI
276 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700277 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
278 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800279 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700280 scapy.UDP(sport=udp_sport, dport=udp_dport)
281 else:
282 if not ip_options:
Rich Laned0478ff2013-03-11 12:46:58 -0700283 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800284 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700285 scapy.UDP(sport=udp_sport, dport=udp_dport)
286 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700287 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800288 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
Rich Lane6ee7bea2012-10-26 16:19:29 -0700289 scapy.UDP(sport=udp_sport, dport=udp_dport)
290
291 pkt = pkt/("D" * (pktlen - len(pkt)))
292
293 return pkt
294
macauley_chengb0ec33d2015-09-04 11:32:44 +0800295
Charles Chanc85f1562018-01-18 15:44:29 -0800296def simple_tcp_packet_two_vlan(pktlen=100,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800297 eth_dst='00:01:02:03:04:05',
298 eth_src='00:06:07:08:09:0a',
299 out_dl_vlan_enable=False,
300 in_dl_vlan_enable=False,
301 out_vlan_vid=0,
302 out_vlan_pcp=0,
Charles Chanc85f1562018-01-18 15:44:29 -0800303 out_dl_vlan_cfi=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800304 in_vlan_vid=0,
Charles Chanc85f1562018-01-18 15:44:29 -0800305 in_vlan_pcp=0,
macauley_chengb0ec33d2015-09-04 11:32:44 +0800306 in_dl_vlan_cfi=0,
307 ip_src='192.168.0.1',
308 ip_dst='192.168.0.2',
309 ip_tos=0,
310 ip_ttl=64,
311 tcp_sport=1234,
312 tcp_dport=80,
313 tcp_flags="S",
314 ip_ihl=None,
315 ip_options=False
316 ):
317 """
318 Return a simple dataplane TCP packet
319
320 Supports a few parameters:
321 @param len Length of packet in bytes w/o CRC
322 @param eth_dst Destinatino MAC
323 @param eth_src Source MAC
324 @param dl_vlan_enable True if the packet is with vlan, False otherwise
325 @param vlan_vid VLAN ID
326 @param vlan_pcp VLAN priority
327 @param ip_src IP source
328 @param ip_dst IP destination
329 @param ip_tos IP ToS
330 @param ip_ttl IP TTL
331 @param tcp_dport TCP destination port
332 @param tcp_sport TCP source port
Charles Chanc85f1562018-01-18 15:44:29 -0800333 @param tcp_flags TCP Control flags
macauley_chengb0ec33d2015-09-04 11:32:44 +0800334
335 Generates a simple TCP request. Users
336 shouldn't assume anything about this packet other than that
337 it is a valid ethernet/IP/TCP frame.
338 """
339
340 if MINSIZE > pktlen:
341 pktlen = MINSIZE
342
343 # Note Dot1Q.id is really CFI
344 if (out_dl_vlan_enable and in_dl_vlan_enable):
345 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
346 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
347
348 if in_dl_vlan_enable:
349 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
350
351 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
352 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
353 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
354 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
355 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
356 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
357 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
358 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
359 assert(0) #shall not have this caes
360 else:
361 if not ip_options:
362 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
363 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
364 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
365 else:
366 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
367 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
368 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
369
370 pkt = pkt/("D" * (pktlen - len(pkt)))
371
372 return pkt
373
macauley17cd60d2015-07-27 17:41:18 +0800374def simple_vxlan_packet(eth_dst='00:01:02:03:04:05',
375 eth_src='00:06:07:08:09:0a',
376 dl_vlan_enable=False,
377 vlan_vid=0,
378 vlan_pcp=0,
379 dl_vlan_cfi=0,
380 ip_src='192.168.0.1',
381 ip_dst='192.168.0.2',
382 ip_tos=0,
383 ip_ttl=64,
384 udp_sport=1234,
385 udp_dport=4789,
386 vnid=1,
macauley1b23af82015-07-30 14:06:33 +0800387 inner_payload=None,
macauley17cd60d2015-07-27 17:41:18 +0800388 ip_ihl=None,
389 ip_options=False
390 ):
391 """
392 Return a simple dataplane UDP packet
393
394 Supports a few parameters:
395 @param len Length of packet in bytes w/o CRC
396 @param eth_dst Destination MAC
397 @param eth_src Source MAC
398 @param dl_vlan_enable True if the packet is with vlan, False otherwise
399 @param vlan_vid VLAN ID
400 @param vlan_pcp VLAN priority
401 @param ip_src IP source
402 @param ip_dst IP destination
403 @param ip_tos IP ToS
404 @param ip_ttl IP TTL
405 @param udp_dport UDP destination port
406 @param udp_sport UDP source port
407 @param inner_pyload inner pacekt content
408 Generates a simple UDP packet. Users shouldn't assume anything about
409 this packet other than that it is a valid ethernet/IP/UDP frame.
410 """
411
412 # Note Dot1Q.id is really CFI
413 if (dl_vlan_enable):
414 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
415 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
416 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
417 scapy.UDP(sport=udp_sport, dport=udp_dport)
418 else:
419 if not ip_options:
420 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
421 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
422 scapy.UDP(sport=udp_sport, dport=udp_dport)
423 else:
424 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
425 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
426 scapy.UDP(sport=udp_sport, dport=udp_dport)
macauley1b23af82015-07-30 14:06:33 +0800427
macauley17cd60d2015-07-27 17:41:18 +0800428 #add vxlan header
429 pkt = pkt/scapy.VXLAN(vni=vnid)
430 #add innder payload
macauley1b23af82015-07-30 14:06:33 +0800431 if inner_payload!=None:
432 pkt=pkt/inner_payload
macauley17cd60d2015-07-27 17:41:18 +0800433
434 return pkt
435
Charles Chanc85f1562018-01-18 15:44:29 -0800436def mpls_packet(pktlen=100,
Flavio Castro72a45d52015-12-02 16:37:05 -0500437 eth_dst='00:01:02:03:04:05',
438 eth_src='00:06:07:08:09:0a',
439 dl_vlan_enable=False,
440 vlan_vid=0,
441 vlan_pcp=0,
442 dl_vlan_cfi=0,
443 ip_src='192.168.0.1',
444 ip_dst='192.168.0.2',
445 ip_tos=0,
446 ip_ttl=64,
447 tcp_sport=1234,
448 tcp_dport=80,
449 tcp_flags="S",
450 ip_ihl=None,
451 ip_options=False,
452 label=None,
Charles Chanc85f1562018-01-18 15:44:29 -0800453 inner_payload=True,
454 encapsulated_ethernet=False,
455 encapsulated_eth_src='01:02:03:04:05:11',
456 encapsulated_eth_dst='01:02:03:04:05:22'
Flavio Castro72a45d52015-12-02 16:37:05 -0500457 ):
458 if MINSIZE > pktlen:
459 pktlen = MINSIZE
460
461 # Note Dot1Q.id is really CFI
462 if (dl_vlan_enable):
463 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
464 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
465 else:
466 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
467
468 #add MPLS header
469 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800470 l,c,s,t=label[i]
Flavio Castro72a45d52015-12-02 16:37:05 -0500471 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
472
473 #add innder payload
474 if inner_payload!=None:
Charles Chanc85f1562018-01-18 15:44:29 -0800475 if not encapsulated_ethernet:
476 pkt=pkt / \
477 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
478 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
479 else:
480 pkt=pkt / \
481 scapy.Ether(dst=encapsulated_eth_dst, src=encapsulated_eth_src)/ \
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
Flavio Castro167f5bd2015-12-02 19:33:53 -0500485 pkt = pkt/("D" * (pktlen - len(pkt)))
Flavio Castro72a45d52015-12-02 16:37:05 -0500486
487 return pkt
macauley_cheng45833df2015-08-31 15:19:07 +0800488
Pier23784aa2016-09-19 20:08:21 -0700489def pw_packet(pktlen=100,
490 out_eth_dst='00:01:02:03:04:05',
491 out_eth_src='00:06:07:08:09:0a',
492 label=None,
493 cw=None,
494 in_eth_dst='00:01:02:03:04:05',
495 in_eth_src='00:06:07:08:09:0a',
496 out_dl_vlan_enable=False,
497 in_dl_vlan_enable=False,
498 out_vlan_vid=0,
499 out_vlan_pcp=0,
500 out_dl_vlan_cfi=0,
501 in_vlan_vid=0,
502 in_vlan_pcp=0,
503 in_dl_vlan_cfi=0,
504 ip_src='192.168.0.1',
505 ip_dst='192.168.0.2',
506 ip_tos=0,
507 ip_ttl=64,
508 tcp_sport=1234,
509 tcp_dport=80,
510 tcp_flags="S",
511 ip_ihl=None,
512 ip_options=False
513 ):
514 """
515 Return a simple dataplane TCP packet encapsulated
516 in a pw packet
517 """
518
519 # Add the outer ethernet header
520 if MINSIZE > pktlen:
521 pktlen = MINSIZE
522
523 pkt = scapy.Ether(dst=out_eth_dst, src=out_eth_src)
524
525 #add MPLS header
526 for i in range(len(label)):
527 l,c,s,t=label[i]
528 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
529
530 #add the PW CW
531 l,c,s,t=cw
532 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
533
534 # Note Dot1Q.id is really CFI
535 if (out_dl_vlan_enable and in_dl_vlan_enable):
536
537 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
538 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)
539
540 pkt = pkt/scapy.Dot1Q(prio=in_vlan_pcp, id=in_dl_vlan_cfi, vlan=in_vlan_vid)
541
542 pkt = pkt/scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
543 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
544
545 elif (out_dl_vlan_enable and (not in_dl_vlan_enable)):
546
547 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
548 scapy.Dot1Q(prio=out_vlan_pcp, id=out_dl_vlan_cfi, vlan=out_vlan_vid)/ \
549 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
550 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
551
552 elif ((not out_dl_vlan_enable) and in_dl_vlan_enable):
553
554 assert(0) #shall not have this caes
555
556 else:
557 if not ip_options:
558 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
559 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
560 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
561 else:
562 pkt = pkt/scapy.Ether(dst=in_eth_dst, src=in_eth_src)/ \
563 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl, options=ip_options)/ \
564 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
565
566 pkt = pkt/("D" * (pktlen - len(pkt)))
567
568 return pkt
569
Pier1e4e98e2016-10-26 14:36:05 -0700570def mplsv6_packet(pktlen=100,
571 eth_dst='00:01:02:03:04:05',
572 eth_src='00:06:07:08:09:0a',
573 dl_vlan_enable=False,
574 vlan_vid=0,
575 vlan_pcp=0,
576 dl_vlan_cfi=0,
577 ipv6_src='2001:db8:85a3::8a2e:370:7334',
578 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
579 ipv6_tc=0,
580 ipv6_hlim=64,
581 ipv6_fl=0,
582 tcp_sport=1234,
583 tcp_dport=80,
584 tcp_flags="S",
585 label=None,
586 inner_payload=True
587 ):
588 if MINSIZE > pktlen:
589 pktlen = MINSIZE
590
591 # Note Dot1Q.id is really CFI
592 if (dl_vlan_enable):
593 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
594 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
595 else:
596 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
597
598 #add MPLS header
599 for i in range(len(label)):
600 l,c,s,t=label[i]
601 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
602
603 #add innder payload
604 if inner_payload!=None:
605 pkt=pkt / \
606 scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)/ \
607 scapy.TCP(sport=tcp_sport, dport=tcp_dport, flags=tcp_flags)
608
609 pkt = pkt/("D" * (pktlen - len(pkt)))
610
611 return pkt
612
macauley_cheng45833df2015-08-31 15:19:07 +0800613def simple_mpls_packet(eth_dst='00:01:02:03:04:05',
614 eth_src='00:06:07:08:09:0a',
615 dl_vlan_enable=False,
616 vlan_vid=0,
617 vlan_pcp=0,
618 dl_vlan_cfi=0,
619 label=None,
620 inner_payload=None
621 ):
622 """
623 Return a simple dataplane MPLS packet
624
625 Supports a few parameters:
626 @param len Length of packet in bytes w/o CRC
627 @param eth_dst Destination MAC
628 @param eth_src Source MAC
629 @param dl_vlan_enable True if the packet is with vlan, False otherwise
630 @param vlan_vid VLAN ID
631 @param vlan_pcp VLAN priority
632 @param inner_pyload inner pacekt content
633 Generates a simple MPLS packet. Users shouldn't assume anything about
634 this packet other than that it is a valid ethernet/IP/UDP frame.
635 """
636
637 # Note Dot1Q.id is really CFI
638 if (dl_vlan_enable):
639 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
640 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)
641 else:
642 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
643
644 #add MPLS header
645 for i in range(len(label)):
Charles Chanc85f1562018-01-18 15:44:29 -0800646 l,c,s,t=label[i]
macauley_cheng45833df2015-08-31 15:19:07 +0800647 pkt = pkt/scapy.MPLS(label=l, cos=c, s=s, ttl=t)
648
649 #add innder payload
650 if inner_payload!=None:
651 pkt=pkt/inner_payload
652
653 return pkt
Charles Chanc85f1562018-01-18 15:44:29 -0800654
Rich Lane86aceb02013-07-17 18:45:38 -0700655def simple_udpv6_packet(pktlen=100,
656 eth_dst='00:01:02:03:04:05',
657 eth_src='00:06:07:08:09:0a',
658 dl_vlan_enable=False,
659 vlan_vid=0,
660 vlan_pcp=0,
661 ipv6_src='2001:db8:85a3::8a2e:370:7334',
662 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
663 ipv6_tc=0,
664 ipv6_hlim=64,
665 ipv6_fl=0,
666 udp_sport=1234,
667 udp_dport=80):
668 """
669 Return a simple IPv6/UDP packet
670
671 Supports a few parameters:
672 @param len Length of packet in bytes w/o CRC
673 @param eth_dst Destination MAC
674 @param eth_src Source MAC
675 @param dl_vlan_enable True if the packet is with vlan, False otherwise
676 @param vlan_vid VLAN ID
677 @param vlan_pcp VLAN priority
678 @param ipv6_src IPv6 source
679 @param ipv6_dst IPv6 destination
680 @param ipv6_tc IPv6 traffic class
681 @param ipv6_ttl IPv6 hop limit
682 @param ipv6_fl IPv6 flow label
683 @param udp_dport UDP destination port
684 @param udp_sport UDP source port
685
686 Generates a simple UDP request. Users shouldn't assume anything about this
687 packet other than that it is a valid ethernet/IPv6/UDP frame.
688 """
689
690 if MINSIZE > pktlen:
691 pktlen = MINSIZE
692
693 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
694 if dl_vlan_enable or vlan_vid or vlan_pcp:
695 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
696 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
697 pkt /= scapy.UDP(sport=udp_sport, dport=udp_dport)
698 pkt /= ("D" * (pktlen - len(pkt)))
699
700 return pkt
701
Charles Chanc85f1562018-01-18 15:44:29 -0800702def simple_icmp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700703 eth_dst='00:01:02:03:04:05',
704 eth_src='00:06:07:08:09:0a',
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700705 dl_vlan_enable=False,
Rich Laned0478ff2013-03-11 12:46:58 -0700706 vlan_vid=0,
707 vlan_pcp=0,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700708 ip_src='192.168.0.1',
709 ip_dst='192.168.0.2',
710 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800711 ip_ttl=64,
Charles Chanc85f1562018-01-18 15:44:29 -0800712 ip_id=1,
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700713 icmp_type=8,
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600714 icmp_code=0,
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600715 icmp_data=''):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700716 """
717 Return a simple ICMP packet
718
719 Supports a few parameters:
720 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700721 @param eth_dst Destinatino MAC
722 @param eth_src Source MAC
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700723 @param dl_vlan_enable True if the packet is with vlan, False otherwise
Rich Laned0478ff2013-03-11 12:46:58 -0700724 @param vlan_vid VLAN ID
725 @param vlan_pcp VLAN priority
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700726 @param ip_src IP source
727 @param ip_dst IP destination
728 @param ip_tos IP ToS
Gregor Maier9cc93342013-01-29 16:55:28 -0800729 @param ip_ttl IP TTL
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600730 @param ip_id IP Identification
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700731 @param icmp_type ICMP type
732 @param icmp_code ICMP code
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600733 @param icmp_data ICMP data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700734
735 Generates a simple ICMP ECHO REQUEST. Users
736 shouldn't assume anything about this packet other than that
737 it is a valid ethernet/ICMP frame.
738 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000739
740 if MINSIZE > pktlen:
741 pktlen = MINSIZE
742
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700743 if (dl_vlan_enable):
Rich Laned0478ff2013-03-11 12:46:58 -0700744 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
745 scapy.Dot1Q(prio=vlan_pcp, id=0, vlan=vlan_vid)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600746 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600747 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700748 else:
Rich Laned0478ff2013-03-11 12:46:58 -0700749 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Harshmeet Singhd209c0b2014-01-28 09:48:58 -0600750 scapy.IP(src=ip_src, dst=ip_dst, ttl=ip_ttl, tos=ip_tos, id=ip_id)/ \
Harshmeet Singh45b2a9d2014-01-28 13:02:04 -0600751 scapy.ICMP(type=icmp_type, code=icmp_code)/ icmp_data
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700752
753 pkt = pkt/("0" * (pktlen - len(pkt)))
754
755 return pkt
756
Rich Lane86aceb02013-07-17 18:45:38 -0700757def simple_icmpv6_packet(pktlen=100,
758 eth_dst='00:01:02:03:04:05',
759 eth_src='00:06:07:08:09:0a',
760 dl_vlan_enable=False,
761 vlan_vid=0,
762 vlan_pcp=0,
763 ipv6_src='2001:db8:85a3::8a2e:370:7334',
764 ipv6_dst='2001:db8:85a3::8a2e:370:7335',
765 ipv6_tc=0,
766 ipv6_hlim=64,
767 ipv6_fl=0,
768 icmp_type=8,
769 icmp_code=0):
770 """
771 Return a simple ICMPv6 packet
772
773 Supports a few parameters:
774 @param len Length of packet in bytes w/o CRC
775 @param eth_dst Destination MAC
776 @param eth_src Source MAC
777 @param dl_vlan_enable True if the packet is with vlan, False otherwise
778 @param vlan_vid VLAN ID
779 @param vlan_pcp VLAN priority
780 @param ipv6_src IPv6 source
781 @param ipv6_dst IPv6 destination
782 @param ipv6_tc IPv6 traffic class
783 @param ipv6_ttl IPv6 hop limit
784 @param ipv6_fl IPv6 flow label
785 @param icmp_type ICMP type
786 @param icmp_code ICMP code
787
788 Generates a simple ICMP ECHO REQUEST. Users shouldn't assume anything
789 about this packet other than that it is a valid ethernet/IPv6/ICMP frame.
790 """
791
792 if MINSIZE > pktlen:
793 pktlen = MINSIZE
794
795 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
796 if dl_vlan_enable or vlan_vid or vlan_pcp:
797 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
798 pkt /= scapy.IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim)
799 pkt /= scapy.ICMPv6Unknown(type=icmp_type, code=icmp_code)
800 pkt /= ("D" * (pktlen - len(pkt)))
801
802 return pkt
803
Charles Chanc85f1562018-01-18 15:44:29 -0800804def simple_arp_packet(pktlen=60,
Rich Laned0478ff2013-03-11 12:46:58 -0700805 eth_dst='ff:ff:ff:ff:ff:ff',
806 eth_src='00:06:07:08:09:0a',
Rich Lanee01611f2014-01-15 14:55:11 -0800807 vlan_vid=0,
808 vlan_pcp=0,
Shudong Zhouc7562b12013-02-06 01:12:18 -0800809 arp_op=1,
810 ip_snd='192.168.0.1',
811 ip_tgt='192.168.0.2',
812 hw_snd='00:06:07:08:09:0a',
813 hw_tgt='00:00:00:00:00:00',
814 ):
815 """
816 Return a simple ARP packet
817
818 Supports a few parameters:
819 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700820 @param eth_dst Destinatino MAC
821 @param eth_src Source MAC
Shudong Zhouc7562b12013-02-06 01:12:18 -0800822 @param arp_op Operation (1=request, 2=reply)
823 @param ip_snd Sender IP
824 @param ip_tgt Target IP
825 @param hw_snd Sender hardware address
826 @param hw_tgt Target hardware address
827
828 Generates a simple ARP REQUEST. Users
829 shouldn't assume anything about this packet other than that
830 it is a valid ethernet/ARP frame.
831 """
832
833 if MINSIZE > pktlen:
834 pktlen = MINSIZE
835
Rich Lanee01611f2014-01-15 14:55:11 -0800836 pkt = scapy.Ether(dst=eth_dst, src=eth_src)
837 if vlan_vid or vlan_pcp:
838 pkt /= scapy.Dot1Q(vlan=vlan_vid, prio=vlan_pcp)
839 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 -0800840
Rich Laned459ce52014-01-24 12:09:54 -0800841 pkt = pkt/("\0" * (pktlen - len(pkt)))
Shudong Zhouc7562b12013-02-06 01:12:18 -0800842
843 return pkt
844
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700845def simple_eth_packet(pktlen=60,
Rich Lane53275082013-11-18 23:26:22 -0800846 eth_dst='00:01:02:03:04:05',
847 eth_src='00:06:07:08:09:0a',
Rich Laned0478ff2013-03-11 12:46:58 -0700848 eth_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000849
850 if MINSIZE > pktlen:
851 pktlen = MINSIZE
852
Rich Laned0478ff2013-03-11 12:46:58 -0700853 pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=eth_type)
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700854
855 pkt = pkt/("0" * (pktlen - len(pkt)))
856
857 return pkt
858
Charles Chanc85f1562018-01-18 15:44:29 -0800859def qinq_tcp_packet(pktlen=100,
Rich Laned0478ff2013-03-11 12:46:58 -0700860 eth_dst='00:01:02:03:04:05',
861 eth_src='00:06:07:08:09:0a',
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800862 dl_vlan_outer=20,
863 dl_vlan_pcp_outer=0,
864 dl_vlan_cfi_outer=0,
Rich Laned0478ff2013-03-11 12:46:58 -0700865 vlan_vid=10,
866 vlan_pcp=0,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800867 dl_vlan_cfi=0,
868 ip_src='192.168.0.1',
869 ip_dst='192.168.0.2',
870 ip_tos=0,
Gregor Maier9cc93342013-01-29 16:55:28 -0800871 ip_ttl=64,
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800872 tcp_sport=1234,
873 tcp_dport=80,
874 ip_ihl=None,
875 ip_options=False
876 ):
877 """
878 Return a doubly tagged dataplane TCP packet
879
880 Supports a few parameters:
881 @param len Length of packet in bytes w/o CRC
Rich Laned0478ff2013-03-11 12:46:58 -0700882 @param eth_dst Destinatino MAC
883 @param eth_src Source MAC
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800884 @param dl_vlan_outer Outer VLAN ID
885 @param dl_vlan_pcp_outer Outer VLAN priority
886 @param dl_vlan_cfi_outer Outer VLAN cfi bit
Rich Laned0478ff2013-03-11 12:46:58 -0700887 @param vlan_vid Inner VLAN ID
888 @param vlan_pcp VLAN priority
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800889 @param dl_vlan_cfi VLAN cfi bit
890 @param ip_src IP source
891 @param ip_dst IP destination
892 @param ip_tos IP ToS
893 @param tcp_dport TCP destination port
894 @param ip_sport TCP source port
895
896 Generates a TCP request. Users
897 shouldn't assume anything about this packet other than that
898 it is a valid ethernet/IP/TCP frame.
899 """
900
901 if MINSIZE > pktlen:
902 pktlen = MINSIZE
903
904 # Note Dot1Q.id is really CFI
Rich Laned0478ff2013-03-11 12:46:58 -0700905 pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800906 scapy.Dot1Q(prio=dl_vlan_pcp_outer, id=dl_vlan_cfi_outer, vlan=dl_vlan_outer)/ \
Rich Laned0478ff2013-03-11 12:46:58 -0700907 scapy.Dot1Q(prio=vlan_pcp, id=dl_vlan_cfi, vlan=vlan_vid)/ \
Gregor Maier9cc93342013-01-29 16:55:28 -0800908 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ttl=ip_ttl, ihl=ip_ihl)/ \
Shudong Zhou43ee54c2012-12-13 15:52:37 -0800909 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
910
911 pkt = pkt/("D" * (pktlen - len(pkt)))
912
913 return pkt
914
Shudong Zhoub7f12462012-11-20 13:01:12 -0800915def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700916 """
917 Do a barrier command
918 Return 0 on success, -1 on error
919 """
Rich Lanee717c6e2013-03-12 10:25:50 -0700920 b = ofp.message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800921 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Rich Lane3a261d52013-01-03 17:45:08 -0800922 if resp is None:
923 raise AssertionError("barrier failed")
Dan Talaycof6b94832012-04-12 21:50:57 -0700924 # We'll trust the transaction processing in the controller that xid matched
Rich Lane3a261d52013-01-03 17:45:08 -0800925 return 0 # for backwards compatibility
Dan Talayco92c99122010-06-03 13:53:18 -0700926
Rich Lane9a003812012-10-04 17:17:59 -0700927def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700928 """
929 Get a port's configuration
930
931 Gets the switch feature configuration and grabs one port's
932 configuration
933
934 @returns (hwaddr, config, advert) The hwaddress, configuration and
935 advertised values
936 """
Rich Lane6dc865c2013-07-10 10:12:13 -0700937
938 if ofp.OFP_VERSION <= 3:
939 request = ofp.message.features_request()
940 reply, _ = controller.transact(request)
941 if reply is None:
942 logging.warn("Get feature request failed")
943 return None, None, None
944 logging.debug(reply.show())
945 ports = reply.ports
946 else:
947 request = ofp.message.port_desc_stats_request()
948 # TODO do multipart correctly
949 reply, _ = controller.transact(request)
950 if reply is None:
951 logging.warn("Port desc stats request failed")
952 return None, None, None
953 logging.debug(reply.show())
954 ports = reply.entries
955
956 for port in ports:
957 if port.port_no == port_no:
958 return (port.hw_addr, port.config, port.advertised)
Charles Chanc85f1562018-01-18 15:44:29 -0800959
Rich Lane9a003812012-10-04 17:17:59 -0700960 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700961 return None, None, None
962
Rich Lane9a003812012-10-04 17:17:59 -0700963def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700964 """
965 Set the port configuration according the given parameters
966
967 Gets the switch feature configuration and updates one port's
968 configuration value according to config and mask
969 """
Rich Lane9a003812012-10-04 17:17:59 -0700970 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Rich Lane6dc865c2013-07-10 10:12:13 -0700971
972 hw_addr, _, _ = port_config_get(controller, port_no)
973
Rich Lanee717c6e2013-03-12 10:25:50 -0700974 mod = ofp.message.port_mod()
Dan Talayco92c99122010-06-03 13:53:18 -0700975 mod.port_no = port_no
Rich Lane6dc865c2013-07-10 10:12:13 -0700976 if hw_addr != None:
977 mod.hw_addr = hw_addr
Dan Talayco92c99122010-06-03 13:53:18 -0700978 mod.config = config
979 mod.mask = mask
Rich Lane6dc865c2013-07-10 10:12:13 -0700980 mod.advertise = 0 # No change
Rich Lane5c3151c2013-01-03 17:15:41 -0800981 controller.message_send(mod)
982 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700983
Rich Lane2014f9b2012-10-05 15:29:40 -0700984def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700985 """
986 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700987 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700988 @param pkt Expected packet; may be None if yes_ports is empty
989 @param yes_ports Set or list of ports that should recieve packet
990 @param no_ports Set or list of ports that should not receive packet
991 @param assert_if Object that implements assertXXX
Rich Lanee4b384d2013-09-13 14:33:40 -0700992
993 DEPRECATED in favor in verify_packets
Dan Talayco92c99122010-06-03 13:53:18 -0700994 """
Rich Lane91765672012-12-06 16:33:04 -0800995
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700996 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -0800997 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700998 exp_pkt_arg = pkt
999
Dan Talayco92c99122010-06-03 13:53:18 -07001000 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001001 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001002 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Wilson Ngc2c6b4e2015-03-04 17:30:20 -08001003 port_number=ofport, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001004 assert_if.assertTrue(rcv_pkt is not None,
Dan Talayco92c99122010-06-03 13:53:18 -07001005 "Did not receive pkt on " + str(ofport))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001006 if not oftest.dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane3c266832013-01-29 18:29:15 -08001007 logging.debug("Expected %s" % format_packet(pkt))
1008 logging.debug("Received %s" % format_packet(rcv_pkt))
Rich Lanecd97d3d2013-01-07 18:50:06 -08001009 assert_if.assertTrue(oftest.dataplane.match_exp_pkt(pkt, rcv_pkt),
Rich Lane3c266832013-01-29 18:29:15 -08001010 "Received packet does not match expected packet " +
Ken Chiang1bf01602012-04-04 10:48:23 -07001011 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -07001012 if len(no_ports) > 0:
Rich Lane57dfee72014-03-24 16:59:47 -07001013 time.sleep(oftest.ofutils.default_negative_timeout)
Dan Talayco92c99122010-06-03 13:53:18 -07001014 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -07001015 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -07001016 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lane91765672012-12-06 16:33:04 -08001017 port_number=ofport, timeout=0, exp_pkt=exp_pkt_arg)
Charles Chanc85f1562018-01-18 15:44:29 -08001018 assert_if.assertTrue(rcv_pkt is None,
Dan Talayco92c99122010-06-03 13:53:18 -07001019 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -07001020
1021
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001022def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -07001023 """
1024 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -07001025 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001026
1027 parent must implement dataplane, assertTrue and assertEqual
Rich Lanee4b384d2013-09-13 14:33:40 -07001028
1029 DEPRECATED in favor in verify_packets
Dan Talayco551befa2010-07-15 17:05:32 -07001030 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001031 exp_pkt_arg = None
Rich Lanecd97d3d2013-01-07 18:50:06 -08001032 if oftest.config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001033 exp_pkt_arg = exp_pkt
1034
Dan Talaycof6e76c02012-03-23 10:56:12 -07001035 if type(egr_ports) == type([]):
1036 egr_port_list = egr_ports
1037 else:
1038 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -07001039
Dan Talaycof6e76c02012-03-23 10:56:12 -07001040 # Expect a packet from each port on egr port list
1041 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001042 check_port = egr_port
Rich Lanee717c6e2013-03-12 10:25:50 -07001043 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -07001044 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001045 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001046 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -07001047
Dan Talaycof6e76c02012-03-23 10:56:12 -07001048 if rcv_pkt is None:
Charles Chanc85f1562018-01-18 15:44:29 -08001049 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -07001050 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -07001051
Dan Talaycof6e76c02012-03-23 10:56:12 -07001052 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001053 "Did not receive packet port " + str(check_port))
Charles Chanc85f1562018-01-18 15:44:29 -08001054 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001055 str(rcv_port))
1056
1057 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -07001058 logging.error("ERROR: Packet match failed.")
1059 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001060 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -07001061 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -07001062 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001063 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
1064 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001065 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -07001066 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -07001067
Dan Talayco551befa2010-07-15 17:05:32 -07001068def match_verify(parent, req_match, res_match):
1069 """
1070 Verify flow matches agree; if they disagree, report where
1071
1072 parent must implement assertEqual
1073 Use str() to ensure content is compared and not pointers
1074 """
1075
1076 parent.assertEqual(req_match.wildcards, res_match.wildcards,
1077 'Match failed: wildcards: ' + hex(req_match.wildcards) +
1078 " != " + hex(res_match.wildcards))
1079 parent.assertEqual(req_match.in_port, res_match.in_port,
1080 'Match failed: in_port: ' + str(req_match.in_port) +
1081 " != " + str(res_match.in_port))
Rich Laned0478ff2013-03-11 12:46:58 -07001082 parent.assertEqual(str(req_match.eth_src), str(res_match.eth_src),
1083 'Match failed: eth_src: ' + str(req_match.eth_src) +
1084 " != " + str(res_match.eth_src))
1085 parent.assertEqual(str(req_match.eth_dst), str(res_match.eth_dst),
1086 'Match failed: eth_dst: ' + str(req_match.eth_dst) +
1087 " != " + str(res_match.eth_dst))
1088 parent.assertEqual(req_match.vlan_vid, res_match.vlan_vid,
1089 'Match failed: vlan_vid: ' + str(req_match.vlan_vid) +
1090 " != " + str(res_match.vlan_vid))
1091 parent.assertEqual(req_match.vlan_pcp, res_match.vlan_pcp,
Charles Chanc85f1562018-01-18 15:44:29 -08001092 'Match failed: vlan_pcp: ' +
1093 str(req_match.vlan_pcp) + " != " +
Rich Laned0478ff2013-03-11 12:46:58 -07001094 str(res_match.vlan_pcp))
1095 parent.assertEqual(req_match.eth_type, res_match.eth_type,
1096 'Match failed: eth_type: ' + str(req_match.eth_type) +
1097 " != " + str(res_match.eth_type))
Dan Talayco551befa2010-07-15 17:05:32 -07001098
Rich Lanee717c6e2013-03-12 10:25:50 -07001099 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
Rich Laned0478ff2013-03-11 12:46:58 -07001100 and (req_match.eth_type == IP_ETHERTYPE)):
1101 parent.assertEqual(req_match.ip_dscp, res_match.ip_dscp,
1102 'Match failed: ip_dscp: ' + str(req_match.ip_dscp) +
1103 " != " + str(res_match.ip_dscp))
1104 parent.assertEqual(req_match.ip_proto, res_match.ip_proto,
1105 'Match failed: ip_proto: ' + str(req_match.ip_proto) +
1106 " != " + str(res_match.ip_proto))
1107 parent.assertEqual(req_match.ipv4_src, res_match.ipv4_src,
1108 'Match failed: ipv4_src: ' + str(req_match.ipv4_src) +
1109 " != " + str(res_match.ipv4_src))
1110 parent.assertEqual(req_match.ipv4_dst, res_match.ipv4_dst,
1111 'Match failed: ipv4_dst: ' + str(req_match.ipv4_dst) +
1112 " != " + str(res_match.ipv4_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001113
Rich Lanee717c6e2013-03-12 10:25:50 -07001114 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
Rich Laned0478ff2013-03-11 12:46:58 -07001115 and ((req_match.ip_proto == TCP_PROTOCOL)
1116 or (req_match.ip_proto == UDP_PROTOCOL))):
1117 parent.assertEqual(req_match.tcp_src, res_match.tcp_src,
Charles Chanc85f1562018-01-18 15:44:29 -08001118 'Match failed: tcp_src: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001119 str(req_match.tcp_src) +
1120 " != " + str(res_match.tcp_src))
1121 parent.assertEqual(req_match.tcp_dst, res_match.tcp_dst,
Charles Chanc85f1562018-01-18 15:44:29 -08001122 'Match failed: tcp_dst: ' +
Rich Laned0478ff2013-03-11 12:46:58 -07001123 str(req_match.tcp_dst) +
1124 " != " + str(res_match.tcp_dst))
Dan Talayco551befa2010-07-15 17:05:32 -07001125
Ed Swierk99a74de2012-08-22 06:40:54 -07001126def packet_to_flow_match(parent, packet):
Rich Lanef6883512013-03-11 17:00:09 -07001127 match = oftest.parse.packet_to_flow_match(packet)
Rich Laneab7476f2013-06-13 15:53:52 -07001128 if ofp.OFP_VERSION in [1, 2]:
1129 match.wildcards |= required_wildcards(parent)
1130 else:
1131 # TODO remove incompatible OXM entries
1132 pass
Ed Swierk99a74de2012-08-22 06:40:54 -07001133 return match
1134
1135def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001136 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001137 """
1138 Create a flow message
1139
Charles Chanc85f1562018-01-18 15:44:29 -08001140 Match on packet with given wildcards.
Dan Talayco551befa2010-07-15 17:05:32 -07001141 See flow_match_test for other parameter descriptoins
1142 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -07001143 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -07001144 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001145 """
Rich Lanef6883512013-03-11 17:00:09 -07001146 match = oftest.parse.packet_to_flow_match(pkt)
Dan Talayco551befa2010-07-15 17:05:32 -07001147 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -07001148 if wildcards is None:
1149 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -07001150 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001151 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -07001152 match.wildcards = wildcards
1153 match.in_port = ing_port
1154
Dan Talaycof6e76c02012-03-23 10:56:12 -07001155 if type(egr_ports) == type([]):
1156 egr_port_list = egr_ports
1157 else:
1158 egr_port_list = [egr_ports]
1159
Rich Lanee717c6e2013-03-12 10:25:50 -07001160 request = ofp.message.flow_add()
Dan Talayco551befa2010-07-15 17:05:32 -07001161 request.match = match
1162 request.buffer_id = 0xffffffff
1163 if check_expire:
Rich Lanee717c6e2013-03-12 10:25:50 -07001164 request.flags |= ofp.OFPFF_SEND_FLOW_REM
Dan Talayco551befa2010-07-15 17:05:32 -07001165 request.hard_timeout = 1
1166
Rich Lane400fb9b2013-10-10 17:20:54 -07001167 if ofp.OFP_VERSION == 1:
1168 actions = request.actions
1169 else:
1170 actions = []
1171 request.instructions.append(ofp.instruction.apply_actions(actions))
1172
Dan Talayco551befa2010-07-15 17:05:32 -07001173 if action_list is not None:
Rich Lane400fb9b2013-10-10 17:20:54 -07001174 actions.extend(action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001175
1176 # Set up output/enqueue action if directed
1177 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -07001178 parent.assertTrue(egr_ports is not None, "Egress port not set")
Rich Lanee717c6e2013-03-12 10:25:50 -07001179 act = ofp.action.enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001180 for egr_port in egr_port_list:
1181 act.port = egr_port
1182 act.queue_id = egr_queue
Rich Lane400fb9b2013-10-10 17:20:54 -07001183 actions.append(act)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001184 elif egr_ports is not None:
1185 for egr_port in egr_port_list:
Rich Lanee717c6e2013-03-12 10:25:50 -07001186 act = ofp.action.output()
Dan Talaycof6e76c02012-03-23 10:56:12 -07001187 act.port = egr_port
Rich Lane400fb9b2013-10-10 17:20:54 -07001188 actions.append(act)
Dan Talayco551befa2010-07-15 17:05:32 -07001189
Rich Lane9a003812012-10-04 17:17:59 -07001190 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -07001191
1192 return request
1193
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001194def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001195 """
1196 Install a flow mod message in the switch
1197
1198 @param parent Must implement controller, assertEqual, assertTrue
1199 @param request The request, all set to go
1200 @param clear_table If true, clear the flow table before installing
1201 """
Dan Talayco8a64e332012-03-28 14:53:20 -07001202
Rich Lane2014f9b2012-10-05 15:29:40 -07001203 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -07001204 if(clear_table_override != None):
1205 clear_table = clear_table_override
1206
Charles Chanc85f1562018-01-18 15:44:29 -08001207 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -07001208 logging.debug("Clear flow table")
Rich Lane32bf9482013-01-03 17:26:30 -08001209 delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001210
Rich Lane9a003812012-10-04 17:17:59 -07001211 logging.debug("Insert flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08001212 parent.controller.message_send(request)
Rich Lanee912d032012-12-22 14:28:33 -08001213
Rich Lane3a261d52013-01-03 17:45:08 -08001214 do_barrier(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -07001215
Ed Swierk99a74de2012-08-22 06:40:54 -07001216def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Rich Laned0478ff2013-03-11 12:46:58 -07001217 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001218 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -07001219 """
1220 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -07001221 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -07001222
1223 Run test with packet through switch from ing_port to egr_port
1224 See flow_match_test for parameter descriptions
1225 """
1226
Ed Swierk99a74de2012-08-22 06:40:54 -07001227 if wildcards is None:
1228 wildcards = required_wildcards(parent)
Charles Chanc85f1562018-01-18 15:44:29 -08001229 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001230 str(egr_ports))
Rich Laned0478ff2013-03-11 12:46:58 -07001231 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(vlan_vid))
Dan Talayco551befa2010-07-15 17:05:32 -07001232 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001233 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001234 if exp_pkt is None:
1235 exp_pkt = pkt
Dan Talayco551befa2010-07-15 17:05:32 -07001236
Charles Chanc85f1562018-01-18 15:44:29 -08001237 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001238 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -07001239 action_list=action_list)
1240
1241 flow_msg_install(parent, request)
1242
Charles Chanc85f1562018-01-18 15:44:29 -08001243 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -07001244 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -07001245 parent.dataplane.send(ing_port, str(pkt))
1246
Rich Lane8f45e2d2013-10-01 16:06:54 -07001247 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001248 verify_packets(parent, exp_pkt, exp_ports)
Dan Talayco551befa2010-07-15 17:05:32 -07001249
Rich Lane89725bb2012-12-03 16:23:27 -08001250def flow_match_test_pktout(parent, ing_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001251 vlan_vid=-1, pkt=None, exp_pkt=None,
Rich Lane89725bb2012-12-03 16:23:27 -08001252 action_list=None):
1253 """
1254 Packet-out test on single TCP packet
1255 @param egr_ports A single port or list of ports
1256
1257 Run test sending packet-out to egr_ports. The goal is to test the actions
1258 taken on the packet, not the matching which is of course irrelevant.
1259 See flow_match_test for parameter descriptions
1260 """
1261
1262 if pkt is None:
Rich Laned0478ff2013-03-11 12:46:58 -07001263 pkt = simple_tcp_packet(dl_vlan_enable=(vlan_vid >= 0), vlan_vid=vlan_vid)
Rich Lanec41fbec2013-10-02 00:27:59 -07001264 if exp_pkt is None:
1265 exp_pkt = pkt
Rich Lane89725bb2012-12-03 16:23:27 -08001266
Rich Lanee717c6e2013-03-12 10:25:50 -07001267 msg = ofp.message.packet_out()
Rich Lane89725bb2012-12-03 16:23:27 -08001268 msg.in_port = ing_port
Rich Laneea8c4722013-04-04 15:30:20 -07001269 msg.buffer_id = 0xffffffff
Rich Lane89725bb2012-12-03 16:23:27 -08001270 msg.data = str(pkt)
1271 if action_list is not None:
1272 for act in action_list:
Rich Lanec495d9e2013-03-08 17:43:36 -08001273 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001274
1275 # Set up output action
1276 if egr_ports is not None:
1277 for egr_port in egr_ports:
Rich Lanee717c6e2013-03-12 10:25:50 -07001278 act = ofp.action.output()
Rich Lane89725bb2012-12-03 16:23:27 -08001279 act.port = egr_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001280 msg.actions.append(act)
Rich Lane89725bb2012-12-03 16:23:27 -08001281
1282 logging.debug(msg.show())
Rich Lane5c3151c2013-01-03 17:15:41 -08001283 parent.controller.message_send(msg)
Rich Lane89725bb2012-12-03 16:23:27 -08001284
Rich Lane8f45e2d2013-10-01 16:06:54 -07001285 exp_ports = [ing_port if port == ofp.OFPP_IN_PORT else port for port in egr_ports]
Rich Lanee4b384d2013-09-13 14:33:40 -07001286 verify_packets(parent, exp_pkt, exp_ports)
Rich Lane89725bb2012-12-03 16:23:27 -08001287
Dan Talaycof6e76c02012-03-23 10:56:12 -07001288def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
1289 """
1290 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -07001291 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -07001292 @param of_ports List of OF port numbers
1293 @param how_many Number of ports to be added to the list
1294 @param exclude_list List of ports not to be used
1295 @returns An empty list if unable to find enough ports
1296 """
1297
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001298 if how_many == 0:
1299 return []
1300
Dan Talaycof6e76c02012-03-23 10:56:12 -07001301 count = 0
1302 egr_ports = []
Charles Chanc85f1562018-01-18 15:44:29 -08001303 for egr_idx in range(len(of_ports)):
Dan Talaycof6e76c02012-03-23 10:56:12 -07001304 if of_ports[egr_idx] not in exclude_list:
1305 egr_ports.append(of_ports[egr_idx])
1306 count += 1
1307 if count >= how_many:
1308 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -07001309 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001310 return []
Charles Chanc85f1562018-01-18 15:44:29 -08001311
1312def flow_match_test(parent, port_map, wildcards=None, vlan_vid=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -07001313 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001314 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -07001315 """
Rich Lane89725bb2012-12-03 16:23:27 -08001316 Run flow_match_test_port_pair on all port pairs and packet-out
Dan Talayco551befa2010-07-15 17:05:32 -07001317
1318 @param max_test If > 0 no more than this number of tests are executed.
1319 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -07001320 and logging
Dan Talayco551befa2010-07-15 17:05:32 -07001321 @param pkt If not None, use this packet for ingress
1322 @param wildcards For flow match entry
Rich Laned0478ff2013-03-11 12:46:58 -07001323 @param vlan_vid If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -07001324 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
1325 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -07001326 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -07001327 """
Ed Swierk99a74de2012-08-22 06:40:54 -07001328 if wildcards is None:
1329 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -07001330 of_ports = port_map.keys()
1331 of_ports.sort()
1332 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1333 test_count = 0
1334
Dan Talaycocfa172f2012-03-23 12:03:00 -07001335 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -07001336 egr_count = test_param_get('egr_count', default=2)
Charles Chanc85f1562018-01-18 15:44:29 -08001337
Dan Talayco551befa2010-07-15 17:05:32 -07001338 for ing_idx in range(len(of_ports)):
1339 ingress_port = of_ports[ing_idx]
Charles Chanc85f1562018-01-18 15:44:29 -08001340 egr_ports = get_egr_list(parent, of_ports, egr_count,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001341 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001342 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001343 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001344 if len(egr_ports) == 0:
1345 parent.assertTrue(0, "Failed to generate egress port list")
1346
Charles Chanc85f1562018-01-18 15:44:29 -08001347 flow_match_test_port_pair(parent, ingress_port, egr_ports,
1348 wildcards=wildcards, vlan_vid=vlan_vid,
Dan Talaycof6e76c02012-03-23 10:56:12 -07001349 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -07001350 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001351 test_count += 1
1352 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -07001353 logging.info("Ran " + str(test_count) + " tests; exiting")
Rich Lane89725bb2012-12-03 16:23:27 -08001354 break
1355
Ed Swierk38eea082013-01-02 19:46:20 -08001356 if not test_param_get('pktout_actions', default=True):
1357 return
Rich Lane89725bb2012-12-03 16:23:27 -08001358
1359 ingress_port = of_ports[0]
1360 egr_ports = get_egr_list(parent, of_ports, egr_count,
1361 exclude_list=[ingress_port])
1362 if ing_port:
Rich Lanee717c6e2013-03-12 10:25:50 -07001363 egr_ports.append(ofp.OFPP_IN_PORT)
Rich Lane89725bb2012-12-03 16:23:27 -08001364 flow_match_test_pktout(parent, ingress_port, egr_ports,
Rich Laned0478ff2013-03-11 12:46:58 -07001365 vlan_vid=vlan_vid,
Rich Lane89725bb2012-12-03 16:23:27 -08001366 pkt=pkt, exp_pkt=exp_pkt,
1367 action_list=action_list)
Dan Talayco551befa2010-07-15 17:05:32 -07001368
Rich Lane2014f9b2012-10-05 15:29:40 -07001369def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001370 """
1371 Return value passed via test-params if present
1372
Dan Talayco4b2bee62010-07-20 14:10:05 -07001373 @param key The lookup key
1374 @param default Default value to use if not found
1375
1376 If the pair 'key=val' appeared in the string passed to --test-params
1377 on the command line, return val (as interpreted by exec). Otherwise
1378 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -07001379
Charles Chanc85f1562018-01-18 15:44:29 -08001380 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
Dan Talaycof6e76c02012-03-23 10:56:12 -07001381 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -07001382 """
1383 try:
Rich Lanecd97d3d2013-01-07 18:50:06 -08001384 exec oftest.config["test_params"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001385 except:
1386 return default
1387
Dan Talayco4b2bee62010-07-20 14:10:05 -07001388 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001389 return eval(str(key))
Dan Talayco4b2bee62010-07-20 14:10:05 -07001390 except:
1391 return default
1392
1393def action_generate(parent, field_to_mod, mod_field_vals):
1394 """
1395 Create an action to modify the field indicated in field_to_mod
1396
1397 @param parent Must implement, assertTrue
1398 @param field_to_mod The field to modify as a string name
1399 @param mod_field_vals Hash of values to use for modified values
1400 """
1401
1402 act = None
1403
1404 if field_to_mod in ['pktlen']:
1405 return None
1406
Rich Laned0478ff2013-03-11 12:46:58 -07001407 if field_to_mod == 'eth_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001408 act = ofp.action.set_dl_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001409 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
Rich Laned0478ff2013-03-11 12:46:58 -07001410 elif field_to_mod == 'eth_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001411 act = ofp.action.set_dl_src()
Rich Lanef6883512013-03-11 17:00:09 -07001412 act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001413 elif field_to_mod == 'dl_vlan_enable':
1414 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
Rich Lanee717c6e2013-03-12 10:25:50 -07001415 act = ofp.action.strip_vlan()
Rich Laned0478ff2013-03-11 12:46:58 -07001416 # Add VLAN tag is handled by vlan_vid field
Dan Talayco4b2bee62010-07-20 14:10:05 -07001417 # Will return None in this case
Rich Laned0478ff2013-03-11 12:46:58 -07001418 elif field_to_mod == 'vlan_vid':
Rich Lanee717c6e2013-03-12 10:25:50 -07001419 act = ofp.action.set_vlan_vid()
Rich Laned0478ff2013-03-11 12:46:58 -07001420 act.vlan_vid = mod_field_vals['vlan_vid']
1421 elif field_to_mod == 'vlan_pcp':
Rich Lanee717c6e2013-03-12 10:25:50 -07001422 act = ofp.action.set_vlan_pcp()
Rich Laned0478ff2013-03-11 12:46:58 -07001423 act.vlan_pcp = mod_field_vals['vlan_pcp']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001424 elif field_to_mod == 'ip_src':
Rich Lanee717c6e2013-03-12 10:25:50 -07001425 act = ofp.action.set_nw_src()
Rich Lanef6883512013-03-11 17:00:09 -07001426 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001427 elif field_to_mod == 'ip_dst':
Rich Lanee717c6e2013-03-12 10:25:50 -07001428 act = ofp.action.set_nw_dst()
Rich Lanef6883512013-03-11 17:00:09 -07001429 act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
Dan Talayco4b2bee62010-07-20 14:10:05 -07001430 elif field_to_mod == 'ip_tos':
Rich Lanee717c6e2013-03-12 10:25:50 -07001431 act = ofp.action.set_nw_tos()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001432 act.nw_tos = mod_field_vals['ip_tos']
1433 elif field_to_mod == 'tcp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001434 act = ofp.action.set_tp_src()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001435 act.tp_port = mod_field_vals['tcp_sport']
1436 elif field_to_mod == 'tcp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001437 act = ofp.action.set_tp_dst()
Dan Talayco4b2bee62010-07-20 14:10:05 -07001438 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -07001439 elif field_to_mod == 'udp_sport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001440 act = ofp.action.set_tp_src()
Rich Lane110e0e32012-10-26 16:21:46 -07001441 act.tp_port = mod_field_vals['udp_sport']
1442 elif field_to_mod == 'udp_dport':
Rich Lanee717c6e2013-03-12 10:25:50 -07001443 act = ofp.action.set_tp_dst()
Rich Lane110e0e32012-10-26 16:21:46 -07001444 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -07001445 else:
1446 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
1447
1448 return act
1449
Charles Chanc85f1562018-01-18 15:44:29 -08001450def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -07001451 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001452 """
1453 Set up the ingress and expected packet and action list for a test
1454
Rich Lane2014f9b2012-10-05 15:29:40 -07001455 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -07001456 @param start_field_values Field values to use for ingress packet (optional)
1457 @param mod_field_values Field values to use for modified packet (optional)
1458 @param mod_fields The list of fields to be modified by the switch in the test.
1459 @params check_test_params If True, will check the parameters vid, add_vlan
1460 and strip_vlan from the command line.
1461
1462 Returns a triple: pkt-to-send, expected-pkt, action-list
1463 """
1464
1465 new_actions = []
1466
Dan Talayco4b2bee62010-07-20 14:10:05 -07001467 base_pkt_params = {}
1468 base_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001469 base_pkt_params['eth_dst'] = '00:DE:F0:12:34:56'
1470 base_pkt_params['eth_src'] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001471 base_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001472 base_pkt_params['vlan_vid'] = 2
1473 base_pkt_params['vlan_pcp'] = 0
Dan Talayco4b2bee62010-07-20 14:10:05 -07001474 base_pkt_params['ip_src'] = '192.168.0.1'
1475 base_pkt_params['ip_dst'] = '192.168.0.2'
1476 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -07001477 if tp == "tcp":
1478 base_pkt_params['tcp_sport'] = 1234
1479 base_pkt_params['tcp_dport'] = 80
1480 elif tp == "udp":
1481 base_pkt_params['udp_sport'] = 1234
1482 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -07001483 for keyname in start_field_vals.keys():
1484 base_pkt_params[keyname] = start_field_vals[keyname]
1485
1486 mod_pkt_params = {}
1487 mod_pkt_params['pktlen'] = 100
Rich Laned0478ff2013-03-11 12:46:58 -07001488 mod_pkt_params['eth_dst'] = '00:21:0F:ED:CB:A9'
1489 mod_pkt_params['eth_src'] = '00:ED:CB:A9:87:65'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001490 mod_pkt_params['dl_vlan_enable'] = False
Rich Laned0478ff2013-03-11 12:46:58 -07001491 mod_pkt_params['vlan_vid'] = 3
1492 mod_pkt_params['vlan_pcp'] = 7
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493 mod_pkt_params['ip_src'] = '10.20.30.40'
1494 mod_pkt_params['ip_dst'] = '50.60.70.80'
1495 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -07001496 if tp == "tcp":
1497 mod_pkt_params['tcp_sport'] = 4321
1498 mod_pkt_params['tcp_dport'] = 8765
1499 elif tp == "udp":
1500 mod_pkt_params['udp_sport'] = 4321
1501 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502 for keyname in mod_field_vals.keys():
1503 mod_pkt_params[keyname] = mod_field_vals[keyname]
1504
1505 # Check for test param modifications
1506 strip = False
1507 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -07001508 add_vlan = test_param_get('add_vlan')
1509 strip_vlan = test_param_get('strip_vlan')
1510 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001511
1512 if add_vlan and strip_vlan:
1513 parent.assertTrue(0, "Add and strip VLAN both specified")
1514
1515 if vid:
1516 base_pkt_params['dl_vlan_enable'] = True
Rich Laned0478ff2013-03-11 12:46:58 -07001517 base_pkt_params['vlan_vid'] = vid
1518 if 'vlan_vid' in mod_fields:
1519 mod_pkt_params['vlan_vid'] = vid + 1
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520
1521 if add_vlan:
1522 base_pkt_params['dl_vlan_enable'] = False
1523 mod_pkt_params['dl_vlan_enable'] = True
1524 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
1525 mod_fields.append('pktlen')
1526 mod_fields.append('dl_vlan_enable')
Rich Laned0478ff2013-03-11 12:46:58 -07001527 if 'vlan_vid' not in mod_fields:
1528 mod_fields.append('vlan_vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -07001529 elif strip_vlan:
1530 base_pkt_params['dl_vlan_enable'] = True
1531 mod_pkt_params['dl_vlan_enable'] = False
1532 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
1533 mod_fields.append('dl_vlan_enable')
1534 mod_fields.append('pktlen')
1535
Rich Lane110e0e32012-10-26 16:21:46 -07001536 if tp == "tcp":
1537 packet_builder = simple_tcp_packet
1538 elif tp == "udp":
1539 packet_builder = simple_udp_packet
1540 else:
1541 raise NotImplementedError("unknown transport protocol %s" % tp)
1542
Dan Talayco4b2bee62010-07-20 14:10:05 -07001543 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -07001544 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001545
1546 # Build the expected packet, modifying the indicated fields
1547 for item in mod_fields:
1548 base_pkt_params[item] = mod_pkt_params[item]
1549 act = action_generate(parent, item, mod_pkt_params)
1550 if act:
1551 new_actions.append(act)
1552
Rich Lane110e0e32012-10-26 16:21:46 -07001553 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001554
1555 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -07001556
1557# Generate a simple "drop" flow mod
1558# If in_band is true, then only drop from first test port
1559def flow_mod_gen(port_map, in_band):
Rich Lanee717c6e2013-03-12 10:25:50 -07001560 request = ofp.message.flow_add()
1561 request.match.wildcards = ofp.OFPFW_ALL
Dan Talayco677c0b72011-08-23 22:53:38 -07001562 if in_band:
Rich Lanee717c6e2013-03-12 10:25:50 -07001563 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
Dan Talayco677c0b72011-08-23 22:53:38 -07001564 for of_port, ifname in port_map.items(): # Grab first port
1565 break
1566 request.match.in_port = of_port
1567 request.buffer_id = 0xffffffff
1568 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -07001569
1570def skip_message_emit(parent, s):
1571 """
1572 Print out a 'skipped' message to stderr
1573
1574 @param s The string to print out to the log file
Dan Talaycoba3745c2010-07-21 21:51:08 -07001575 """
1576 global skipped_test_count
1577
1578 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -07001579 logging.info("Skipping: " + s)
Dan Talayco2940fdd2013-02-06 15:01:35 -08001580 if oftest.config["debug"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -07001581 sys.stderr.write("(skipped) ")
1582 else:
1583 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -07001584
Dan Talayco8a64e332012-03-28 14:53:20 -07001585
1586def all_stats_get(parent):
1587 """
1588 Get the aggregate stats for all flows in the table
1589 @param parent Test instance with controller connection and assert
Charles Chanc85f1562018-01-18 15:44:29 -08001590 @returns dict with keys flows, packets, bytes, active (flows),
Dan Talayco8a64e332012-03-28 14:53:20 -07001591 lookups, matched
1592 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001593 stat_req = ofp.message.aggregate_stats_request()
1594 stat_req.match = ofp.match()
1595 stat_req.match.wildcards = ofp.OFPFW_ALL
Dan Talayco8a64e332012-03-28 14:53:20 -07001596 stat_req.table_id = 0xff
Rich Lanee717c6e2013-03-12 10:25:50 -07001597 stat_req.out_port = ofp.OFPP_NONE
Dan Talayco8a64e332012-03-28 14:53:20 -07001598
1599 rv = {}
1600
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001601 (reply, pkt) = parent.controller.transact(stat_req)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001602 parent.assertTrue(len(reply.entries) == 1, "Did not receive flow stats reply")
Dan Talayco8a64e332012-03-28 14:53:20 -07001603
Rich Lane5fd6faf2013-03-11 13:30:20 -07001604 for obj in reply.entries:
Charles Chanc85f1562018-01-18 15:44:29 -08001605 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
Dan Talayco8a64e332012-03-28 14:53:20 -07001606 obj.packet_count, obj.byte_count)
1607 break
1608
Rich Lanee717c6e2013-03-12 10:25:50 -07001609 request = ofp.message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -07001610 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -07001611
Charles Chanc85f1562018-01-18 15:44:29 -08001612
Dan Talayco8a64e332012-03-28 14:53:20 -07001613 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
Rich Lane5fd6faf2013-03-11 13:30:20 -07001614 for obj in reply.entries:
Dan Talayco8a64e332012-03-28 14:53:20 -07001615 rv["active"] += obj.active_count
1616 rv["lookups"] += obj.lookup_count
1617 rv["matched"] += obj.matched_count
1618
1619 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -07001620
Rich Lane7744e112013-01-11 17:23:57 -08001621_import_blacklist.add('FILTER')
Charles Chanc85f1562018-01-18 15:44:29 -08001622FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
Dan Talayco2baf8b52012-03-30 09:55:42 -07001623 for x in range(256)])
1624
1625def hex_dump_buffer(src, length=16):
1626 """
1627 Convert src to a hex dump string and return the string
1628 @param src The source buffer
1629 @param length The number of bytes shown in each line
1630 @returns A string showing the hex dump
1631 """
Dan Talaycoc516fa02012-04-12 22:28:43 -07001632 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -07001633 for i in xrange(0, len(src), length):
1634 chars = src[i:i+length]
1635 hex = ' '.join(["%02x" % ord(x) for x in chars])
1636 printable = ''.join(["%s" % ((ord(x) <= 127 and
1637 FILTER[ord(x)]) or '.') for x in chars])
1638 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
1639 return ''.join(result)
1640
1641def format_packet(pkt):
Charles Chanc85f1562018-01-18 15:44:29 -08001642 return "Packet length %d \n%s" % (len(str(pkt)),
Dan Talayco2baf8b52012-03-30 09:55:42 -07001643 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -07001644
1645def inspect_packet(pkt):
1646 """
1647 Wrapper around scapy's show() method.
1648 @returns A string showing the dissected packet.
1649 """
1650 from cStringIO import StringIO
1651 out = None
1652 backup = sys.stdout
1653 try:
Rich Lanefdec0fb2013-08-09 18:01:05 -07001654 tmp = StringIO()
1655 sys.stdout = tmp
Rich Lane5d7e89a2012-10-26 16:43:13 -07001656 pkt.show2()
Rich Lanefdec0fb2013-08-09 18:01:05 -07001657 out = tmp.getvalue()
1658 tmp.close()
Rich Lane5d7e89a2012-10-26 16:43:13 -07001659 finally:
1660 sys.stdout = backup
1661 return out
Rich Lane0a4f6372013-01-02 14:40:22 -08001662
1663def nonstandard(cls):
1664 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001665 Testcase decorator that marks the test as being non-standard.
1666 These tests are not automatically added to the "standard" group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001667 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001668 cls._nonstandard = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001669 return cls
1670
1671def disabled(cls):
1672 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001673 Testcase decorator that marks the test as being disabled.
1674 These tests are not automatically added to the "standard" group or
1675 their module's group.
Rich Lane0a4f6372013-01-02 14:40:22 -08001676 """
Rich Lanecc45b8e2013-01-02 15:55:02 -08001677 cls._disabled = True
Rich Lane0a4f6372013-01-02 14:40:22 -08001678 return cls
Rich Lane97e99652013-01-02 17:23:20 -08001679
1680def group(name):
1681 """
1682 Testcase decorator that adds the test to a group.
1683 """
1684 def fn(cls):
1685 if not hasattr(cls, "_groups"):
1686 cls._groups = []
1687 cls._groups.append(name)
1688 return cls
1689 return fn
Rich Lane5a9a1922013-01-11 14:29:30 -08001690
1691def version(ver):
1692 """
1693 Testcase decorator that specifies which versions of OpenFlow the test
1694 supports. The default is 1.0+. This decorator may only be used once.
1695
1696 Supported syntax:
1697 1.0 -> 1.0
1698 1.0,1.2,1.3 -> 1.0, 1.2, 1.3
1699 1.0+ -> 1.0, 1.1, 1.2, 1.3
1700 """
1701 versions = parse_version(ver)
1702 def fn(cls):
1703 cls._versions = versions
1704 return cls
1705 return fn
1706
1707def parse_version(ver):
1708 allowed_versions = ["1.0", "1.1", "1.2", "1.3"]
1709 if re.match("^1\.\d+$", ver):
1710 versions = set([ver])
1711 elif re.match("^(1\.\d+)\+$", ver):
1712 if not ver[:-1] in allowed_versions:
1713 raise ValueError("invalid OpenFlow version %s" % ver[:-1])
1714 versions = set()
1715 if ver != "1.1+": versions.add("1.0")
1716 if ver != "1.2+": versions.add("1.1")
1717 if ver != "1.3+": versions.add("1.2")
1718 versions.add("1.3")
1719 else:
1720 versions = set(ver.split(','))
1721
1722 for version in versions:
1723 if not version in allowed_versions:
1724 raise ValueError("invalid OpenFlow version %s" % version)
1725
1726 return versions
1727
1728assert(parse_version("1.0") == set(["1.0"]))
1729assert(parse_version("1.0,1.2,1.3") == set(["1.0", "1.2", "1.3"]))
1730assert(parse_version("1.0+") == set(["1.0", "1.1", "1.2", "1.3"]))
Rich Lane7744e112013-01-11 17:23:57 -08001731
Rich Laneae3428c2013-03-07 14:37:42 -08001732def get_stats(test, req):
1733 """
1734 Retrieve a list of stats entries. Handles OFPSF_REPLY_MORE.
1735 """
Rich Lane609194f2013-10-21 06:17:37 -07001736 msgtype = ofp.OFPT_STATS_REPLY
1737 more_flag = ofp.OFPSF_REPLY_MORE
Rich Laneae3428c2013-03-07 14:37:42 -08001738 stats = []
1739 reply, _ = test.controller.transact(req)
1740 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane34c68d52013-10-11 10:38:21 -07001741 test.assertEquals(reply.type, msgtype, "Response had unexpected message type")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001742 stats.extend(reply.entries)
Rich Lanebd56ed62013-07-10 15:49:44 -07001743 while reply.flags & more_flag != 0:
Rich Lane34c68d52013-10-11 10:38:21 -07001744 reply, pkt = test.controller.poll(exp_msg=msgtype)
Rich Laneae3428c2013-03-07 14:37:42 -08001745 test.assertTrue(reply is not None, "No response to stats request")
Rich Lane5fd6faf2013-03-11 13:30:20 -07001746 stats.extend(reply.entries)
Rich Laneae3428c2013-03-07 14:37:42 -08001747 return stats
1748
Rich Lanebd56ed62013-07-10 15:49:44 -07001749def get_flow_stats(test, match, table_id=None,
1750 out_port=None, out_group=None,
1751 cookie=0, cookie_mask=0):
Rich Laneae3428c2013-03-07 14:37:42 -08001752 """
1753 Retrieve a list of flow stats entries.
1754 """
Rich Lanebd56ed62013-07-10 15:49:44 -07001755
1756 if table_id == None:
1757 if ofp.OFP_VERSION <= 2:
1758 table_id = 0xff
1759 else:
1760 table_id = ofp.OFPTT_ALL
1761
Rich Lanef3bc48c2013-05-03 17:39:35 -07001762 if out_port == None:
Rich Lanebd56ed62013-07-10 15:49:44 -07001763 if ofp.OFP_VERSION == 1:
1764 out_port = ofp.OFPP_NONE
1765 else:
1766 out_port = ofp.OFPP_ANY
1767
1768 if out_group == None:
1769 if ofp.OFP_VERSION > 1:
1770 out_group = ofp.OFPP_ANY
1771
Rich Lanee717c6e2013-03-12 10:25:50 -07001772 req = ofp.message.flow_stats_request(match=match,
Rich Lanebd56ed62013-07-10 15:49:44 -07001773 table_id=table_id,
1774 out_port=out_port)
1775 if ofp.OFP_VERSION > 1:
1776 req.out_group = out_group
1777 req.cookie = cookie
1778 req.cookie_mask = cookie_mask
1779
Rich Laneae3428c2013-03-07 14:37:42 -08001780 return get_stats(test, req)
1781
Rich Lane968b6192013-03-07 15:34:43 -08001782def get_port_stats(test, port_no):
1783 """
1784 Retrieve a list of port stats entries.
1785 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001786 req = ofp.message.port_stats_request(port_no=port_no)
Rich Lane968b6192013-03-07 15:34:43 -08001787 return get_stats(test, req)
1788
Rich Lane6a334922013-03-07 16:14:52 -08001789def get_queue_stats(test, port_no, queue_id):
1790 """
1791 Retrieve a list of queue stats entries.
1792 """
Rich Lanee717c6e2013-03-12 10:25:50 -07001793 req = ofp.message.queue_stats_request(port_no=port_no, queue_id=queue_id)
Rich Lane6a334922013-03-07 16:14:52 -08001794 return get_stats(test, req)
1795
Rich Laneae3428c2013-03-07 14:37:42 -08001796def verify_flow_stats(test, match, table_id=0xff,
Rich Laneae3428c2013-03-07 14:37:42 -08001797 initial=[],
1798 pkts=None, bytes=None):
1799 """
1800 Verify that flow stats changed as expected.
1801
1802 Optionally takes an 'initial' list of stats entries, as returned by
1803 get_flow_stats(). If 'initial' is not given the counters are assumed to
1804 begin at 0.
1805 """
Rich Lanef3bc48c2013-05-03 17:39:35 -07001806
Rich Laneae3428c2013-03-07 14:37:42 -08001807 def accumulate(stats):
1808 pkts_acc = bytes_acc = 0
1809 for stat in stats:
1810 pkts_acc += stat.packet_count
1811 bytes_acc += stat.byte_count
1812 return (pkts_acc, bytes_acc)
1813
1814 pkts_before, bytes_before = accumulate(initial)
1815
1816 # Wait 10s for counters to update
1817 pkt_diff = byte_diff = None
1818 for i in range(0, 100):
Rich Lane61edad52014-03-28 16:25:08 -07001819 stats = get_flow_stats(test, match, table_id=table_id)
Rich Laneae3428c2013-03-07 14:37:42 -08001820 pkts_after, bytes_after = accumulate(stats)
1821 pkt_diff = pkts_after - pkts_before
1822 byte_diff = bytes_after - bytes_before
1823 if (pkts == None or pkt_diff >= pkts) and \
1824 (bytes == None or byte_diff >= bytes):
1825 break
Dan Talayco53724732013-03-08 23:54:02 -08001826 time.sleep(0.1)
Rich Laneae3428c2013-03-07 14:37:42 -08001827
1828 if pkts != None:
1829 test.assertEquals(pkt_diff, pkts, "Flow packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1830
1831 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001832 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1833 "Flow byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001834
Rich Lane968b6192013-03-07 15:34:43 -08001835def verify_port_stats(test, port,
1836 initial=[],
1837 tx_pkts=None, rx_pkts=None,
1838 tx_bytes=None, rx_bytes=None):
1839 """
1840 Verify that port stats changed as expected.
1841
1842 Optionally takes an 'initial' list of stats entries, as returned by
1843 get_port_stats(). If 'initial' is not given the counters are assumed to
1844 begin at 0.
1845 """
1846 def accumulate(stats):
1847 tx_pkts_acc = rx_pkts_acc = tx_bytes_acc = rx_bytes_acc = 0
1848 for stat in stats:
1849 tx_pkts_acc += stat.tx_packets
1850 rx_pkts_acc += stat.rx_packets
1851 tx_bytes_acc += stat.tx_bytes
1852 rx_bytes_acc += stat.rx_bytes
1853 return (tx_pkts_acc, rx_pkts_acc, tx_bytes_acc, rx_bytes_acc)
1854
1855 tx_pkts_before, rx_pkts_before, \
1856 tx_bytes_before, rx_bytes_before = accumulate(initial)
1857
1858 # Wait 10s for counters to update
1859 for i in range(0, 100):
1860 stats = get_port_stats(test, port)
1861 tx_pkts_after, rx_pkts_after, \
1862 tx_bytes_after, rx_bytes_after = accumulate(stats)
1863 tx_pkts_diff = tx_pkts_after - tx_pkts_before
1864 rx_pkts_diff = rx_pkts_after - rx_pkts_before
1865 tx_bytes_diff = tx_bytes_after - tx_bytes_before
1866 rx_bytes_diff = rx_bytes_after - rx_bytes_before
Rich Lane3a208f82015-04-10 12:37:57 -07001867 if (tx_pkts == None or tx_pkts <= tx_pkts_diff) and \
1868 (rx_pkts == None or rx_pkts <= rx_pkts_diff) and \
Rich Lane53b96812013-03-07 16:54:50 -08001869 (tx_bytes == None or tx_bytes <= tx_bytes_diff) and \
1870 (rx_bytes == None or rx_bytes <= rx_bytes_diff):
Rich Lane968b6192013-03-07 15:34:43 -08001871 break
1872 time.sleep(0.1)
1873
1874 if (tx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001875 test.assertGreaterEqual(tx_pkts_diff, tx_pkts,
1876 "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 -08001877 if (rx_pkts != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001878 test.assertGreaterEqual(rx_pkts_diff, rx_pkts,
1879 "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 -08001880 if (tx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001881 test.assertGreaterEqual(tx_bytes_diff, tx_bytes,
1882 "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 -08001883 if (rx_bytes != None):
Rich Lane3a208f82015-04-10 12:37:57 -07001884 test.assertGreaterEqual(rx_bytes_diff, rx_bytes,
1885 "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 -08001886
Rich Lane6a334922013-03-07 16:14:52 -08001887def verify_queue_stats(test, port_no, queue_id,
1888 initial=[],
1889 pkts=None, bytes=None):
1890 """
1891 Verify that queue stats changed as expected.
1892
1893 Optionally takes an 'initial' list of stats entries, as returned by
1894 get_queue_stats(). If 'initial' is not given the counters are assumed to
1895 begin at 0.
1896 """
1897 def accumulate(stats):
1898 pkts_acc = bytes_acc = 0
1899 for stat in stats:
1900 pkts_acc += stat.tx_packets
1901 bytes_acc += stat.tx_bytes
1902 return (pkts_acc, bytes_acc)
1903
1904 pkts_before, bytes_before = accumulate(initial)
1905
1906 # Wait 10s for counters to update
1907 pkt_diff = byte_diff = None
1908 for i in range(0, 100):
1909 stats = get_queue_stats(test, port_no, queue_id)
1910 pkts_after, bytes_after = accumulate(stats)
1911 pkt_diff = pkts_after - pkts_before
1912 byte_diff = bytes_after - bytes_before
1913 if (pkts == None or pkt_diff >= pkts) and \
1914 (bytes == None or byte_diff >= bytes):
1915 break
Dan Talayco53724732013-03-08 23:54:02 -08001916 time.sleep(0.1)
Rich Lane6a334922013-03-07 16:14:52 -08001917
1918 if pkts != None:
1919 test.assertEquals(pkt_diff, pkts, "Queue packet counter not updated properly (expected increase of %d, got increase of %d)" % (pkts, pkt_diff))
1920
1921 if bytes != None:
Rich Lane53b96812013-03-07 16:54:50 -08001922 test.assertTrue(byte_diff >= bytes and byte_diff <= bytes*1.1,
1923 "Queue byte counter not updated properly (expected increase of %d, got increase of %d)" % (bytes, byte_diff))
Rich Laneae3428c2013-03-07 14:37:42 -08001924
Rich Lane4c504f32013-06-07 17:24:14 -07001925def packet_in_match(msg, data, in_port=None, reason=None):
1926 """
1927 Check whether the packet_in message 'msg' has fields matching 'data',
1928 'in_port', and 'reason'.
1929
1930 This function handles truncated packet_in data. The 'in_port' and 'reason'
1931 parameters are optional.
1932
1933 @param msg packet_in message
1934 @param data Expected packet_in data
1935 @param in_port Expected packet_in in_port, or None
1936 @param reason Expected packet_in reason, or None
1937 """
1938
Rich Lanec0d26dd2013-07-10 12:46:03 -07001939 if ofp.OFP_VERSION <= 2:
1940 pkt_in_port = msg.in_port
1941 else:
1942 oxms = { type(oxm): oxm for oxm in msg.match.oxm_list }
1943 if ofp.oxm.in_port in oxms:
1944 pkt_in_port = oxms[ofp.oxm.in_port].value
1945 else:
1946 logging.warn("Missing in_port in packet-in message")
1947 pkt_in_port = None
1948
1949 if in_port != None and in_port != pkt_in_port:
Rich Lane9f2f17e2013-09-13 13:19:37 -07001950 logging.debug("Incorrect packet_in in_port (expected %d, received %d)", in_port, pkt_in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07001951 return False
1952
Rich Lanec0d26dd2013-07-10 12:46:03 -07001953 if reason != None and reason != msg.reason:
Rich Lane4c504f32013-06-07 17:24:14 -07001954 logging.debug("Incorrect packet_in reason (expected %d, received %d)", reason, msg.reason)
1955 return False
1956
1957 # Check that one of the packets is a prefix of the other.
1958 # The received packet may be either truncated or padded, but not both.
1959 # (Some of the padding may be truncated but that's irrelevant). We
1960 # need to check that the smaller packet is a prefix of the larger one.
1961 # Note that this check succeeds if the switch sends a zero-length
1962 # packet-in.
1963 compare_len = min(len(msg.data), len(data))
1964 if data[:compare_len] != msg.data[:compare_len]:
1965 logging.debug("Incorrect packet_in data")
1966 logging.debug("Expected %s" % format_packet(data[:compare_len]))
1967 logging.debug("Received %s" % format_packet(msg.data[:compare_len]))
1968 return False
1969
1970 return True
1971
1972def verify_packet_in(test, data, in_port, reason, controller=None):
1973 """
1974 Assert that the controller receives a packet_in message matching data 'data'
1975 from port 'in_port' with reason 'reason'. Does not trigger the packet_in
1976 itself, that's up to the test case.
1977
1978 @param test Instance of base_tests.SimpleProtocol
1979 @param pkt String to expect as the packet_in data
1980 @param in_port OpenFlow port number to expect as the packet_in in_port
1981 @param reason One of OFPR_* to expect as the packet_in reason
1982 @param controller Controller instance, defaults to test.controller
1983 @returns The received packet-in message
1984 """
1985
1986 if controller == None:
1987 controller = test.controller
1988
1989 end_time = time.time() + oftest.ofutils.default_timeout
1990
1991 while True:
1992 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, end_time - time.time())
1993 if not msg:
1994 # Timeout
1995 break
1996 elif packet_in_match(msg, data, in_port, reason):
1997 # Found a matching message
1998 break
1999
Kiran Poola58c5c042014-05-15 15:11:06 -07002000 test.assertTrue(msg is not None, 'Packet in message not received on port %r' % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002001 return msg
2002
2003def verify_no_packet_in(test, data, in_port, controller=None):
2004 """
2005 Assert that the controller does not receive a packet_in message matching
2006 data 'data' from port 'in_port'.
2007
2008 @param test Instance of base_tests.SimpleProtocol
2009 @param pkt String to expect as the packet_in data
2010 @param in_port OpenFlow port number to expect as the packet_in in_port
2011 @param controller Controller instance, defaults to test.controller
2012 """
2013
2014 if controller == None:
2015 controller = test.controller
2016
2017 # Negative test, need to wait a short amount of time before checking we
2018 # didn't receive the message.
Rich Lane48f6aed2014-03-23 15:51:02 -07002019 time.sleep(oftest.ofutils.default_negative_timeout)
Rich Lane4c504f32013-06-07 17:24:14 -07002020
2021 # Check every packet_in queued in the controller
2022 while True:
2023 msg, _ = controller.poll(ofp.OFPT_PACKET_IN, timeout=0)
2024 if msg == None:
2025 # No more queued packet_in messages
2026 break
2027 elif packet_in_match(msg, data, in_port, None):
2028 # Found a matching message
2029 break
2030
Rich Lane82c882d2013-08-09 17:13:52 -07002031 if in_port == None:
2032 test.assertTrue(msg == None, "Did not expect a packet-in message on any port")
2033 else:
2034 test.assertTrue(msg == None, "Did not expect a packet-in message on port %d" % in_port)
Rich Lane4c504f32013-06-07 17:24:14 -07002035
Rich Lane045db072013-08-06 13:16:30 -07002036def openflow_ports(num=None):
2037 """
2038 Return a list of 'num' OpenFlow port numbers
2039
2040 If 'num' is None, return all available ports. Otherwise, limit the length
2041 of the result to 'num' and raise an exception if not enough ports are
2042 available.
2043 """
2044 ports = sorted(oftest.config["port_map"].keys())
2045 if num != None and len(ports) < num:
2046 raise Exception("test requires %d ports but only %d are available" % (num, len(ports)))
2047 return ports[:num]
2048
Rich Lanee4b384d2013-09-13 14:33:40 -07002049def verify_packet(test, pkt, ofport):
2050 """
2051 Check that an expected packet is received
2052 """
2053 logging.debug("Checking for pkt on port %r", ofport)
2054 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(port_number=ofport, exp_pkt=str(pkt))
2055 test.assertTrue(rcv_pkt != None, "Did not receive pkt on %r" % ofport)
macauley17cd60d2015-07-27 17:41:18 +08002056 return (rcv_port, rcv_pkt, pkt_time)
Charles Chanc85f1562018-01-18 15:44:29 -08002057
Rich Lanee4b384d2013-09-13 14:33:40 -07002058def verify_no_packet(test, pkt, ofport):
2059 """
2060 Check that a particular packet is not received
2061 """
2062 logging.debug("Negative check for pkt on port %r", ofport)
Rich Lane48f6aed2014-03-23 15:51:02 -07002063 (rcv_port, rcv_pkt, pkt_time) = \
2064 test.dataplane.poll(
2065 port_number=ofport, exp_pkt=str(pkt),
2066 timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002067 test.assertTrue(rcv_pkt == None, "Received packet on %r" % ofport)
2068
2069def verify_no_other_packets(test):
2070 """
2071 Check that no unexpected packets are received
2072
2073 This is a no-op if the --relax option is in effect.
2074 """
2075 if oftest.config["relax"]:
2076 return
2077 logging.debug("Checking for unexpected packets on all ports")
Rich Lane48f6aed2014-03-23 15:51:02 -07002078 (rcv_port, rcv_pkt, pkt_time) = test.dataplane.poll(timeout=oftest.ofutils.default_negative_timeout)
Rich Lanee4b384d2013-09-13 14:33:40 -07002079 if rcv_pkt != None:
2080 logging.debug("Received unexpected packet on port %r: %s", rcv_port, format_packet(rcv_pkt))
2081 test.assertTrue(rcv_pkt == None, "Unexpected packet on port %r" % rcv_port)
2082
2083def verify_packets(test, pkt, ofports):
2084 """
2085 Check that a packet is received on certain ports
2086
2087 Also verifies that the packet is not received on any other ports, and that no
2088 other packets are received (unless --relax is in effect).
2089
2090 This covers the common and simplest cases for checking dataplane outputs.
2091 For more complex usage, like multiple different packets being output, or
2092 multiple packets on the same port, use the primitive verify_packet,
2093 verify_no_packet, and verify_no_other_packets functions directly.
2094 """
2095 pkt = str(pkt)
2096 for ofport in openflow_ports():
2097 if ofport in ofports:
2098 verify_packet(test, pkt, ofport)
2099 else:
2100 verify_no_packet(test, pkt, ofport)
2101 verify_no_other_packets(test)
2102
Rich Lane12d04592013-10-10 17:21:07 -07002103def verify_no_errors(ctrl):
2104 error, _ = ctrl.poll(ofp.OFPT_ERROR, 0)
2105 if error:
2106 raise AssertionError("unexpected error type=%d code=%d" % (error.err_type, error.code))
Rich Lanee4b384d2013-09-13 14:33:40 -07002107
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002108def verify_capability(test, capability):
2109 """
Jonathan Stout073642d2014-02-04 13:41:48 -05002110 Return True if DUT supports the specified capability.
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002111
2112 @param test Instance of base_tests.SimpleProtocol
2113 @param capability One of ofp_capabilities.
2114 """
2115 logging.info("Verifing that capability code is valid.")
2116 test.assertIn(capability, ofp.const.ofp_capabilities_map,
2117 "Capability code %d does not exist." % capability)
2118 capability_str = ofp.const.ofp_capabilities_map[capability]
Charles Chanc85f1562018-01-18 15:44:29 -08002119
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002120 logging.info(("Sending features_request to test if capability "
Jonathan Stout97e458a2014-01-28 16:08:04 -05002121 "%s is supported."), capability_str)
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002122 req = ofp.message.features_request()
2123 res, raw = test.controller.transact(req)
2124 test.assertIsNotNone(res, "Did not receive a response from the DUT.")
2125 test.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
2126 ("Unexpected packet type %d received in response to "
2127 "OFPT_FEATURES_REQUEST") % res.type)
Jonathan Stout641167f2014-02-04 12:07:10 -05002128 logging.info("Received features_reply.")
Charles Chanc85f1562018-01-18 15:44:29 -08002129
Jonathan Stout641167f2014-02-04 12:07:10 -05002130 if (res.capabilities & capability) > 0:
2131 logging.info("Switch capabilities bitmask claims to support %s",
2132 capability_str)
2133 return True, res.capabilities
2134 else:
2135 logging.info("Capabilities bitmask does not support %s.",
2136 capability_str)
2137 return False, res.capabilities
Jonathan Stoutfcee3142014-01-28 15:46:22 -05002138
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002139def verify_configuration_flag(test, flag):
2140 """
2141 Return True if DUT supports specified configuration flag.
2142
2143 @param test Instance of base_tests.SimpleProtocol
2144 @param flag One of ofp_config_flags.
Jonathan Stout1ec8c0f2014-02-04 15:25:38 -05002145 @returns (supported, flags) Bool if flag is set and flag values.
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002146 """
2147 logging.info("Verifing that flag is valid.")
2148 test.assertIn(flag, ofp.const.ofp_config_flags_map,
2149 "flag %s does not exist." % flag)
2150 flag_str = ofp.const.ofp_config_flags_map[flag]
2151
Charles Chanc85f1562018-01-18 15:44:29 -08002152 logging.info("Sending OFPT_GET_CONFIG_REQUEST.")
Jonathan Stouteb3721d2014-02-04 13:59:12 -05002153 req = ofp.message.get_config_request()
2154 rv = test.controller.message_send(req)
2155 test.assertNotEqual(rv, -1, "Not able to send get_config_request.")
2156
2157 logging.info("Expecting OFPT_GET_CONFIG_REPLY ")
2158 (res, pkt) = test.controller.poll(exp_msg=ofp.OFPT_GET_CONFIG_REPLY,
2159 timeout=2)
2160 test.assertIsNotNone(res, "Did not receive OFPT_GET_CONFIG_REPLY")
2161 logging.info("Received OFPT_GET_CONFIG_REPLY ")
2162
2163 if res.flags == flag:
2164 logging.info("%s flag is set.", flag_str)
2165 return True, res.flags
2166 else:
2167 logging.info("%s flag is not set.", flag_str)
2168 return False, res.flags
2169
Rich Lane7744e112013-01-11 17:23:57 -08002170__all__ = list(set(locals()) - _import_blacklist)