blob: ee88b93ade62483ae736d79e727a24f10e298d24 [file] [log] [blame]
Rich Lanea8d74912013-07-16 10:10:39 -07001# Distributed under the OpenFlow Software License (see LICENSE)
2# Copyright (c) 2010 The Board of Trustees of The Leland Stanford Junior University
3# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
4"""
5Flow match test cases
6
7These tests check the behavior of each match field. The only action used is a
8single output.
9"""
10
11import logging
12
13from oftest import config
14import oftest.base_tests as base_tests
15import ofp
16
17from oftest.testutils import *
18
19class MatchTest(base_tests.SimpleDataPlane):
20 """
21 Base class for match tests
22 """
23
24 def verify_match(self, match, matching, nonmatching):
25 """
26 Verify matching behavior
27
28 Checks that all the packets in 'matching' match 'match', and that
29 the packets in 'nonmatching' do not.
30
31 'match' is a LOXI match object. 'matching' and 'nonmatching' are
32 dicts mapping from string names (used in log messages) to string
33 packet data.
34 """
35 ports = sorted(config["port_map"].keys())
36 in_port = ports[0]
37 out_port = ports[1]
38
39 logging.info("Running match test for %s", match.show())
40
41 delete_all_flows(self.controller)
42
43 logging.info("Inserting flow sending matching packets to port %d", out_port)
44 request = ofp.message.flow_add(
45 table_id=0,
46 match=match,
47 instructions=[
48 ofp.instruction.apply_actions(
49 actions=[
50 ofp.action.output(
51 port=out_port,
52 max_len=ofp.OFPCML_NO_BUFFER)])],
53 buffer_id=ofp.OFP_NO_BUFFER,
54 priority=1000)
55 self.controller.message_send(request)
56
57 logging.info("Inserting match-all flow sending packets to controller")
58 request = ofp.message.flow_add(
59 table_id=0,
60 instructions=[
61 ofp.instruction.apply_actions(
62 actions=[
63 ofp.action.output(
64 port=ofp.OFPP_CONTROLLER,
65 max_len=ofp.OFPCML_NO_BUFFER)])],
66 buffer_id=ofp.OFP_NO_BUFFER,
67 priority=1)
68 self.controller.message_send(request)
69
70 do_barrier(self.controller)
71
72 for name, pkt in matching.items():
73 logging.info("Sending matching packet %s, expecting output to port %d", repr(name), out_port)
74 pktstr = str(pkt)
75 self.dataplane.send(in_port, pktstr)
76 receive_pkt_verify(self, [out_port], pktstr, in_port)
77
78 for name, pkt in nonmatching.items():
79 logging.info("Sending non-matching packet %s, expecting packet-in", repr(name))
80 pktstr = str(pkt)
81 self.dataplane.send(in_port, pktstr)
82 verify_packet_in(self, pktstr, in_port, ofp.OFPR_ACTION)
83
Rich Lane059f0122013-07-17 11:54:13 -070084class EthDst(MatchTest):
85 """
86 Match on ethernet destination
87 """
88 def runTest(self):
89 match = ofp.match([
90 ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05])
91 ])
92
93 matching = {
94 "correct": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
95 }
96
97 nonmatching = {
98 "incorrect": simple_tcp_packet(eth_dst='00:01:02:03:04:06'),
99 "multicast": simple_tcp_packet(eth_dst='01:01:02:03:04:05'),
100 "local": simple_tcp_packet(eth_dst='02:01:02:03:04:05'),
101 }
102
103 self.verify_match(match, matching, nonmatching)
104
105class EthDstBroadcast(MatchTest):
106 """
107 Match on ethernet destination (broadcast)
108 """
109 def runTest(self):
110 match = ofp.match([
111 ofp.oxm.eth_dst([0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
112 ])
113
114 matching = {
115 "ff:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:ff:ff:ff:ff:ff'),
116 }
117
118 nonmatching = {
119 "fd:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fd:ff:ff:ff:ff:ff'),
120 "fe:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fe:ff:ff:ff:ff:ff'),
121 "ff:fe:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:fe:ff:ff:ff:ff'),
122 }
123
124 self.verify_match(match, matching, nonmatching)
125
126class EthDstMulticast(MatchTest):
127 """
128 Match on ethernet destination (IPv4 multicast)
129 """
130 def runTest(self):
131 match = ofp.match([
132 ofp.oxm.eth_dst([0x01, 0x00, 0x5e, 0xed, 0x99, 0x02])
133 ])
134
135 matching = {
136 "correct": simple_tcp_packet(eth_dst='01:00:5e:ed:99:02'),
137 }
138
139 nonmatching = {
140 "incorrect": simple_tcp_packet(eth_dst='01:00:5e:ed:99:03'),
141 "unicast": simple_tcp_packet(eth_dst='00:00:5e:ed:99:02'),
142 "local": simple_tcp_packet(eth_dst='03:00:5e:ed:99:02'),
143 }
144
145 self.verify_match(match, matching, nonmatching)
146
147class EthDstMasked(MatchTest):
148 """
149 Match on ethernet destination (masked)
150 """
151 def runTest(self):
152 match = ofp.match([
153 ofp.oxm.eth_dst_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
154 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
155 ])
156
157 matching = {
158 "00:01:02:03:04:05": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
159 "ff:01:02:f3:04:05": simple_tcp_packet(eth_dst='ff:01:02:f3:04:05'),
160 }
161
162 nonmatching = {
163 "00:02:02:03:04:05": simple_tcp_packet(eth_dst='00:02:02:03:04:05'),
164 "00:01:02:07:04:05": simple_tcp_packet(eth_dst='00:01:02:07:04:05'),
165 }
166
167 self.verify_match(match, matching, nonmatching)
168
169class EthSrc(MatchTest):
170 """
171 Match on ethernet source
172 """
173 def runTest(self):
174 match = ofp.match([
175 ofp.oxm.eth_src([0,1,2,3,4,5])
176 ])
177
178 matching = {
179 "correct": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
180 }
181
182 nonmatching = {
183 "incorrect": simple_tcp_packet(eth_src='00:01:02:03:04:06'),
184 "multicast": simple_tcp_packet(eth_src='01:01:02:03:04:05'),
185 "local": simple_tcp_packet(eth_src='02:01:02:03:04:05'),
186 }
187
188 self.verify_match(match, matching, nonmatching)
189
190class EthSrcMasked(MatchTest):
191 """
192 Match on ethernet source (masked)
193 """
194 def runTest(self):
195 match = ofp.match([
196 ofp.oxm.eth_src_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
197 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
198 ])
199
200 matching = {
201 "00:01:02:03:04:05": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
202 "ff:01:02:f3:04:05": simple_tcp_packet(eth_src='ff:01:02:f3:04:05'),
203 }
204
205 nonmatching = {
206 "00:02:02:03:04:05": simple_tcp_packet(eth_src='00:02:02:03:04:05'),
207 "00:01:02:07:04:05": simple_tcp_packet(eth_src='00:01:02:07:04:05'),
208 }
209
210 self.verify_match(match, matching, nonmatching)
211
Rich Lanea8d74912013-07-16 10:10:39 -0700212class VlanExact(MatchTest):
213 """
214 Match on VLAN VID and PCP
215 """
216 def runTest(self):
217 match = ofp.match([
218 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
219 ofp.oxm.vlan_pcp(3),
220 ])
221
222 matching = {
223 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
224 }
225
226 nonmatching = {
227 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
228 "vid=4 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
229 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
230 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
231 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
232 "no vlan tag": simple_tcp_packet(),
233 }
234
235 self.verify_match(match, matching, nonmatching)
236
237class VlanVID(MatchTest):
238 """
239 Match on VLAN VID
240 """
241 def runTest(self):
242 match = ofp.match([
243 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
244 ])
245
246 matching = {
247 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
248 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
249 }
250
251 nonmatching = {
252 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
253 "no vlan tag": simple_tcp_packet(),
254 }
255
256 self.verify_match(match, matching, nonmatching)
257
Rich Laned51b94f2013-07-16 13:29:55 -0700258class VlanVIDMasked(MatchTest):
259 """
260 Match on VLAN VID (masked)
261 """
262 def runTest(self):
263 match = ofp.match([
264 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT|3, ofp.OFPVID_PRESENT|3),
265 ])
266
267 matching = {
268 "vid=3 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=3, vlan_pcp=2),
269 "vid=7 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=7, vlan_pcp=2),
270 "vid=11 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=11, vlan_pcp=2),
271 }
272
273 nonmatching = {
274 "vid=0 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=2),
275 "vid=1 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=1, vlan_pcp=2),
276 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
277 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
278 "no vlan tag": simple_tcp_packet(),
279 }
280
281 self.verify_match(match, matching, nonmatching)
282
Rich Lanea8d74912013-07-16 10:10:39 -0700283class VlanPCP(MatchTest):
284 """
285 Match on VLAN PCP (VID matched)
286 """
287 def runTest(self):
288 match = ofp.match([
289 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
290 ofp.oxm.vlan_pcp(3),
291 ])
292
293 matching = {
294 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
295 }
296
297 nonmatching = {
298 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
299 "no vlan tag": simple_tcp_packet(),
300 }
301
302 self.verify_match(match, matching, nonmatching)
303
Rich Laned51b94f2013-07-16 13:29:55 -0700304@nonstandard
305class VlanPCPMasked(MatchTest):
306 """
307 Match on VLAN PCP (masked, VID matched)
308 """
309 def runTest(self):
310 match = ofp.match([
311 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
312 ofp.oxm.vlan_pcp_masked(3, 3),
313 ])
314
315 matching = {
316 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
317 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
318 }
319
320 nonmatching = {
321 "vid=2 pcp=1": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=1),
322 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
323 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
324 "vid=2 pcp=5": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=5),
325 "vid=2 pcp=6": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=6),
326 "no vlan tag": simple_tcp_packet(),
327 }
328
329 self.verify_match(match, matching, nonmatching)
330
Rich Lanea8d74912013-07-16 10:10:39 -0700331class VlanPCPAnyVID(MatchTest):
332 """
333 Match on VLAN PCP (VID present)
334 """
335 def runTest(self):
336 match = ofp.match([
337 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
338 ofp.oxm.vlan_pcp(3),
339 ])
340
341 matching = {
342 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
343 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=3),
344 }
345
346 nonmatching = {
347 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
348 "no vlan tag": simple_tcp_packet(),
349 }
350
351 self.verify_match(match, matching, nonmatching)
352
353class VlanPresent(MatchTest):
354 """
355 Match on any VLAN tag (but must be present)
356 """
357 def runTest(self):
358 match = ofp.match([
359 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
360 ])
361
362 matching = {
363 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
364 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
365 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
366 }
367
368 nonmatching = {
369 "no vlan tag": simple_tcp_packet()
370 }
371
372 self.verify_match(match, matching, nonmatching)
373
374class VlanAbsent(MatchTest):
375 """
376 Match on absent VLAN tag
377 """
378 def runTest(self):
379 match = ofp.match([
380 ofp.oxm.vlan_vid(ofp.OFPVID_NONE),
381 ])
382
383 matching = {
384 "no vlan tag": simple_tcp_packet()
385 }
386
387 nonmatching = {
388 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
389 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
390 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
391 }
392
393 self.verify_match(match, matching, nonmatching)