blob: 293828cd99dceab07fbf18300dbdb52194a7496f [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
Rich Lane14f10e22013-07-17 14:24:35 -070016import scapy.all as scapy
Rich Lanea8d74912013-07-16 10:10:39 -070017
18from oftest.testutils import *
19
20class MatchTest(base_tests.SimpleDataPlane):
21 """
22 Base class for match tests
23 """
24
25 def verify_match(self, match, matching, nonmatching):
26 """
27 Verify matching behavior
28
29 Checks that all the packets in 'matching' match 'match', and that
30 the packets in 'nonmatching' do not.
31
32 'match' is a LOXI match object. 'matching' and 'nonmatching' are
33 dicts mapping from string names (used in log messages) to string
34 packet data.
35 """
36 ports = sorted(config["port_map"].keys())
37 in_port = ports[0]
38 out_port = ports[1]
39
40 logging.info("Running match test for %s", match.show())
41
42 delete_all_flows(self.controller)
43
44 logging.info("Inserting flow sending matching packets to port %d", out_port)
45 request = ofp.message.flow_add(
46 table_id=0,
47 match=match,
48 instructions=[
49 ofp.instruction.apply_actions(
50 actions=[
51 ofp.action.output(
52 port=out_port,
53 max_len=ofp.OFPCML_NO_BUFFER)])],
54 buffer_id=ofp.OFP_NO_BUFFER,
55 priority=1000)
56 self.controller.message_send(request)
57
58 logging.info("Inserting match-all flow sending packets to controller")
59 request = ofp.message.flow_add(
60 table_id=0,
61 instructions=[
62 ofp.instruction.apply_actions(
63 actions=[
64 ofp.action.output(
65 port=ofp.OFPP_CONTROLLER,
66 max_len=ofp.OFPCML_NO_BUFFER)])],
67 buffer_id=ofp.OFP_NO_BUFFER,
68 priority=1)
69 self.controller.message_send(request)
70
71 do_barrier(self.controller)
72
73 for name, pkt in matching.items():
74 logging.info("Sending matching packet %s, expecting output to port %d", repr(name), out_port)
75 pktstr = str(pkt)
76 self.dataplane.send(in_port, pktstr)
77 receive_pkt_verify(self, [out_port], pktstr, in_port)
78
79 for name, pkt in nonmatching.items():
80 logging.info("Sending non-matching packet %s, expecting packet-in", repr(name))
81 pktstr = str(pkt)
82 self.dataplane.send(in_port, pktstr)
83 verify_packet_in(self, pktstr, in_port, ofp.OFPR_ACTION)
84
Rich Laneb9d1f4b2013-07-17 18:02:23 -070085# Does not use MatchTest because the ingress port is not a packet field
86class InPort(base_tests.SimpleDataPlane):
87 """
88 Match on ingress port
89 """
90 def runTest(self):
91 ports = sorted(config["port_map"].keys())
92 in_port = ports[0]
93 out_port = ports[1]
94 bad_port = ports[2]
95
96 match = ofp.match([
97 ofp.oxm.in_port(in_port)
98 ])
99
100 pkt = simple_tcp_packet()
101
102 logging.info("Running match test for %s", match.show())
103
104 delete_all_flows(self.controller)
105
106 logging.info("Inserting flow sending matching packets to port %d", out_port)
107 request = ofp.message.flow_add(
108 table_id=0,
109 match=match,
110 instructions=[
111 ofp.instruction.apply_actions(
112 actions=[
113 ofp.action.output(
114 port=out_port,
115 max_len=ofp.OFPCML_NO_BUFFER)])],
116 buffer_id=ofp.OFP_NO_BUFFER,
117 priority=1000)
118 self.controller.message_send(request)
119
120 logging.info("Inserting match-all flow sending packets to controller")
121 request = ofp.message.flow_add(
122 table_id=0,
123 instructions=[
124 ofp.instruction.apply_actions(
125 actions=[
126 ofp.action.output(
127 port=ofp.OFPP_CONTROLLER,
128 max_len=ofp.OFPCML_NO_BUFFER)])],
129 buffer_id=ofp.OFP_NO_BUFFER,
130 priority=1)
131 self.controller.message_send(request)
132
133 do_barrier(self.controller)
134
135 pktstr = str(pkt)
136
137 logging.info("Sending packet on matching ingress port, expecting output to port %d", out_port)
138 self.dataplane.send(in_port, pktstr)
139 receive_pkt_verify(self, [out_port], pktstr, in_port)
140
141 logging.info("Sending packet on non-matching ingress port, expecting packet-in")
142 self.dataplane.send(bad_port, pktstr)
143 verify_packet_in(self, pktstr, bad_port, ofp.OFPR_ACTION)
144
Rich Lane059f0122013-07-17 11:54:13 -0700145class EthDst(MatchTest):
146 """
147 Match on ethernet destination
148 """
149 def runTest(self):
150 match = ofp.match([
151 ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05])
152 ])
153
154 matching = {
155 "correct": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
156 }
157
158 nonmatching = {
159 "incorrect": simple_tcp_packet(eth_dst='00:01:02:03:04:06'),
160 "multicast": simple_tcp_packet(eth_dst='01:01:02:03:04:05'),
161 "local": simple_tcp_packet(eth_dst='02:01:02:03:04:05'),
162 }
163
164 self.verify_match(match, matching, nonmatching)
165
166class EthDstBroadcast(MatchTest):
167 """
168 Match on ethernet destination (broadcast)
169 """
170 def runTest(self):
171 match = ofp.match([
172 ofp.oxm.eth_dst([0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
173 ])
174
175 matching = {
176 "ff:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:ff:ff:ff:ff:ff'),
177 }
178
179 nonmatching = {
180 "fd:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fd:ff:ff:ff:ff:ff'),
181 "fe:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fe:ff:ff:ff:ff:ff'),
182 "ff:fe:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:fe:ff:ff:ff:ff'),
183 }
184
185 self.verify_match(match, matching, nonmatching)
186
187class EthDstMulticast(MatchTest):
188 """
189 Match on ethernet destination (IPv4 multicast)
190 """
191 def runTest(self):
192 match = ofp.match([
193 ofp.oxm.eth_dst([0x01, 0x00, 0x5e, 0xed, 0x99, 0x02])
194 ])
195
196 matching = {
197 "correct": simple_tcp_packet(eth_dst='01:00:5e:ed:99:02'),
198 }
199
200 nonmatching = {
201 "incorrect": simple_tcp_packet(eth_dst='01:00:5e:ed:99:03'),
202 "unicast": simple_tcp_packet(eth_dst='00:00:5e:ed:99:02'),
203 "local": simple_tcp_packet(eth_dst='03:00:5e:ed:99:02'),
204 }
205
206 self.verify_match(match, matching, nonmatching)
207
208class EthDstMasked(MatchTest):
209 """
210 Match on ethernet destination (masked)
211 """
212 def runTest(self):
213 match = ofp.match([
214 ofp.oxm.eth_dst_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
215 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
216 ])
217
218 matching = {
219 "00:01:02:03:04:05": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
220 "ff:01:02:f3:04:05": simple_tcp_packet(eth_dst='ff:01:02:f3:04:05'),
221 }
222
223 nonmatching = {
224 "00:02:02:03:04:05": simple_tcp_packet(eth_dst='00:02:02:03:04:05'),
225 "00:01:02:07:04:05": simple_tcp_packet(eth_dst='00:01:02:07:04:05'),
226 }
227
228 self.verify_match(match, matching, nonmatching)
229
230class EthSrc(MatchTest):
231 """
232 Match on ethernet source
233 """
234 def runTest(self):
235 match = ofp.match([
236 ofp.oxm.eth_src([0,1,2,3,4,5])
237 ])
238
239 matching = {
240 "correct": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
241 }
242
243 nonmatching = {
244 "incorrect": simple_tcp_packet(eth_src='00:01:02:03:04:06'),
245 "multicast": simple_tcp_packet(eth_src='01:01:02:03:04:05'),
246 "local": simple_tcp_packet(eth_src='02:01:02:03:04:05'),
247 }
248
249 self.verify_match(match, matching, nonmatching)
250
251class EthSrcMasked(MatchTest):
252 """
253 Match on ethernet source (masked)
254 """
255 def runTest(self):
256 match = ofp.match([
257 ofp.oxm.eth_src_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
258 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
259 ])
260
261 matching = {
262 "00:01:02:03:04:05": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
263 "ff:01:02:f3:04:05": simple_tcp_packet(eth_src='ff:01:02:f3:04:05'),
264 }
265
266 nonmatching = {
267 "00:02:02:03:04:05": simple_tcp_packet(eth_src='00:02:02:03:04:05'),
268 "00:01:02:07:04:05": simple_tcp_packet(eth_src='00:01:02:07:04:05'),
269 }
270
271 self.verify_match(match, matching, nonmatching)
272
Rich Lane14f10e22013-07-17 14:24:35 -0700273class EthTypeIPv4(MatchTest):
274 """
275 Match on ethertype (IPv4)
276 """
277 def runTest(self):
278 match = ofp.match([
279 ofp.oxm.eth_type(0x0800)
280 ])
281
282 snap_pkt = \
283 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=48)/ \
284 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
285 scapy.SNAP(OUI=0x000000, code=0x0800)/ \
286 scapy.IP(src='192.168.0.1', dst='192.168.0.2', proto=6)/ \
287 scapy.TCP(sport=1234, dport=80)
288
289 llc_pkt = \
290 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=17)/ \
291 scapy.LLC(dsap=0xaa, ssap=0xab, ctrl=0x03)
292
293 matching = {
294 "ipv4/tcp": simple_tcp_packet(),
295 "ipv4/udp": simple_udp_packet(),
296 "ipv4/icmp": simple_icmp_packet(),
297 "vlan tagged": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
298 "llc/snap": snap_pkt,
299 }
300
301 nonmatching = {
302 "arp": simple_arp_packet(),
303 "llc": llc_pkt,
Rich Lane86aceb02013-07-17 18:45:38 -0700304 "ipv6/tcp": simple_tcpv6_packet(),
305 }
306
307 self.verify_match(match, matching, nonmatching)
308
309class EthTypeIPv6(MatchTest):
310 """
311 Match on ethertype (IPv6)
312 """
313 def runTest(self):
314 match = ofp.match([
315 ofp.oxm.eth_type(0x86dd)
316 ])
317
318 matching = {
319 "ipv6/tcp": simple_tcpv6_packet(),
320 "ipv6/udp": simple_udpv6_packet(),
321 "ipv6/icmp": simple_icmpv6_packet(),
322 "vlan tagged": simple_tcpv6_packet(vlan_vid=2, vlan_pcp=3),
323 }
324
325 nonmatching = {
326 "ipv4/tcp": simple_tcp_packet(),
327 "arp": simple_arp_packet(),
Rich Lane14f10e22013-07-17 14:24:35 -0700328 }
329
330 self.verify_match(match, matching, nonmatching)
331
332class EthTypeARP(MatchTest):
333 """
334 Match on ethertype (ARP)
335 """
336 def runTest(self):
337 match = ofp.match([
338 ofp.oxm.eth_type(0x0806)
339 ])
340
341 matching = {
342 "arp": simple_arp_packet(),
343 # TODO vlan tagged
344 }
345
346 nonmatching = {
347 "ipv4/tcp": simple_tcp_packet(),
Rich Lane86aceb02013-07-17 18:45:38 -0700348 "ipv6/tcp": simple_tcpv6_packet(),
Rich Lane14f10e22013-07-17 14:24:35 -0700349 }
350
351 self.verify_match(match, matching, nonmatching)
352
353class EthTypeNone(MatchTest):
354 """
355 Match on no ethertype (IEEE 802.3 without SNAP header)
356 """
357 def runTest(self):
358 match = ofp.match([
359 ofp.oxm.eth_type(0x05ff)
360 ])
361
362 snap_pkt = \
363 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=48)/ \
364 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
365 scapy.SNAP(OUI=0x000000, code=0x0800)/ \
366 scapy.IP(src='192.168.0.1', dst='192.168.0.2', proto=6)/ \
367 scapy.TCP(sport=1234, dport=80)
368
369 llc_pkt = \
370 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=17)/ \
371 scapy.LLC(dsap=0xaa, ssap=0xab, ctrl=0x03)
372
373 matching = {
374 "llc": llc_pkt,
375 }
376
377 nonmatching = {
378 "ipv4/tcp": simple_tcp_packet(),
Rich Lane86aceb02013-07-17 18:45:38 -0700379 "ipv6/tcp": simple_tcpv6_packet(),
Rich Lane14f10e22013-07-17 14:24:35 -0700380 "llc/snap": snap_pkt,
381 }
382
383 self.verify_match(match, matching, nonmatching)
384
Rich Lanea8d74912013-07-16 10:10:39 -0700385class VlanExact(MatchTest):
386 """
387 Match on VLAN VID and PCP
388 """
389 def runTest(self):
390 match = ofp.match([
391 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
392 ofp.oxm.vlan_pcp(3),
393 ])
394
395 matching = {
396 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
397 }
398
399 nonmatching = {
400 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
401 "vid=4 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
402 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
403 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
404 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
405 "no vlan tag": simple_tcp_packet(),
406 }
407
408 self.verify_match(match, matching, nonmatching)
409
410class VlanVID(MatchTest):
411 """
412 Match on VLAN VID
413 """
414 def runTest(self):
415 match = ofp.match([
416 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
417 ])
418
419 matching = {
420 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
421 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
422 }
423
424 nonmatching = {
425 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
426 "no vlan tag": simple_tcp_packet(),
427 }
428
429 self.verify_match(match, matching, nonmatching)
430
Rich Laned51b94f2013-07-16 13:29:55 -0700431class VlanVIDMasked(MatchTest):
432 """
433 Match on VLAN VID (masked)
434 """
435 def runTest(self):
436 match = ofp.match([
437 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT|3, ofp.OFPVID_PRESENT|3),
438 ])
439
440 matching = {
441 "vid=3 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=3, vlan_pcp=2),
442 "vid=7 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=7, vlan_pcp=2),
443 "vid=11 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=11, vlan_pcp=2),
444 }
445
446 nonmatching = {
447 "vid=0 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=2),
448 "vid=1 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=1, vlan_pcp=2),
449 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
450 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
451 "no vlan tag": simple_tcp_packet(),
452 }
453
454 self.verify_match(match, matching, nonmatching)
455
Rich Lanea8d74912013-07-16 10:10:39 -0700456class VlanPCP(MatchTest):
457 """
458 Match on VLAN PCP (VID matched)
459 """
460 def runTest(self):
461 match = ofp.match([
462 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
463 ofp.oxm.vlan_pcp(3),
464 ])
465
466 matching = {
467 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
468 }
469
470 nonmatching = {
471 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
472 "no vlan tag": simple_tcp_packet(),
473 }
474
475 self.verify_match(match, matching, nonmatching)
476
Rich Laned51b94f2013-07-16 13:29:55 -0700477@nonstandard
478class VlanPCPMasked(MatchTest):
479 """
480 Match on VLAN PCP (masked, VID matched)
481 """
482 def runTest(self):
483 match = ofp.match([
484 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
485 ofp.oxm.vlan_pcp_masked(3, 3),
486 ])
487
488 matching = {
489 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
490 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
491 }
492
493 nonmatching = {
494 "vid=2 pcp=1": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=1),
495 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
496 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
497 "vid=2 pcp=5": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=5),
498 "vid=2 pcp=6": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=6),
499 "no vlan tag": simple_tcp_packet(),
500 }
501
502 self.verify_match(match, matching, nonmatching)
503
Rich Lanea8d74912013-07-16 10:10:39 -0700504class VlanPCPAnyVID(MatchTest):
505 """
506 Match on VLAN PCP (VID present)
507 """
508 def runTest(self):
509 match = ofp.match([
510 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
511 ofp.oxm.vlan_pcp(3),
512 ])
513
514 matching = {
515 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
516 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=3),
517 }
518
519 nonmatching = {
520 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
521 "no vlan tag": simple_tcp_packet(),
522 }
523
524 self.verify_match(match, matching, nonmatching)
525
526class VlanPresent(MatchTest):
527 """
528 Match on any VLAN tag (but must be present)
529 """
530 def runTest(self):
531 match = ofp.match([
532 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
533 ])
534
535 matching = {
536 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
537 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
538 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
539 }
540
541 nonmatching = {
542 "no vlan tag": simple_tcp_packet()
543 }
544
545 self.verify_match(match, matching, nonmatching)
546
547class VlanAbsent(MatchTest):
548 """
549 Match on absent VLAN tag
550 """
551 def runTest(self):
552 match = ofp.match([
553 ofp.oxm.vlan_vid(ofp.OFPVID_NONE),
554 ])
555
556 matching = {
557 "no vlan tag": simple_tcp_packet()
558 }
559
560 nonmatching = {
561 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
562 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
563 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
564 }
565
566 self.verify_match(match, matching, nonmatching)
Rich Lane11f6d772013-07-17 15:27:46 -0700567
568class IPv4Dscp(MatchTest):
569 """
570 Match on ipv4 dscp
571 """
572 def runTest(self):
573 match = ofp.match([
574 ofp.oxm.eth_type(0x0800),
575 ofp.oxm.ip_dscp(4),
576 ])
577
578 matching = {
579 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
580 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
581 }
582
583 nonmatching = {
584 "dscp=5 ecn=0": simple_tcp_packet(ip_tos=0x14),
585 }
586
587 self.verify_match(match, matching, nonmatching)
588
Rich Lane93bbc542013-07-17 19:06:24 -0700589class IPv6Dscp(MatchTest):
590 """
591 Match on ipv6 dscp
592 """
593 def runTest(self):
594 match = ofp.match([
595 ofp.oxm.eth_type(0x86dd),
596 ofp.oxm.ip_dscp(4),
597 ])
598
599 matching = {
600 "dscp=4 ecn=0": simple_tcpv6_packet(ipv6_tc=0x10),
601 "dscp=4 ecn=3": simple_tcpv6_packet(ipv6_tc=0x13),
602 }
603
604 nonmatching = {
605 "dscp=5 ecn=0": simple_tcpv6_packet(ipv6_tc=0x14),
606 }
607
608 self.verify_match(match, matching, nonmatching)
Rich Lane11f6d772013-07-17 15:27:46 -0700609
610class IPv4Ecn(MatchTest):
611 """
612 Match on ipv4 ecn
613 """
614 def runTest(self):
615 match = ofp.match([
616 ofp.oxm.eth_type(0x0800),
617 ofp.oxm.ip_ecn(2),
618 ])
619
620 matching = {
621 "dscp=4 ecn=2": simple_tcp_packet(ip_tos=0x12),
622 "dscp=6 ecn=2": simple_tcp_packet(ip_tos=0x1a),
623 }
624
625 nonmatching = {
626 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
627 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
628 }
629
630 self.verify_match(match, matching, nonmatching)
631
Rich Lane93bbc542013-07-17 19:06:24 -0700632class IPv6Ecn(MatchTest):
633 """
634 Match on ipv6 ecn
635 """
636 def runTest(self):
637 match = ofp.match([
638 ofp.oxm.eth_type(0x86dd),
639 ofp.oxm.ip_ecn(2),
640 ])
641
642 matching = {
643 "dscp=4 ecn=2": simple_tcpv6_packet(ipv6_tc=0x12),
644 "dscp=6 ecn=2": simple_tcpv6_packet(ipv6_tc=0x1a),
645 }
646
647 nonmatching = {
648 "dscp=4 ecn=0": simple_tcpv6_packet(ipv6_tc=0x10),
649 "dscp=4 ecn=3": simple_tcpv6_packet(ipv6_tc=0x13),
650 }
651
652 self.verify_match(match, matching, nonmatching)
Rich Lane6b848af2013-07-17 15:35:36 -0700653
654class IPv4ProtoTCP(MatchTest):
655 """
656 Match on ipv4 protocol field (TCP)
657 """
658 def runTest(self):
659 match = ofp.match([
660 ofp.oxm.eth_type(0x0800),
661 ofp.oxm.ip_proto(6),
662 ])
663
664 matching = {
665 "tcp": simple_tcp_packet(),
666 }
667
668 nonmatching = {
669 "udp": simple_udp_packet(),
670 "icmp": simple_icmp_packet(),
671 }
672
673 self.verify_match(match, matching, nonmatching)
674
675# TODO IPv6 protocol (TCP)
676
677class IPv4ProtoUDP(MatchTest):
678 """
679 Match on ipv4 protocol field (UDP)
680 """
681 def runTest(self):
682 match = ofp.match([
683 ofp.oxm.eth_type(0x0800),
684 ofp.oxm.ip_proto(17),
685 ])
686
687 matching = {
688 "udp": simple_udp_packet(),
689 }
690
691 nonmatching = {
692 "tcp": simple_tcp_packet(),
693 "icmp": simple_icmp_packet(),
694 }
695
696 self.verify_match(match, matching, nonmatching)
697
698# TODO IPv6 protocol (UDP)
699
700class IPv4ProtoICMP(MatchTest):
701 """
702 Match on ipv4 protocol field (ICMP)
703 """
704 def runTest(self):
705 match = ofp.match([
706 ofp.oxm.eth_type(0x0800),
707 ofp.oxm.ip_proto(1),
708 ])
709
710 matching = {
711 "icmp": simple_icmp_packet(),
712 }
713
714 nonmatching = {
715 "tcp": simple_tcp_packet(),
716 "udp": simple_udp_packet(),
717 }
718
719 self.verify_match(match, matching, nonmatching)
720
721# TODO IPv6 protocol (ICMP)
Rich Lane05e756b2013-07-17 15:48:16 -0700722
Rich Lane3030a4f2013-07-17 16:21:45 -0700723class IPv4Src(MatchTest):
724 """
725 Match on ipv4 source address
726 """
727 def runTest(self):
728 match = ofp.match([
729 ofp.oxm.eth_type(0x0800),
730 ofp.oxm.ipv4_src(0xc0a80001), # 192.168.0.1
731 ])
732
733 matching = {
734 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
735 }
736
737 nonmatching = {
738 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
739 "255.255.255.255": simple_tcp_packet(ip_src='255.255.255.255'),
740 }
741
742 self.verify_match(match, matching, nonmatching)
743
744class IPv4SrcSubnetMasked(MatchTest):
745 """
746 Match on ipv4 source address (subnet masked)
747 """
748 def runTest(self):
749 match = ofp.match([
750 ofp.oxm.eth_type(0x0800),
751 # 192.168.0.0/20 (255.255.240.0)
752 ofp.oxm.ipv4_src_masked(0xc0a80000, 0xfffff000),
753 ])
754
755 matching = {
756 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
757 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
758 "192.168.4.2": simple_tcp_packet(ip_src='192.168.4.2'),
759 "192.168.0.0": simple_tcp_packet(ip_src='192.168.0.0'),
760 "192.168.15.255": simple_tcp_packet(ip_src='192.168.15.255'),
761 }
762
763 nonmatching = {
764 "192.168.16.0": simple_tcp_packet(ip_src='192.168.16.0'),
765 "192.167.255.255": simple_tcp_packet(ip_src='192.167.255.255'),
766 "192.168.31.1": simple_tcp_packet(ip_src='192.168.31.1'),
767 }
768
769 self.verify_match(match, matching, nonmatching)
770
771class IPv4SrcMasked(MatchTest):
772 """
773 Match on ipv4 source address (arbitrarily masked)
774 """
775 def runTest(self):
776 match = ofp.match([
777 ofp.oxm.eth_type(0x0800),
778 # 192.168.0.1 255.254.255.255
779 ofp.oxm.ipv4_src_masked(0xc0a80001, 0xfffeffff),
780 ])
781
782 matching = {
783 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
784 "192.169.0.1": simple_tcp_packet(ip_src='192.169.0.1'),
785 }
786
787 nonmatching = {
788 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
789 "192.167.0.1": simple_tcp_packet(ip_src='192.167.0.1'),
790 }
791
792 self.verify_match(match, matching, nonmatching)
793
794class IPv4Dst(MatchTest):
795 """
796 Match on ipv4 source address
797 """
798 def runTest(self):
799 match = ofp.match([
800 ofp.oxm.eth_type(0x0800),
801 ofp.oxm.ipv4_dst(0xc0a80001), # 192.168.0.1
802 ])
803
804 matching = {
805 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
806 }
807
808 nonmatching = {
809 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
810 "255.255.255.255": simple_tcp_packet(ip_dst='255.255.255.255'),
811 }
812
813 self.verify_match(match, matching, nonmatching)
814
815class IPv4DstSubnetMasked(MatchTest):
816 """
817 Match on ipv4 source address (subnet masked)
818 """
819 def runTest(self):
820 match = ofp.match([
821 ofp.oxm.eth_type(0x0800),
822 # 192.168.0.0/20 (255.255.240.0)
823 ofp.oxm.ipv4_dst_masked(0xc0a80000, 0xfffff000),
824 ])
825
826 matching = {
827 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
828 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
829 "192.168.4.2": simple_tcp_packet(ip_dst='192.168.4.2'),
830 "192.168.0.0": simple_tcp_packet(ip_dst='192.168.0.0'),
831 "192.168.15.255": simple_tcp_packet(ip_dst='192.168.15.255'),
832 }
833
834 nonmatching = {
835 "192.168.16.0": simple_tcp_packet(ip_dst='192.168.16.0'),
836 "192.167.255.255": simple_tcp_packet(ip_dst='192.167.255.255'),
837 "192.168.31.1": simple_tcp_packet(ip_dst='192.168.31.1'),
838 }
839
840 self.verify_match(match, matching, nonmatching)
841
842class IPv4DstMasked(MatchTest):
843 """
844 Match on ipv4 source address (arbitrarily masked)
845 """
846 def runTest(self):
847 match = ofp.match([
848 ofp.oxm.eth_type(0x0800),
849 # 192.168.0.1 255.254.255.255
850 ofp.oxm.ipv4_dst_masked(0xc0a80001, 0xfffeffff),
851 ])
852
853 matching = {
854 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
855 "192.169.0.1": simple_tcp_packet(ip_dst='192.169.0.1'),
856 }
857
858 nonmatching = {
859 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
860 "192.167.0.1": simple_tcp_packet(ip_dst='192.167.0.1'),
861 }
862
863 self.verify_match(match, matching, nonmatching)
864
865# TODO IPv6 source address
866# TODO IPv6 destination address
867
Rich Lane05e756b2013-07-17 15:48:16 -0700868class IPv4TCPSrc(MatchTest):
869 """
870 Match on ipv4 tcp source port
871 """
872 def runTest(self):
873 match = ofp.match([
874 ofp.oxm.eth_type(0x0800),
875 ofp.oxm.ip_proto(6),
876 ofp.oxm.tcp_src(53),
877 ])
878
879 matching = {
880 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
881 }
882
883 nonmatching = {
884 "tcp sport=52": simple_tcp_packet(tcp_sport=52),
885 "udp sport=53": simple_udp_packet(udp_sport=53),
886 }
887
888 self.verify_match(match, matching, nonmatching)
889
890# TODO IPv6 tcp source port
891
892class IPv4TCPDst(MatchTest):
893 """
894 Match on ipv4 tcp destination port
895 """
896 def runTest(self):
897 match = ofp.match([
898 ofp.oxm.eth_type(0x0800),
899 ofp.oxm.ip_proto(6),
900 ofp.oxm.tcp_dst(53),
901 ])
902
903 matching = {
904 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
905 }
906
907 nonmatching = {
908 "tcp dport=52": simple_tcp_packet(tcp_dport=52),
909 "udp dport=53": simple_udp_packet(udp_dport=53),
910 }
911
912 self.verify_match(match, matching, nonmatching)
913
914# TODO IPv6 tcp destination port
915
916class IPv4UDPSrc(MatchTest):
917 """
918 Match on ipv4 udp source port
919 """
920 def runTest(self):
921 match = ofp.match([
922 ofp.oxm.eth_type(0x0800),
923 ofp.oxm.ip_proto(17),
924 ofp.oxm.udp_src(53),
925 ])
926
927 matching = {
928 "udp sport=53": simple_udp_packet(udp_sport=53),
929 }
930
931 nonmatching = {
932 "udp sport=52": simple_udp_packet(udp_sport=52),
933 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
934 }
935
936 self.verify_match(match, matching, nonmatching)
937
938# TODO IPv6 udp source port
939
940class IPv4UDPDst(MatchTest):
941 """
942 Match on ipv4 udp destination port
943 """
944 def runTest(self):
945 match = ofp.match([
946 ofp.oxm.eth_type(0x0800),
947 ofp.oxm.ip_proto(17),
948 ofp.oxm.udp_dst(53),
949 ])
950
951 matching = {
952 "udp dport=53": simple_udp_packet(udp_dport=53),
953 }
954
955 nonmatching = {
956 "udp dport=52": simple_udp_packet(udp_dport=52),
957 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
958 }
959
960 self.verify_match(match, matching, nonmatching)
961
962# TODO IPv6 udp destination port
Rich Laneee574362013-07-17 16:40:07 -0700963
964class IPv4ICMPType(MatchTest):
965 """
966 Match on ipv4 icmp type
967 """
968 def runTest(self):
969 match = ofp.match([
970 ofp.oxm.eth_type(0x0800),
971 ofp.oxm.ip_proto(1),
972 ofp.oxm.icmpv4_type(3),
973 ])
974
975 matching = {
976 "type=3 code=1": simple_icmp_packet(icmp_type=3, icmp_code=1),
977 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
978 }
979
980 nonmatching = {
981 "type=2 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
982 }
983
984 self.verify_match(match, matching, nonmatching)
985
986class IPv4ICMPCode(MatchTest):
987 """
988 Match on ipv4 icmp code
989 """
990 def runTest(self):
991 match = ofp.match([
992 ofp.oxm.eth_type(0x0800),
993 ofp.oxm.ip_proto(1),
994 ofp.oxm.icmpv4_code(2),
995 ])
996
997 matching = {
998 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
999 "type=5 code=2": simple_icmp_packet(icmp_type=5, icmp_code=2),
1000 }
1001
1002 nonmatching = {
1003 "type=3 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
1004 }
1005
1006 self.verify_match(match, matching, nonmatching)
1007
1008# TODO ipv6 icmp type
1009# TODO ipv6 icmp code
Rich Lane6b770992013-07-17 17:11:24 -07001010
1011class ArpOp(MatchTest):
1012 """
1013 Match on ARP operation
1014 """
1015 def runTest(self):
1016 match = ofp.match([
1017 ofp.oxm.eth_type(0x0806),
1018 ofp.oxm.arp_op(3),
1019 ])
1020
1021 matching = {
1022 "op=3": simple_arp_packet(arp_op=3),
1023 }
1024
1025 nonmatching = {
1026 "op=4": simple_arp_packet(arp_op=4),
1027 }
1028
1029 self.verify_match(match, matching, nonmatching)
Rich Lane503a2de2013-07-17 17:20:58 -07001030
1031class ArpSPA(MatchTest):
1032 """
1033 Match on ARP sender IP
1034 """
1035 def runTest(self):
1036 match = ofp.match([
1037 ofp.oxm.eth_type(0x0806),
1038 ofp.oxm.arp_spa(0xc0a80001), # 192.168.0.1
1039 ])
1040
1041 matching = {
1042 "192.168.0.1": simple_arp_packet(ip_snd="192.168.0.1"),
1043 }
1044
1045 nonmatching = {
1046 "192.168.0.2": simple_arp_packet(ip_snd="192.168.0.2"),
1047 }
1048
1049 self.verify_match(match, matching, nonmatching)
1050
1051class ArpTPA(MatchTest):
1052 """
1053 Match on ARP target IP
1054 """
1055 def runTest(self):
1056 match = ofp.match([
1057 ofp.oxm.eth_type(0x0806),
1058 ofp.oxm.arp_tpa(0xc0a80001), # 192.168.0.1
1059 ])
1060
1061 matching = {
1062 "192.168.0.1": simple_arp_packet(ip_tgt="192.168.0.1"),
1063 }
1064
1065 nonmatching = {
1066 "192.168.0.2": simple_arp_packet(ip_tgt="192.168.0.2"),
1067 }
1068
1069 self.verify_match(match, matching, nonmatching)