blob: c81fc388c4c96cbb772839ae8c8c8f24f1adce04 [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
589# TODO IPv6 dscp
590
591class IPv4Ecn(MatchTest):
592 """
593 Match on ipv4 ecn
594 """
595 def runTest(self):
596 match = ofp.match([
597 ofp.oxm.eth_type(0x0800),
598 ofp.oxm.ip_ecn(2),
599 ])
600
601 matching = {
602 "dscp=4 ecn=2": simple_tcp_packet(ip_tos=0x12),
603 "dscp=6 ecn=2": simple_tcp_packet(ip_tos=0x1a),
604 }
605
606 nonmatching = {
607 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
608 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
609 }
610
611 self.verify_match(match, matching, nonmatching)
612
613# TODO IPv6 ecn
Rich Lane6b848af2013-07-17 15:35:36 -0700614
615class IPv4ProtoTCP(MatchTest):
616 """
617 Match on ipv4 protocol field (TCP)
618 """
619 def runTest(self):
620 match = ofp.match([
621 ofp.oxm.eth_type(0x0800),
622 ofp.oxm.ip_proto(6),
623 ])
624
625 matching = {
626 "tcp": simple_tcp_packet(),
627 }
628
629 nonmatching = {
630 "udp": simple_udp_packet(),
631 "icmp": simple_icmp_packet(),
632 }
633
634 self.verify_match(match, matching, nonmatching)
635
636# TODO IPv6 protocol (TCP)
637
638class IPv4ProtoUDP(MatchTest):
639 """
640 Match on ipv4 protocol field (UDP)
641 """
642 def runTest(self):
643 match = ofp.match([
644 ofp.oxm.eth_type(0x0800),
645 ofp.oxm.ip_proto(17),
646 ])
647
648 matching = {
649 "udp": simple_udp_packet(),
650 }
651
652 nonmatching = {
653 "tcp": simple_tcp_packet(),
654 "icmp": simple_icmp_packet(),
655 }
656
657 self.verify_match(match, matching, nonmatching)
658
659# TODO IPv6 protocol (UDP)
660
661class IPv4ProtoICMP(MatchTest):
662 """
663 Match on ipv4 protocol field (ICMP)
664 """
665 def runTest(self):
666 match = ofp.match([
667 ofp.oxm.eth_type(0x0800),
668 ofp.oxm.ip_proto(1),
669 ])
670
671 matching = {
672 "icmp": simple_icmp_packet(),
673 }
674
675 nonmatching = {
676 "tcp": simple_tcp_packet(),
677 "udp": simple_udp_packet(),
678 }
679
680 self.verify_match(match, matching, nonmatching)
681
682# TODO IPv6 protocol (ICMP)
Rich Lane05e756b2013-07-17 15:48:16 -0700683
Rich Lane3030a4f2013-07-17 16:21:45 -0700684class IPv4Src(MatchTest):
685 """
686 Match on ipv4 source address
687 """
688 def runTest(self):
689 match = ofp.match([
690 ofp.oxm.eth_type(0x0800),
691 ofp.oxm.ipv4_src(0xc0a80001), # 192.168.0.1
692 ])
693
694 matching = {
695 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
696 }
697
698 nonmatching = {
699 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
700 "255.255.255.255": simple_tcp_packet(ip_src='255.255.255.255'),
701 }
702
703 self.verify_match(match, matching, nonmatching)
704
705class IPv4SrcSubnetMasked(MatchTest):
706 """
707 Match on ipv4 source address (subnet masked)
708 """
709 def runTest(self):
710 match = ofp.match([
711 ofp.oxm.eth_type(0x0800),
712 # 192.168.0.0/20 (255.255.240.0)
713 ofp.oxm.ipv4_src_masked(0xc0a80000, 0xfffff000),
714 ])
715
716 matching = {
717 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
718 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
719 "192.168.4.2": simple_tcp_packet(ip_src='192.168.4.2'),
720 "192.168.0.0": simple_tcp_packet(ip_src='192.168.0.0'),
721 "192.168.15.255": simple_tcp_packet(ip_src='192.168.15.255'),
722 }
723
724 nonmatching = {
725 "192.168.16.0": simple_tcp_packet(ip_src='192.168.16.0'),
726 "192.167.255.255": simple_tcp_packet(ip_src='192.167.255.255'),
727 "192.168.31.1": simple_tcp_packet(ip_src='192.168.31.1'),
728 }
729
730 self.verify_match(match, matching, nonmatching)
731
732class IPv4SrcMasked(MatchTest):
733 """
734 Match on ipv4 source address (arbitrarily masked)
735 """
736 def runTest(self):
737 match = ofp.match([
738 ofp.oxm.eth_type(0x0800),
739 # 192.168.0.1 255.254.255.255
740 ofp.oxm.ipv4_src_masked(0xc0a80001, 0xfffeffff),
741 ])
742
743 matching = {
744 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
745 "192.169.0.1": simple_tcp_packet(ip_src='192.169.0.1'),
746 }
747
748 nonmatching = {
749 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
750 "192.167.0.1": simple_tcp_packet(ip_src='192.167.0.1'),
751 }
752
753 self.verify_match(match, matching, nonmatching)
754
755class IPv4Dst(MatchTest):
756 """
757 Match on ipv4 source address
758 """
759 def runTest(self):
760 match = ofp.match([
761 ofp.oxm.eth_type(0x0800),
762 ofp.oxm.ipv4_dst(0xc0a80001), # 192.168.0.1
763 ])
764
765 matching = {
766 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
767 }
768
769 nonmatching = {
770 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
771 "255.255.255.255": simple_tcp_packet(ip_dst='255.255.255.255'),
772 }
773
774 self.verify_match(match, matching, nonmatching)
775
776class IPv4DstSubnetMasked(MatchTest):
777 """
778 Match on ipv4 source address (subnet masked)
779 """
780 def runTest(self):
781 match = ofp.match([
782 ofp.oxm.eth_type(0x0800),
783 # 192.168.0.0/20 (255.255.240.0)
784 ofp.oxm.ipv4_dst_masked(0xc0a80000, 0xfffff000),
785 ])
786
787 matching = {
788 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
789 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
790 "192.168.4.2": simple_tcp_packet(ip_dst='192.168.4.2'),
791 "192.168.0.0": simple_tcp_packet(ip_dst='192.168.0.0'),
792 "192.168.15.255": simple_tcp_packet(ip_dst='192.168.15.255'),
793 }
794
795 nonmatching = {
796 "192.168.16.0": simple_tcp_packet(ip_dst='192.168.16.0'),
797 "192.167.255.255": simple_tcp_packet(ip_dst='192.167.255.255'),
798 "192.168.31.1": simple_tcp_packet(ip_dst='192.168.31.1'),
799 }
800
801 self.verify_match(match, matching, nonmatching)
802
803class IPv4DstMasked(MatchTest):
804 """
805 Match on ipv4 source address (arbitrarily masked)
806 """
807 def runTest(self):
808 match = ofp.match([
809 ofp.oxm.eth_type(0x0800),
810 # 192.168.0.1 255.254.255.255
811 ofp.oxm.ipv4_dst_masked(0xc0a80001, 0xfffeffff),
812 ])
813
814 matching = {
815 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
816 "192.169.0.1": simple_tcp_packet(ip_dst='192.169.0.1'),
817 }
818
819 nonmatching = {
820 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
821 "192.167.0.1": simple_tcp_packet(ip_dst='192.167.0.1'),
822 }
823
824 self.verify_match(match, matching, nonmatching)
825
826# TODO IPv6 source address
827# TODO IPv6 destination address
828
Rich Lane05e756b2013-07-17 15:48:16 -0700829class IPv4TCPSrc(MatchTest):
830 """
831 Match on ipv4 tcp source port
832 """
833 def runTest(self):
834 match = ofp.match([
835 ofp.oxm.eth_type(0x0800),
836 ofp.oxm.ip_proto(6),
837 ofp.oxm.tcp_src(53),
838 ])
839
840 matching = {
841 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
842 }
843
844 nonmatching = {
845 "tcp sport=52": simple_tcp_packet(tcp_sport=52),
846 "udp sport=53": simple_udp_packet(udp_sport=53),
847 }
848
849 self.verify_match(match, matching, nonmatching)
850
851# TODO IPv6 tcp source port
852
853class IPv4TCPDst(MatchTest):
854 """
855 Match on ipv4 tcp destination port
856 """
857 def runTest(self):
858 match = ofp.match([
859 ofp.oxm.eth_type(0x0800),
860 ofp.oxm.ip_proto(6),
861 ofp.oxm.tcp_dst(53),
862 ])
863
864 matching = {
865 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
866 }
867
868 nonmatching = {
869 "tcp dport=52": simple_tcp_packet(tcp_dport=52),
870 "udp dport=53": simple_udp_packet(udp_dport=53),
871 }
872
873 self.verify_match(match, matching, nonmatching)
874
875# TODO IPv6 tcp destination port
876
877class IPv4UDPSrc(MatchTest):
878 """
879 Match on ipv4 udp source port
880 """
881 def runTest(self):
882 match = ofp.match([
883 ofp.oxm.eth_type(0x0800),
884 ofp.oxm.ip_proto(17),
885 ofp.oxm.udp_src(53),
886 ])
887
888 matching = {
889 "udp sport=53": simple_udp_packet(udp_sport=53),
890 }
891
892 nonmatching = {
893 "udp sport=52": simple_udp_packet(udp_sport=52),
894 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
895 }
896
897 self.verify_match(match, matching, nonmatching)
898
899# TODO IPv6 udp source port
900
901class IPv4UDPDst(MatchTest):
902 """
903 Match on ipv4 udp destination port
904 """
905 def runTest(self):
906 match = ofp.match([
907 ofp.oxm.eth_type(0x0800),
908 ofp.oxm.ip_proto(17),
909 ofp.oxm.udp_dst(53),
910 ])
911
912 matching = {
913 "udp dport=53": simple_udp_packet(udp_dport=53),
914 }
915
916 nonmatching = {
917 "udp dport=52": simple_udp_packet(udp_dport=52),
918 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
919 }
920
921 self.verify_match(match, matching, nonmatching)
922
923# TODO IPv6 udp destination port
Rich Laneee574362013-07-17 16:40:07 -0700924
925class IPv4ICMPType(MatchTest):
926 """
927 Match on ipv4 icmp type
928 """
929 def runTest(self):
930 match = ofp.match([
931 ofp.oxm.eth_type(0x0800),
932 ofp.oxm.ip_proto(1),
933 ofp.oxm.icmpv4_type(3),
934 ])
935
936 matching = {
937 "type=3 code=1": simple_icmp_packet(icmp_type=3, icmp_code=1),
938 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
939 }
940
941 nonmatching = {
942 "type=2 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
943 }
944
945 self.verify_match(match, matching, nonmatching)
946
947class IPv4ICMPCode(MatchTest):
948 """
949 Match on ipv4 icmp code
950 """
951 def runTest(self):
952 match = ofp.match([
953 ofp.oxm.eth_type(0x0800),
954 ofp.oxm.ip_proto(1),
955 ofp.oxm.icmpv4_code(2),
956 ])
957
958 matching = {
959 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
960 "type=5 code=2": simple_icmp_packet(icmp_type=5, icmp_code=2),
961 }
962
963 nonmatching = {
964 "type=3 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
965 }
966
967 self.verify_match(match, matching, nonmatching)
968
969# TODO ipv6 icmp type
970# TODO ipv6 icmp code
Rich Lane6b770992013-07-17 17:11:24 -0700971
972class ArpOp(MatchTest):
973 """
974 Match on ARP operation
975 """
976 def runTest(self):
977 match = ofp.match([
978 ofp.oxm.eth_type(0x0806),
979 ofp.oxm.arp_op(3),
980 ])
981
982 matching = {
983 "op=3": simple_arp_packet(arp_op=3),
984 }
985
986 nonmatching = {
987 "op=4": simple_arp_packet(arp_op=4),
988 }
989
990 self.verify_match(match, matching, nonmatching)
Rich Lane503a2de2013-07-17 17:20:58 -0700991
992class ArpSPA(MatchTest):
993 """
994 Match on ARP sender IP
995 """
996 def runTest(self):
997 match = ofp.match([
998 ofp.oxm.eth_type(0x0806),
999 ofp.oxm.arp_spa(0xc0a80001), # 192.168.0.1
1000 ])
1001
1002 matching = {
1003 "192.168.0.1": simple_arp_packet(ip_snd="192.168.0.1"),
1004 }
1005
1006 nonmatching = {
1007 "192.168.0.2": simple_arp_packet(ip_snd="192.168.0.2"),
1008 }
1009
1010 self.verify_match(match, matching, nonmatching)
1011
1012class ArpTPA(MatchTest):
1013 """
1014 Match on ARP target IP
1015 """
1016 def runTest(self):
1017 match = ofp.match([
1018 ofp.oxm.eth_type(0x0806),
1019 ofp.oxm.arp_tpa(0xc0a80001), # 192.168.0.1
1020 ])
1021
1022 matching = {
1023 "192.168.0.1": simple_arp_packet(ip_tgt="192.168.0.1"),
1024 }
1025
1026 nonmatching = {
1027 "192.168.0.2": simple_arp_packet(ip_tgt="192.168.0.2"),
1028 }
1029
1030 self.verify_match(match, matching, nonmatching)