blob: 0e37485db7e9a9b24a791d2fd364111a586fea1d [file] [log] [blame]
Dan Talaycoc901f4d2010-03-07 21:55:45 -08001
Dan Talaycod2ca1032010-03-10 14:40:26 -08002import sys
Dan Talayco92c99122010-06-03 13:53:18 -07003import copy
Dan Talaycod2ca1032010-03-10 14:40:26 -08004
5try:
6 import scapy.all as scapy
7except:
8 try:
9 import scapy as scapy
10 except:
11 sys.exit("Need to install scapy for packet parsing")
Dan Talayco41eae8b2010-03-10 13:57:06 -080012
Rich Lane477f4812012-10-04 22:49:00 -070013from oftest import config
Dan Talaycoc901f4d2010-03-07 21:55:45 -080014import oftest.controller as controller
15import oftest.cstruct as ofp
16import oftest.message as message
17import oftest.dataplane as dataplane
18import oftest.action as action
Dan Talayco41eae8b2010-03-10 13:57:06 -080019import oftest.parse as parse
Dan Talaycoc901f4d2010-03-07 21:55:45 -080020import logging
Dan Talayco4b2bee62010-07-20 14:10:05 -070021import types
Dan Talayco73f84012012-10-02 09:23:18 -070022import time
Dan Talaycoc901f4d2010-03-07 21:55:45 -080023
Dan Talaycoba3745c2010-07-21 21:51:08 -070024global skipped_test_count
25skipped_test_count = 0
26
Dan Talayco551befa2010-07-15 17:05:32 -070027# Some useful defines
28IP_ETHERTYPE = 0x800
29TCP_PROTOCOL = 0x6
30UDP_PROTOCOL = 0x11
31
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000032MINSIZE = 0
33
Rich Lane9a003812012-10-04 17:17:59 -070034def delete_all_flows(ctrl):
Dan Talayco41eae8b2010-03-10 13:57:06 -080035 """
36 Delete all flows on the switch
37 @param ctrl The controller object for the test
Dan Talayco41eae8b2010-03-10 13:57:06 -080038 """
39
Rich Lane9a003812012-10-04 17:17:59 -070040 logging.info("Deleting all flows")
Dan Talaycoc901f4d2010-03-07 21:55:45 -080041 msg = message.flow_mod()
42 msg.match.wildcards = ofp.OFPFW_ALL
Dan Talayco41eae8b2010-03-10 13:57:06 -080043 msg.out_port = ofp.OFPP_NONE
Dan Talaycoc901f4d2010-03-07 21:55:45 -080044 msg.command = ofp.OFPFC_DELETE
45 msg.buffer_id = 0xffffffff
Dan Talayco41eae8b2010-03-10 13:57:06 -080046 return ctrl.message_send(msg)
47
Ed Swierk99a74de2012-08-22 06:40:54 -070048def required_wildcards(parent):
Rich Lane2014f9b2012-10-05 15:29:40 -070049 w = test_param_get('required_wildcards', default='default')
Ed Swierk99a74de2012-08-22 06:40:54 -070050 if w == 'l3-l4':
51 return (ofp.OFPFW_NW_SRC_ALL | ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS
52 | ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST)
53 else:
54 return 0
55
Dan Talayco41eae8b2010-03-10 13:57:06 -080056def simple_tcp_packet(pktlen=100,
57 dl_dst='00:01:02:03:04:05',
58 dl_src='00:06:07:08:09:0a',
Shudong Zhoub10ebd62012-11-27 01:42:51 -080059 dl_qinq_enable=False,
60 dl_vlan_outer=20,
Tatsuya Yabe460321e2010-05-25 17:50:49 -070061 dl_vlan_enable=False,
62 dl_vlan=0,
63 dl_vlan_pcp=0,
Dan Talayco551befa2010-07-15 17:05:32 -070064 dl_vlan_cfi=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -080065 ip_src='192.168.0.1',
66 ip_dst='192.168.0.2',
Tatsuya Yabe460321e2010-05-25 17:50:49 -070067 ip_tos=0,
Dan Talayco41eae8b2010-03-10 13:57:06 -080068 tcp_sport=1234,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070069 tcp_dport=80,
70 ip_ihl=None,
71 ip_options=False
Dan Talayco41eae8b2010-03-10 13:57:06 -080072 ):
73 """
74 Return a simple dataplane TCP packet
75
76 Supports a few parameters:
77 @param len Length of packet in bytes w/o CRC
78 @param dl_dst Destinatino MAC
79 @param dl_src Source MAC
Shudong Zhoub10ebd62012-11-27 01:42:51 -080080 @param dl_qinq_enable True if the packet is double vlan tags
81 @param dl_vlan_outer Outer VLAN ID
Tatsuya Yabe460321e2010-05-25 17:50:49 -070082 @param dl_vlan_enable True if the packet is with vlan, False otherwise
83 @param dl_vlan VLAN ID
84 @param dl_vlan_pcp VLAN priority
Dan Talayco41eae8b2010-03-10 13:57:06 -080085 @param ip_src IP source
86 @param ip_dst IP destination
Tatsuya Yabe460321e2010-05-25 17:50:49 -070087 @param ip_tos IP ToS
Dan Talayco41eae8b2010-03-10 13:57:06 -080088 @param tcp_dport TCP destination port
89 @param ip_sport TCP source port
90
91 Generates a simple TCP request. Users
92 shouldn't assume anything about this packet other than that
93 it is a valid ethernet/IP/TCP frame.
94 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +000095
96 if MINSIZE > pktlen:
97 pktlen = MINSIZE
98
Dan Talayco551befa2010-07-15 17:05:32 -070099 # Note Dot1Q.id is really CFI
Shudong Zhoub10ebd62012-11-27 01:42:51 -0800100 if (dl_qinq_enable):
101 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
102 scapy.Dot1Q(prio=0, id=0, vlan=dl_vlan_outer)/ \
103 scapy.Dot1Q(prio=dl_vlan_pcp, id=dl_vlan_cfi, vlan=dl_vlan)/ \
104 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl)/ \
105 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
106 elif (dl_vlan_enable):
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700107 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
Dan Talayco551befa2010-07-15 17:05:32 -0700108 scapy.Dot1Q(prio=dl_vlan_pcp, id=dl_vlan_cfi, vlan=dl_vlan)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700109 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl)/ \
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700110 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
111 else:
Christian Dickmann8b59b4b2012-09-23 16:48:30 -0700112 if not ip_options:
113 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
114 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl)/ \
115 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
116 else:
117 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
118 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl, options=ip_options)/ \
119 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
Tatsuya Yabe460321e2010-05-25 17:50:49 -0700120
Dan Talayco41eae8b2010-03-10 13:57:06 -0800121 pkt = pkt/("D" * (pktlen - len(pkt)))
122
123 return pkt
124
Rich Lane6ee7bea2012-10-26 16:19:29 -0700125def simple_udp_packet(pktlen=100,
126 dl_dst='00:01:02:03:04:05',
127 dl_src='00:06:07:08:09:0a',
128 dl_vlan_enable=False,
129 dl_vlan=0,
130 dl_vlan_pcp=0,
131 dl_vlan_cfi=0,
132 ip_src='192.168.0.1',
133 ip_dst='192.168.0.2',
134 ip_tos=0,
135 udp_sport=1234,
136 udp_dport=80,
137 ip_ihl=None,
138 ip_options=False
139 ):
140 """
141 Return a simple dataplane UDP packet
142
143 Supports a few parameters:
144 @param len Length of packet in bytes w/o CRC
145 @param dl_dst Destination MAC
146 @param dl_src Source MAC
147 @param dl_vlan_enable True if the packet is with vlan, False otherwise
148 @param dl_vlan VLAN ID
149 @param dl_vlan_pcp VLAN priority
150 @param ip_src IP source
151 @param ip_dst IP destination
152 @param ip_tos IP ToS
153 @param udp_dport UDP destination port
154 @param udp_sport UDP source port
155
156 Generates a simple UDP packet. Users shouldn't assume anything about
157 this packet other than that it is a valid ethernet/IP/UDP frame.
158 """
159
160 if MINSIZE > pktlen:
161 pktlen = MINSIZE
162
163 # Note Dot1Q.id is really CFI
164 if (dl_vlan_enable):
165 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
166 scapy.Dot1Q(prio=dl_vlan_pcp, id=dl_vlan_cfi, vlan=dl_vlan)/ \
167 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl)/ \
168 scapy.UDP(sport=udp_sport, dport=udp_dport)
169 else:
170 if not ip_options:
171 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
172 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl)/ \
173 scapy.UDP(sport=udp_sport, dport=udp_dport)
174 else:
175 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
176 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=ip_ihl, options=ip_options)/ \
177 scapy.UDP(sport=udp_sport, dport=udp_dport)
178
179 pkt = pkt/("D" * (pktlen - len(pkt)))
180
181 return pkt
182
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700183def simple_icmp_packet(pktlen=60,
184 dl_dst='00:01:02:03:04:05',
185 dl_src='00:06:07:08:09:0a',
186 dl_vlan_enable=False,
187 dl_vlan=0,
188 dl_vlan_pcp=0,
189 ip_src='192.168.0.1',
190 ip_dst='192.168.0.2',
191 ip_tos=0,
192 icmp_type=8,
193 icmp_code=0
194 ):
195 """
196 Return a simple ICMP packet
197
198 Supports a few parameters:
199 @param len Length of packet in bytes w/o CRC
200 @param dl_dst Destinatino MAC
201 @param dl_src Source MAC
202 @param dl_vlan_enable True if the packet is with vlan, False otherwise
203 @param dl_vlan VLAN ID
204 @param dl_vlan_pcp VLAN priority
205 @param ip_src IP source
206 @param ip_dst IP destination
207 @param ip_tos IP ToS
208 @param icmp_type ICMP type
209 @param icmp_code ICMP code
210
211 Generates a simple ICMP ECHO REQUEST. Users
212 shouldn't assume anything about this packet other than that
213 it is a valid ethernet/ICMP frame.
214 """
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000215
216 if MINSIZE > pktlen:
217 pktlen = MINSIZE
218
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700219 if (dl_vlan_enable):
220 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
221 scapy.Dot1Q(prio=dl_vlan_pcp, id=0, vlan=dl_vlan)/ \
222 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
223 scapy.ICMP(type=icmp_type, code=icmp_code)
224 else:
225 pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
226 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
227 scapy.ICMP(type=icmp_type, code=icmp_code)
228
229 pkt = pkt/("0" * (pktlen - len(pkt)))
230
231 return pkt
232
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700233def simple_eth_packet(pktlen=60,
234 dl_dst='00:01:02:03:04:05',
235 dl_src='01:80:c2:00:00:00',
236 dl_type=0x88cc):
Jeffrey Townsend5cb7ed32012-08-17 18:11:01 +0000237
238 if MINSIZE > pktlen:
239 pktlen = MINSIZE
240
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700241 pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=dl_type)
242
243 pkt = pkt/("0" * (pktlen - len(pkt)))
244
245 return pkt
246
Shudong Zhoub7f12462012-11-20 13:01:12 -0800247def do_barrier(ctrl, timeout=-1):
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700248 """
249 Do a barrier command
250 Return 0 on success, -1 on error
251 """
Dan Talayco41eae8b2010-03-10 13:57:06 -0800252 b = message.barrier_request()
Shudong Zhoub7f12462012-11-20 13:01:12 -0800253 (resp, pkt) = ctrl.transact(b, timeout=timeout)
Dan Talaycof6b94832012-04-12 21:50:57 -0700254 # We'll trust the transaction processing in the controller that xid matched
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700255 if not resp:
256 return -1
257 return 0
Dan Talayco92c99122010-06-03 13:53:18 -0700258
Rich Lane9a003812012-10-04 17:17:59 -0700259def port_config_get(controller, port_no):
Dan Talayco92c99122010-06-03 13:53:18 -0700260 """
261 Get a port's configuration
262
263 Gets the switch feature configuration and grabs one port's
264 configuration
265
266 @returns (hwaddr, config, advert) The hwaddress, configuration and
267 advertised values
268 """
269 request = message.features_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700270 reply, pkt = controller.transact(request)
Rich Lane9a003812012-10-04 17:17:59 -0700271 logging.debug(reply.show())
Dan Talayco92c99122010-06-03 13:53:18 -0700272 if reply is None:
Rich Lane9a003812012-10-04 17:17:59 -0700273 logging.warn("Get feature request failed")
Dan Talayco92c99122010-06-03 13:53:18 -0700274 return None, None, None
275 for idx in range(len(reply.ports)):
276 if reply.ports[idx].port_no == port_no:
277 return (reply.ports[idx].hw_addr, reply.ports[idx].config,
278 reply.ports[idx].advertised)
279
Rich Lane9a003812012-10-04 17:17:59 -0700280 logging.warn("Did not find port number for port config")
Dan Talayco92c99122010-06-03 13:53:18 -0700281 return None, None, None
282
Rich Lane9a003812012-10-04 17:17:59 -0700283def port_config_set(controller, port_no, config, mask):
Dan Talayco92c99122010-06-03 13:53:18 -0700284 """
285 Set the port configuration according the given parameters
286
287 Gets the switch feature configuration and updates one port's
288 configuration value according to config and mask
289 """
Rich Lane9a003812012-10-04 17:17:59 -0700290 logging.info("Setting port " + str(port_no) + " to config " + str(config))
Dan Talayco92c99122010-06-03 13:53:18 -0700291 request = message.features_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700292 reply, pkt = controller.transact(request)
Dan Talayco92c99122010-06-03 13:53:18 -0700293 if reply is None:
294 return -1
Rich Lane9a003812012-10-04 17:17:59 -0700295 logging.debug(reply.show())
Dan Talayco92c99122010-06-03 13:53:18 -0700296 for idx in range(len(reply.ports)):
297 if reply.ports[idx].port_no == port_no:
298 break
299 if idx >= len(reply.ports):
300 return -1
301 mod = message.port_mod()
302 mod.port_no = port_no
303 mod.hw_addr = reply.ports[idx].hw_addr
304 mod.config = config
305 mod.mask = mask
306 mod.advertise = reply.ports[idx].advertised
307 rv = controller.message_send(mod)
308 return rv
309
Rich Lane2014f9b2012-10-05 15:29:40 -0700310def receive_pkt_check(dp, pkt, yes_ports, no_ports, assert_if):
Dan Talayco92c99122010-06-03 13:53:18 -0700311 """
312 Check for proper receive packets across all ports
Ken Chiang1bf01602012-04-04 10:48:23 -0700313 @param dp The dataplane object
Dan Talayco92c99122010-06-03 13:53:18 -0700314 @param pkt Expected packet; may be None if yes_ports is empty
315 @param yes_ports Set or list of ports that should recieve packet
316 @param no_ports Set or list of ports that should not receive packet
317 @param assert_if Object that implements assertXXX
318 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700319 exp_pkt_arg = None
Rich Lane2014f9b2012-10-05 15:29:40 -0700320 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700321 exp_pkt_arg = pkt
322
Dan Talayco92c99122010-06-03 13:53:18 -0700323 for ofport in yes_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700324 logging.debug("Checking for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700325 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700326 port_number=ofport, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700327 assert_if.assertTrue(rcv_pkt is not None,
328 "Did not receive pkt on " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700329 if not dataplane.match_exp_pkt(pkt, rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700330 logging.debug("Sent %s" % format_packet(pkt))
331 logging.debug("Resp %s" % format_packet(rcv_pkt))
Ken Chiang1bf01602012-04-04 10:48:23 -0700332 assert_if.assertTrue(dataplane.match_exp_pkt(pkt, rcv_pkt),
333 "Response packet does not match send packet " +
334 "on port " + str(ofport))
Dan Talayco73f84012012-10-02 09:23:18 -0700335 if len(no_ports) > 0:
336 time.sleep(1)
Dan Talayco92c99122010-06-03 13:53:18 -0700337 for ofport in no_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700338 logging.debug("Negative check for pkt on port " + str(ofport))
Ken Chiang1bf01602012-04-04 10:48:23 -0700339 (rcv_port, rcv_pkt, pkt_time) = dp.poll(
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700340 port_number=ofport, timeout=1, exp_pkt=exp_pkt_arg)
Dan Talayco92c99122010-06-03 13:53:18 -0700341 assert_if.assertTrue(rcv_pkt is None,
342 "Unexpected pkt on port " + str(ofport))
Dan Talayco551befa2010-07-15 17:05:32 -0700343
344
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700345def receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port):
Dan Talayco551befa2010-07-15 17:05:32 -0700346 """
347 Receive a packet and verify it matches an expected value
Dan Talaycof6e76c02012-03-23 10:56:12 -0700348 @param egr_port A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700349
350 parent must implement dataplane, assertTrue and assertEqual
351 """
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700352 exp_pkt_arg = None
Rich Lane477f4812012-10-04 22:49:00 -0700353 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700354 exp_pkt_arg = exp_pkt
355
Dan Talaycof6e76c02012-03-23 10:56:12 -0700356 if type(egr_ports) == type([]):
357 egr_port_list = egr_ports
358 else:
359 egr_port_list = [egr_ports]
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700360
Dan Talaycof6e76c02012-03-23 10:56:12 -0700361 # Expect a packet from each port on egr port list
362 for egr_port in egr_port_list:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700363 check_port = egr_port
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700364 if egr_port == ofp.OFPP_IN_PORT:
Dan Talaycod8ae7582012-03-23 12:24:56 -0700365 check_port = ing_port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700366 (rcv_port, rcv_pkt, pkt_time) = parent.dataplane.poll(
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700367 port_number=check_port, exp_pkt=exp_pkt_arg)
Dan Talayco551befa2010-07-15 17:05:32 -0700368
Dan Talaycof6e76c02012-03-23 10:56:12 -0700369 if rcv_pkt is None:
Rich Lane9a003812012-10-04 17:17:59 -0700370 logging.error("ERROR: No packet received from " +
Dan Talaycod8ae7582012-03-23 12:24:56 -0700371 str(check_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700372
Dan Talaycof6e76c02012-03-23 10:56:12 -0700373 parent.assertTrue(rcv_pkt is not None,
Dan Talaycod8ae7582012-03-23 12:24:56 -0700374 "Did not receive packet port " + str(check_port))
Rich Lane9a003812012-10-04 17:17:59 -0700375 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700376 str(rcv_port))
377
378 if str(exp_pkt) != str(rcv_pkt):
Rich Lane9a003812012-10-04 17:17:59 -0700379 logging.error("ERROR: Packet match failed.")
380 logging.debug("Expected len " + str(len(exp_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700381 + str(exp_pkt).encode('hex'))
Rich Lane9a003812012-10-04 17:17:59 -0700382 logging.debug("Received len " + str(len(rcv_pkt)) + ": "
Dan Talaycof6e76c02012-03-23 10:56:12 -0700383 + str(rcv_pkt).encode('hex'))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700384 logging.debug("Expected packet: " + inspect_packet(scapy.Ether(str(exp_pkt))))
385 logging.debug("Received packet: " + inspect_packet(scapy.Ether(str(rcv_pkt))))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700386 parent.assertEqual(str(exp_pkt), str(rcv_pkt),
Dan Talaycod8ae7582012-03-23 12:24:56 -0700387 "Packet match error on port " + str(check_port))
Dan Talaycof6e76c02012-03-23 10:56:12 -0700388
Dan Talayco551befa2010-07-15 17:05:32 -0700389def match_verify(parent, req_match, res_match):
390 """
391 Verify flow matches agree; if they disagree, report where
392
393 parent must implement assertEqual
394 Use str() to ensure content is compared and not pointers
395 """
396
397 parent.assertEqual(req_match.wildcards, res_match.wildcards,
398 'Match failed: wildcards: ' + hex(req_match.wildcards) +
399 " != " + hex(res_match.wildcards))
400 parent.assertEqual(req_match.in_port, res_match.in_port,
401 'Match failed: in_port: ' + str(req_match.in_port) +
402 " != " + str(res_match.in_port))
403 parent.assertEqual(str(req_match.dl_src), str(res_match.dl_src),
404 'Match failed: dl_src: ' + str(req_match.dl_src) +
405 " != " + str(res_match.dl_src))
406 parent.assertEqual(str(req_match.dl_dst), str(res_match.dl_dst),
407 'Match failed: dl_dst: ' + str(req_match.dl_dst) +
408 " != " + str(res_match.dl_dst))
409 parent.assertEqual(req_match.dl_vlan, res_match.dl_vlan,
410 'Match failed: dl_vlan: ' + str(req_match.dl_vlan) +
411 " != " + str(res_match.dl_vlan))
412 parent.assertEqual(req_match.dl_vlan_pcp, res_match.dl_vlan_pcp,
413 'Match failed: dl_vlan_pcp: ' +
414 str(req_match.dl_vlan_pcp) + " != " +
415 str(res_match.dl_vlan_pcp))
416 parent.assertEqual(req_match.dl_type, res_match.dl_type,
417 'Match failed: dl_type: ' + str(req_match.dl_type) +
418 " != " + str(res_match.dl_type))
419
420 if (not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
421 and (req_match.dl_type == IP_ETHERTYPE)):
422 parent.assertEqual(req_match.nw_tos, res_match.nw_tos,
423 'Match failed: nw_tos: ' + str(req_match.nw_tos) +
424 " != " + str(res_match.nw_tos))
425 parent.assertEqual(req_match.nw_proto, res_match.nw_proto,
426 'Match failed: nw_proto: ' + str(req_match.nw_proto) +
427 " != " + str(res_match.nw_proto))
428 parent.assertEqual(req_match.nw_src, res_match.nw_src,
429 'Match failed: nw_src: ' + str(req_match.nw_src) +
430 " != " + str(res_match.nw_src))
431 parent.assertEqual(req_match.nw_dst, res_match.nw_dst,
432 'Match failed: nw_dst: ' + str(req_match.nw_dst) +
433 " != " + str(res_match.nw_dst))
434
435 if (not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
436 and ((req_match.nw_proto == TCP_PROTOCOL)
437 or (req_match.nw_proto == UDP_PROTOCOL))):
438 parent.assertEqual(req_match.tp_src, res_match.tp_src,
439 'Match failed: tp_src: ' +
440 str(req_match.tp_src) +
441 " != " + str(res_match.tp_src))
442 parent.assertEqual(req_match.tp_dst, res_match.tp_dst,
443 'Match failed: tp_dst: ' +
444 str(req_match.tp_dst) +
445 " != " + str(res_match.tp_dst))
446
Ed Swierk99a74de2012-08-22 06:40:54 -0700447def packet_to_flow_match(parent, packet):
448 match = parse.packet_to_flow_match(packet)
449 match.wildcards |= required_wildcards(parent)
450 return match
451
452def flow_msg_create(parent, pkt, ing_port=None, action_list=None, wildcards=None,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700453 egr_ports=None, egr_queue=None, check_expire=False, in_band=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700454 """
455 Create a flow message
456
457 Match on packet with given wildcards.
458 See flow_match_test for other parameter descriptoins
459 @param egr_queue if not None, make the output an enqueue action
Dan Talayco677c0b72011-08-23 22:53:38 -0700460 @param in_band if True, do not wildcard ingress port
Dan Talaycof6e76c02012-03-23 10:56:12 -0700461 @param egr_ports None (drop), single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700462 """
463 match = parse.packet_to_flow_match(pkt)
464 parent.assertTrue(match is not None, "Flow match from pkt failed")
Ed Swierk99a74de2012-08-22 06:40:54 -0700465 if wildcards is None:
466 wildcards = required_wildcards(parent)
Dan Talayco677c0b72011-08-23 22:53:38 -0700467 if in_band:
468 wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco551befa2010-07-15 17:05:32 -0700469 match.wildcards = wildcards
470 match.in_port = ing_port
471
Dan Talaycof6e76c02012-03-23 10:56:12 -0700472 if type(egr_ports) == type([]):
473 egr_port_list = egr_ports
474 else:
475 egr_port_list = [egr_ports]
476
Dan Talayco551befa2010-07-15 17:05:32 -0700477 request = message.flow_mod()
478 request.match = match
479 request.buffer_id = 0xffffffff
480 if check_expire:
481 request.flags |= ofp.OFPFF_SEND_FLOW_REM
482 request.hard_timeout = 1
483
484 if action_list is not None:
485 for act in action_list:
Rich Lane9a003812012-10-04 17:17:59 -0700486 logging.debug("Adding action " + act.show())
Dan Talayco551befa2010-07-15 17:05:32 -0700487 rv = request.actions.add(act)
488 parent.assertTrue(rv, "Could not add action" + act.show())
489
490 # Set up output/enqueue action if directed
491 if egr_queue is not None:
Dan Talaycof6e76c02012-03-23 10:56:12 -0700492 parent.assertTrue(egr_ports is not None, "Egress port not set")
Dan Talayco551befa2010-07-15 17:05:32 -0700493 act = action.action_enqueue()
Dan Talaycof6e76c02012-03-23 10:56:12 -0700494 for egr_port in egr_port_list:
495 act.port = egr_port
496 act.queue_id = egr_queue
497 rv = request.actions.add(act)
498 parent.assertTrue(rv, "Could not add enqueue action " +
499 str(egr_port) + " Q: " + str(egr_queue))
500 elif egr_ports is not None:
501 for egr_port in egr_port_list:
502 act = action.action_output()
503 act.port = egr_port
504 rv = request.actions.add(act)
505 parent.assertTrue(rv, "Could not add output action " +
506 str(egr_port))
Dan Talayco551befa2010-07-15 17:05:32 -0700507
Rich Lane9a003812012-10-04 17:17:59 -0700508 logging.debug(request.show())
Dan Talayco551befa2010-07-15 17:05:32 -0700509
510 return request
511
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -0700512def flow_msg_install(parent, request, clear_table_override=None):
Dan Talayco551befa2010-07-15 17:05:32 -0700513 """
514 Install a flow mod message in the switch
515
516 @param parent Must implement controller, assertEqual, assertTrue
517 @param request The request, all set to go
518 @param clear_table If true, clear the flow table before installing
519 """
Dan Talayco8a64e332012-03-28 14:53:20 -0700520
Rich Lane2014f9b2012-10-05 15:29:40 -0700521 clear_table = test_param_get('clear_table', default=True)
Jeffrey Townsendf3eae9c2012-03-28 18:23:21 -0700522 if(clear_table_override != None):
523 clear_table = clear_table_override
524
525 if clear_table:
Rich Lane9a003812012-10-04 17:17:59 -0700526 logging.debug("Clear flow table")
527 rc = delete_all_flows(parent.controller)
Dan Talayco551befa2010-07-15 17:05:32 -0700528 parent.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700529 parent.assertEqual(do_barrier(parent.controller), 0, "Barrier failed")
Dan Talayco551befa2010-07-15 17:05:32 -0700530
Rich Lane9a003812012-10-04 17:17:59 -0700531 logging.debug("Insert flow")
Dan Talayco551befa2010-07-15 17:05:32 -0700532 rv = parent.controller.message_send(request)
533 parent.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700534 parent.assertEqual(do_barrier(parent.controller), 0, "Barrier failed")
Dan Talayco551befa2010-07-15 17:05:32 -0700535
Ed Swierk99a74de2012-08-22 06:40:54 -0700536def flow_match_test_port_pair(parent, ing_port, egr_ports, wildcards=None,
Dan Talayco551befa2010-07-15 17:05:32 -0700537 dl_vlan=-1, pkt=None, exp_pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -0700538 action_list=None):
Dan Talayco551befa2010-07-15 17:05:32 -0700539 """
540 Flow match test on single TCP packet
Dan Talaycof6e76c02012-03-23 10:56:12 -0700541 @param egr_ports A single port or list of ports
Dan Talayco551befa2010-07-15 17:05:32 -0700542
543 Run test with packet through switch from ing_port to egr_port
544 See flow_match_test for parameter descriptions
545 """
546
Ed Swierk99a74de2012-08-22 06:40:54 -0700547 if wildcards is None:
548 wildcards = required_wildcards(parent)
Rich Lane9a003812012-10-04 17:17:59 -0700549 logging.info("Pkt match test: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700550 str(egr_ports))
Rich Lanee5779d32012-10-05 17:56:04 -0700551 logging.debug(" WC: " + hex(wildcards) + " vlan: " + str(dl_vlan))
Dan Talayco551befa2010-07-15 17:05:32 -0700552 if pkt is None:
553 pkt = simple_tcp_packet(dl_vlan_enable=(dl_vlan >= 0), dl_vlan=dl_vlan)
554
555 request = flow_msg_create(parent, pkt, ing_port=ing_port,
Dan Talaycof6e76c02012-03-23 10:56:12 -0700556 wildcards=wildcards, egr_ports=egr_ports,
Dan Talayco551befa2010-07-15 17:05:32 -0700557 action_list=action_list)
558
559 flow_msg_install(parent, request)
560
Rich Lane9a003812012-10-04 17:17:59 -0700561 logging.debug("Send packet: " + str(ing_port) + " to " +
Dan Talaycof6e76c02012-03-23 10:56:12 -0700562 str(egr_ports))
Dan Talayco551befa2010-07-15 17:05:32 -0700563 parent.dataplane.send(ing_port, str(pkt))
564
565 if exp_pkt is None:
566 exp_pkt = pkt
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700567 receive_pkt_verify(parent, egr_ports, exp_pkt, ing_port)
Dan Talayco551befa2010-07-15 17:05:32 -0700568
Dan Talaycof6e76c02012-03-23 10:56:12 -0700569def get_egr_list(parent, of_ports, how_many, exclude_list=[]):
570 """
571 Generate a list of ports avoiding those in the exclude list
Rich Lane9a003812012-10-04 17:17:59 -0700572 @param parent Supplies logging
Dan Talaycof6e76c02012-03-23 10:56:12 -0700573 @param of_ports List of OF port numbers
574 @param how_many Number of ports to be added to the list
575 @param exclude_list List of ports not to be used
576 @returns An empty list if unable to find enough ports
577 """
578
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700579 if how_many == 0:
580 return []
581
Dan Talaycof6e76c02012-03-23 10:56:12 -0700582 count = 0
583 egr_ports = []
584 for egr_idx in range(len(of_ports)):
585 if of_ports[egr_idx] not in exclude_list:
586 egr_ports.append(of_ports[egr_idx])
587 count += 1
588 if count >= how_many:
589 return egr_ports
Rich Lane9a003812012-10-04 17:17:59 -0700590 logging.debug("Could not generate enough egress ports for test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700591 return []
592
Ed Swierk99a74de2012-08-22 06:40:54 -0700593def flow_match_test(parent, port_map, wildcards=None, dl_vlan=-1, pkt=None,
Rich Lanee5779d32012-10-05 17:56:04 -0700594 exp_pkt=None, action_list=None,
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700595 max_test=0, egr_count=1, ing_port=False):
Dan Talayco551befa2010-07-15 17:05:32 -0700596 """
597 Run flow_match_test_port_pair on all port pairs
598
599 @param max_test If > 0 no more than this number of tests are executed.
600 @param parent Must implement controller, dataplane, assertTrue, assertEqual
Rich Lane9a003812012-10-04 17:17:59 -0700601 and logging
Dan Talayco551befa2010-07-15 17:05:32 -0700602 @param pkt If not None, use this packet for ingress
603 @param wildcards For flow match entry
Dan Talayco79184222010-11-01 12:24:29 -0700604 @param dl_vlan If not -1, and pkt is None, create a pkt w/ VLAN tag
Dan Talayco551befa2010-07-15 17:05:32 -0700605 @param exp_pkt If not None, use this as the expected output pkt; els use pkt
606 @param action_list Additional actions to add to flow mod
Dan Talaycocfa172f2012-03-23 12:03:00 -0700607 @param egr_count Number of egress ports; -1 means get from config w/ dflt 2
Dan Talayco551befa2010-07-15 17:05:32 -0700608 """
Ed Swierk99a74de2012-08-22 06:40:54 -0700609 if wildcards is None:
610 wildcards = required_wildcards(parent)
Dan Talayco551befa2010-07-15 17:05:32 -0700611 of_ports = port_map.keys()
612 of_ports.sort()
613 parent.assertTrue(len(of_ports) > 1, "Not enough ports for test")
614 test_count = 0
615
Dan Talaycocfa172f2012-03-23 12:03:00 -0700616 if egr_count == -1:
Rich Lane2014f9b2012-10-05 15:29:40 -0700617 egr_count = test_param_get('egr_count', default=2)
Dan Talaycocfa172f2012-03-23 12:03:00 -0700618
Dan Talayco551befa2010-07-15 17:05:32 -0700619 for ing_idx in range(len(of_ports)):
620 ingress_port = of_ports[ing_idx]
Dan Talaycof6e76c02012-03-23 10:56:12 -0700621 egr_ports = get_egr_list(parent, of_ports, egr_count,
622 exclude_list=[ingress_port])
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700623 if ing_port:
624 egr_ports.append(ofp.OFPP_IN_PORT)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700625 if len(egr_ports) == 0:
626 parent.assertTrue(0, "Failed to generate egress port list")
627
628 flow_match_test_port_pair(parent, ingress_port, egr_ports,
629 wildcards=wildcards, dl_vlan=dl_vlan,
630 pkt=pkt, exp_pkt=exp_pkt,
Rich Lanee5779d32012-10-05 17:56:04 -0700631 action_list=action_list)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700632 test_count += 1
633 if (max_test > 0) and (test_count > max_test):
Rich Lane9a003812012-10-04 17:17:59 -0700634 logging.info("Ran " + str(test_count) + " tests; exiting")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700635 return
Dan Talayco551befa2010-07-15 17:05:32 -0700636
Rich Lane2014f9b2012-10-05 15:29:40 -0700637def test_param_get(key, default=None):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700638 """
639 Return value passed via test-params if present
640
Dan Talayco4b2bee62010-07-20 14:10:05 -0700641 @param key The lookup key
642 @param default Default value to use if not found
643
644 If the pair 'key=val' appeared in the string passed to --test-params
645 on the command line, return val (as interpreted by exec). Otherwise
646 return default value.
Dan Talaycof6e76c02012-03-23 10:56:12 -0700647
648 WARNING: TEST PARAMETERS MUST BE PYTHON IDENTIFIERS;
649 eg egr_count, not egr-count.
Dan Talayco4b2bee62010-07-20 14:10:05 -0700650 """
651 try:
652 exec config["test_params"]
653 except:
654 return default
655
656 s = "val = " + str(key)
657 try:
658 exec s
659 return val
660 except:
661 return default
662
663def action_generate(parent, field_to_mod, mod_field_vals):
664 """
665 Create an action to modify the field indicated in field_to_mod
666
667 @param parent Must implement, assertTrue
668 @param field_to_mod The field to modify as a string name
669 @param mod_field_vals Hash of values to use for modified values
670 """
671
672 act = None
673
674 if field_to_mod in ['pktlen']:
675 return None
676
677 if field_to_mod == 'dl_dst':
678 act = action.action_set_dl_dst()
679 act.dl_addr = parse.parse_mac(mod_field_vals['dl_dst'])
680 elif field_to_mod == 'dl_src':
681 act = action.action_set_dl_src()
682 act.dl_addr = parse.parse_mac(mod_field_vals['dl_src'])
683 elif field_to_mod == 'dl_vlan_enable':
684 if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
685 act = action.action_strip_vlan()
686 # Add VLAN tag is handled by dl_vlan field
687 # Will return None in this case
688 elif field_to_mod == 'dl_vlan':
689 act = action.action_set_vlan_vid()
690 act.vlan_vid = mod_field_vals['dl_vlan']
691 elif field_to_mod == 'dl_vlan_pcp':
692 act = action.action_set_vlan_pcp()
693 act.vlan_pcp = mod_field_vals['dl_vlan_pcp']
694 elif field_to_mod == 'ip_src':
695 act = action.action_set_nw_src()
696 act.nw_addr = parse.parse_ip(mod_field_vals['ip_src'])
697 elif field_to_mod == 'ip_dst':
698 act = action.action_set_nw_dst()
699 act.nw_addr = parse.parse_ip(mod_field_vals['ip_dst'])
700 elif field_to_mod == 'ip_tos':
701 act = action.action_set_nw_tos()
702 act.nw_tos = mod_field_vals['ip_tos']
703 elif field_to_mod == 'tcp_sport':
704 act = action.action_set_tp_src()
705 act.tp_port = mod_field_vals['tcp_sport']
706 elif field_to_mod == 'tcp_dport':
707 act = action.action_set_tp_dst()
708 act.tp_port = mod_field_vals['tcp_dport']
Rich Lane110e0e32012-10-26 16:21:46 -0700709 elif field_to_mod == 'udp_sport':
710 act = action.action_set_tp_src()
711 act.tp_port = mod_field_vals['udp_sport']
712 elif field_to_mod == 'udp_dport':
713 act = action.action_set_tp_dst()
714 act.tp_port = mod_field_vals['udp_dport']
Dan Talayco4b2bee62010-07-20 14:10:05 -0700715 else:
716 parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
717
718 return act
719
720def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
Rich Lane110e0e32012-10-26 16:21:46 -0700721 mod_fields=[], tp="tcp", check_test_params=False):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700722 """
723 Set up the ingress and expected packet and action list for a test
724
Rich Lane2014f9b2012-10-05 15:29:40 -0700725 @param parent Must implement assertTrue
Dan Talayco4b2bee62010-07-20 14:10:05 -0700726 @param start_field_values Field values to use for ingress packet (optional)
727 @param mod_field_values Field values to use for modified packet (optional)
728 @param mod_fields The list of fields to be modified by the switch in the test.
729 @params check_test_params If True, will check the parameters vid, add_vlan
730 and strip_vlan from the command line.
731
732 Returns a triple: pkt-to-send, expected-pkt, action-list
733 """
734
735 new_actions = []
736
Dan Talayco4b2bee62010-07-20 14:10:05 -0700737 base_pkt_params = {}
738 base_pkt_params['pktlen'] = 100
739 base_pkt_params['dl_dst'] = '00:DE:F0:12:34:56'
740 base_pkt_params['dl_src'] = '00:23:45:67:89:AB'
741 base_pkt_params['dl_vlan_enable'] = False
742 base_pkt_params['dl_vlan'] = 2
743 base_pkt_params['dl_vlan_pcp'] = 0
744 base_pkt_params['ip_src'] = '192.168.0.1'
745 base_pkt_params['ip_dst'] = '192.168.0.2'
746 base_pkt_params['ip_tos'] = 0
Rich Lane110e0e32012-10-26 16:21:46 -0700747 if tp == "tcp":
748 base_pkt_params['tcp_sport'] = 1234
749 base_pkt_params['tcp_dport'] = 80
750 elif tp == "udp":
751 base_pkt_params['udp_sport'] = 1234
752 base_pkt_params['udp_dport'] = 80
Dan Talayco4b2bee62010-07-20 14:10:05 -0700753 for keyname in start_field_vals.keys():
754 base_pkt_params[keyname] = start_field_vals[keyname]
755
756 mod_pkt_params = {}
757 mod_pkt_params['pktlen'] = 100
758 mod_pkt_params['dl_dst'] = '00:21:0F:ED:CB:A9'
759 mod_pkt_params['dl_src'] = '00:ED:CB:A9:87:65'
760 mod_pkt_params['dl_vlan_enable'] = False
761 mod_pkt_params['dl_vlan'] = 3
762 mod_pkt_params['dl_vlan_pcp'] = 7
763 mod_pkt_params['ip_src'] = '10.20.30.40'
764 mod_pkt_params['ip_dst'] = '50.60.70.80'
765 mod_pkt_params['ip_tos'] = 0xf0
Rich Lane110e0e32012-10-26 16:21:46 -0700766 if tp == "tcp":
767 mod_pkt_params['tcp_sport'] = 4321
768 mod_pkt_params['tcp_dport'] = 8765
769 elif tp == "udp":
770 mod_pkt_params['udp_sport'] = 4321
771 mod_pkt_params['udp_dport'] = 8765
Dan Talayco4b2bee62010-07-20 14:10:05 -0700772 for keyname in mod_field_vals.keys():
773 mod_pkt_params[keyname] = mod_field_vals[keyname]
774
775 # Check for test param modifications
776 strip = False
777 if check_test_params:
Rich Lane2014f9b2012-10-05 15:29:40 -0700778 add_vlan = test_param_get('add_vlan')
779 strip_vlan = test_param_get('strip_vlan')
780 vid = test_param_get('vid')
Dan Talayco4b2bee62010-07-20 14:10:05 -0700781
782 if add_vlan and strip_vlan:
783 parent.assertTrue(0, "Add and strip VLAN both specified")
784
785 if vid:
786 base_pkt_params['dl_vlan_enable'] = True
787 base_pkt_params['dl_vlan'] = vid
788 if 'dl_vlan' in mod_fields:
789 mod_pkt_params['dl_vlan'] = vid + 1
790
791 if add_vlan:
792 base_pkt_params['dl_vlan_enable'] = False
793 mod_pkt_params['dl_vlan_enable'] = True
794 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] + 4
795 mod_fields.append('pktlen')
796 mod_fields.append('dl_vlan_enable')
797 if 'dl_vlan' not in mod_fields:
798 mod_fields.append('dl_vlan')
799 elif strip_vlan:
800 base_pkt_params['dl_vlan_enable'] = True
801 mod_pkt_params['dl_vlan_enable'] = False
802 mod_pkt_params['pktlen'] = base_pkt_params['pktlen'] - 4
803 mod_fields.append('dl_vlan_enable')
804 mod_fields.append('pktlen')
805
Rich Lane110e0e32012-10-26 16:21:46 -0700806 if tp == "tcp":
807 packet_builder = simple_tcp_packet
808 elif tp == "udp":
809 packet_builder = simple_udp_packet
810 else:
811 raise NotImplementedError("unknown transport protocol %s" % tp)
812
Dan Talayco4b2bee62010-07-20 14:10:05 -0700813 # Build the ingress packet
Rich Lane110e0e32012-10-26 16:21:46 -0700814 ingress_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700815
816 # Build the expected packet, modifying the indicated fields
817 for item in mod_fields:
818 base_pkt_params[item] = mod_pkt_params[item]
819 act = action_generate(parent, item, mod_pkt_params)
820 if act:
821 new_actions.append(act)
822
Rich Lane110e0e32012-10-26 16:21:46 -0700823 expected_pkt = packet_builder(**base_pkt_params)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700824
825 return (ingress_pkt, expected_pkt, new_actions)
Dan Talayco677c0b72011-08-23 22:53:38 -0700826
827# Generate a simple "drop" flow mod
828# If in_band is true, then only drop from first test port
829def flow_mod_gen(port_map, in_band):
830 request = message.flow_mod()
831 request.match.wildcards = ofp.OFPFW_ALL
832 if in_band:
833 request.match.wildcards = ofp.OFPFW_ALL - ofp.OFPFW_IN_PORT
834 for of_port, ifname in port_map.items(): # Grab first port
835 break
836 request.match.in_port = of_port
837 request.buffer_id = 0xffffffff
838 return request
Dan Talaycoba3745c2010-07-21 21:51:08 -0700839
840def skip_message_emit(parent, s):
841 """
842 Print out a 'skipped' message to stderr
843
844 @param s The string to print out to the log file
Rich Lane9a003812012-10-04 17:17:59 -0700845 @param parent Must implement config object
Dan Talaycoba3745c2010-07-21 21:51:08 -0700846 """
847 global skipped_test_count
848
849 skipped_test_count += 1
Rich Lane9a003812012-10-04 17:17:59 -0700850 logging.info("Skipping: " + s)
Rich Lane477f4812012-10-04 22:49:00 -0700851 if config["dbg_level"] < logging.WARNING:
Dan Talaycoba3745c2010-07-21 21:51:08 -0700852 sys.stderr.write("(skipped) ")
853 else:
854 sys.stderr.write("(S)")
Dan Talayco677c0b72011-08-23 22:53:38 -0700855
Dan Talayco8a64e332012-03-28 14:53:20 -0700856
857def all_stats_get(parent):
858 """
859 Get the aggregate stats for all flows in the table
860 @param parent Test instance with controller connection and assert
861 @returns dict with keys flows, packets, bytes, active (flows),
862 lookups, matched
863 """
864 stat_req = message.aggregate_stats_request()
865 stat_req.match = ofp.ofp_match()
866 stat_req.match.wildcards = ofp.OFPFW_ALL
867 stat_req.table_id = 0xff
868 stat_req.out_port = ofp.OFPP_NONE
869
870 rv = {}
871
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700872 (reply, pkt) = parent.controller.transact(stat_req)
Dan Talayco8a64e332012-03-28 14:53:20 -0700873 parent.assertTrue(len(reply.stats) == 1, "Did not receive flow stats reply")
874
875 for obj in reply.stats:
876 (rv["flows"], rv["packets"], rv["bytes"]) = (obj.flow_count,
877 obj.packet_count, obj.byte_count)
878 break
879
880 request = message.table_stats_request()
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700881 (reply , pkt) = parent.controller.transact(request)
Dan Talayco8a64e332012-03-28 14:53:20 -0700882
883
884 (rv["active"], rv["lookups"], rv["matched"]) = (0,0,0)
885 for obj in reply.stats:
886 rv["active"] += obj.active_count
887 rv["lookups"] += obj.lookup_count
888 rv["matched"] += obj.matched_count
889
890 return rv
Dan Talayco2baf8b52012-03-30 09:55:42 -0700891
892FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.'
893 for x in range(256)])
894
895def hex_dump_buffer(src, length=16):
896 """
897 Convert src to a hex dump string and return the string
898 @param src The source buffer
899 @param length The number of bytes shown in each line
900 @returns A string showing the hex dump
901 """
Dan Talaycoc516fa02012-04-12 22:28:43 -0700902 result = ["\n"]
Dan Talayco2baf8b52012-03-30 09:55:42 -0700903 for i in xrange(0, len(src), length):
904 chars = src[i:i+length]
905 hex = ' '.join(["%02x" % ord(x) for x in chars])
906 printable = ''.join(["%s" % ((ord(x) <= 127 and
907 FILTER[ord(x)]) or '.') for x in chars])
908 result.append("%04x %-*s %s\n" % (i, length*3, hex, printable))
909 return ''.join(result)
910
911def format_packet(pkt):
912 return "Packet length %d \n%s" % (len(str(pkt)),
913 hex_dump_buffer(str(pkt)))
Rich Lane5d7e89a2012-10-26 16:43:13 -0700914
915def inspect_packet(pkt):
916 """
917 Wrapper around scapy's show() method.
918 @returns A string showing the dissected packet.
919 """
920 from cStringIO import StringIO
921 out = None
922 backup = sys.stdout
923 try:
924 sys.stdout = StringIO()
925 pkt.show2()
926 out = sys.stdout.getvalue()
927 sys.stdout.close()
928 finally:
929 sys.stdout = backup
930 return out