blob: 8a4611861206a12f365e97da66f7f75a5e78c9f3 [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,
304 # TODO ipv6
305 }
306
307 self.verify_match(match, matching, nonmatching)
308
309class EthTypeARP(MatchTest):
310 """
311 Match on ethertype (ARP)
312 """
313 def runTest(self):
314 match = ofp.match([
315 ofp.oxm.eth_type(0x0806)
316 ])
317
318 matching = {
319 "arp": simple_arp_packet(),
320 # TODO vlan tagged
321 }
322
323 nonmatching = {
324 "ipv4/tcp": simple_tcp_packet(),
325 }
326
327 self.verify_match(match, matching, nonmatching)
328
329class EthTypeNone(MatchTest):
330 """
331 Match on no ethertype (IEEE 802.3 without SNAP header)
332 """
333 def runTest(self):
334 match = ofp.match([
335 ofp.oxm.eth_type(0x05ff)
336 ])
337
338 snap_pkt = \
339 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=48)/ \
340 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
341 scapy.SNAP(OUI=0x000000, code=0x0800)/ \
342 scapy.IP(src='192.168.0.1', dst='192.168.0.2', proto=6)/ \
343 scapy.TCP(sport=1234, dport=80)
344
345 llc_pkt = \
346 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=17)/ \
347 scapy.LLC(dsap=0xaa, ssap=0xab, ctrl=0x03)
348
349 matching = {
350 "llc": llc_pkt,
351 }
352
353 nonmatching = {
354 "ipv4/tcp": simple_tcp_packet(),
355 "llc/snap": snap_pkt,
356 }
357
358 self.verify_match(match, matching, nonmatching)
359
Rich Lanea8d74912013-07-16 10:10:39 -0700360class VlanExact(MatchTest):
361 """
362 Match on VLAN VID and PCP
363 """
364 def runTest(self):
365 match = ofp.match([
366 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
367 ofp.oxm.vlan_pcp(3),
368 ])
369
370 matching = {
371 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
372 }
373
374 nonmatching = {
375 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
376 "vid=4 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
377 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
378 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
379 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
380 "no vlan tag": simple_tcp_packet(),
381 }
382
383 self.verify_match(match, matching, nonmatching)
384
385class VlanVID(MatchTest):
386 """
387 Match on VLAN VID
388 """
389 def runTest(self):
390 match = ofp.match([
391 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
392 ])
393
394 matching = {
395 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
396 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
397 }
398
399 nonmatching = {
400 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
401 "no vlan tag": simple_tcp_packet(),
402 }
403
404 self.verify_match(match, matching, nonmatching)
405
Rich Laned51b94f2013-07-16 13:29:55 -0700406class VlanVIDMasked(MatchTest):
407 """
408 Match on VLAN VID (masked)
409 """
410 def runTest(self):
411 match = ofp.match([
412 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT|3, ofp.OFPVID_PRESENT|3),
413 ])
414
415 matching = {
416 "vid=3 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=3, vlan_pcp=2),
417 "vid=7 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=7, vlan_pcp=2),
418 "vid=11 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=11, vlan_pcp=2),
419 }
420
421 nonmatching = {
422 "vid=0 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=2),
423 "vid=1 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=1, vlan_pcp=2),
424 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
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 Lanea8d74912013-07-16 10:10:39 -0700431class VlanPCP(MatchTest):
432 """
433 Match on VLAN PCP (VID matched)
434 """
435 def runTest(self):
436 match = ofp.match([
437 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
438 ofp.oxm.vlan_pcp(3),
439 ])
440
441 matching = {
442 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
443 }
444
445 nonmatching = {
446 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
447 "no vlan tag": simple_tcp_packet(),
448 }
449
450 self.verify_match(match, matching, nonmatching)
451
Rich Laned51b94f2013-07-16 13:29:55 -0700452@nonstandard
453class VlanPCPMasked(MatchTest):
454 """
455 Match on VLAN PCP (masked, VID matched)
456 """
457 def runTest(self):
458 match = ofp.match([
459 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
460 ofp.oxm.vlan_pcp_masked(3, 3),
461 ])
462
463 matching = {
464 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
465 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
466 }
467
468 nonmatching = {
469 "vid=2 pcp=1": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=1),
470 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
471 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
472 "vid=2 pcp=5": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=5),
473 "vid=2 pcp=6": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=6),
474 "no vlan tag": simple_tcp_packet(),
475 }
476
477 self.verify_match(match, matching, nonmatching)
478
Rich Lanea8d74912013-07-16 10:10:39 -0700479class VlanPCPAnyVID(MatchTest):
480 """
481 Match on VLAN PCP (VID present)
482 """
483 def runTest(self):
484 match = ofp.match([
485 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
486 ofp.oxm.vlan_pcp(3),
487 ])
488
489 matching = {
490 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
491 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=3),
492 }
493
494 nonmatching = {
495 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
496 "no vlan tag": simple_tcp_packet(),
497 }
498
499 self.verify_match(match, matching, nonmatching)
500
501class VlanPresent(MatchTest):
502 """
503 Match on any VLAN tag (but must be present)
504 """
505 def runTest(self):
506 match = ofp.match([
507 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
508 ])
509
510 matching = {
511 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
512 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
513 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
514 }
515
516 nonmatching = {
517 "no vlan tag": simple_tcp_packet()
518 }
519
520 self.verify_match(match, matching, nonmatching)
521
522class VlanAbsent(MatchTest):
523 """
524 Match on absent VLAN tag
525 """
526 def runTest(self):
527 match = ofp.match([
528 ofp.oxm.vlan_vid(ofp.OFPVID_NONE),
529 ])
530
531 matching = {
532 "no vlan tag": simple_tcp_packet()
533 }
534
535 nonmatching = {
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 self.verify_match(match, matching, nonmatching)
Rich Lane11f6d772013-07-17 15:27:46 -0700542
543class IPv4Dscp(MatchTest):
544 """
545 Match on ipv4 dscp
546 """
547 def runTest(self):
548 match = ofp.match([
549 ofp.oxm.eth_type(0x0800),
550 ofp.oxm.ip_dscp(4),
551 ])
552
553 matching = {
554 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
555 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
556 }
557
558 nonmatching = {
559 "dscp=5 ecn=0": simple_tcp_packet(ip_tos=0x14),
560 }
561
562 self.verify_match(match, matching, nonmatching)
563
564# TODO IPv6 dscp
565
566class IPv4Ecn(MatchTest):
567 """
568 Match on ipv4 ecn
569 """
570 def runTest(self):
571 match = ofp.match([
572 ofp.oxm.eth_type(0x0800),
573 ofp.oxm.ip_ecn(2),
574 ])
575
576 matching = {
577 "dscp=4 ecn=2": simple_tcp_packet(ip_tos=0x12),
578 "dscp=6 ecn=2": simple_tcp_packet(ip_tos=0x1a),
579 }
580
581 nonmatching = {
582 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
583 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
584 }
585
586 self.verify_match(match, matching, nonmatching)
587
588# TODO IPv6 ecn
Rich Lane6b848af2013-07-17 15:35:36 -0700589
590class IPv4ProtoTCP(MatchTest):
591 """
592 Match on ipv4 protocol field (TCP)
593 """
594 def runTest(self):
595 match = ofp.match([
596 ofp.oxm.eth_type(0x0800),
597 ofp.oxm.ip_proto(6),
598 ])
599
600 matching = {
601 "tcp": simple_tcp_packet(),
602 }
603
604 nonmatching = {
605 "udp": simple_udp_packet(),
606 "icmp": simple_icmp_packet(),
607 }
608
609 self.verify_match(match, matching, nonmatching)
610
611# TODO IPv6 protocol (TCP)
612
613class IPv4ProtoUDP(MatchTest):
614 """
615 Match on ipv4 protocol field (UDP)
616 """
617 def runTest(self):
618 match = ofp.match([
619 ofp.oxm.eth_type(0x0800),
620 ofp.oxm.ip_proto(17),
621 ])
622
623 matching = {
624 "udp": simple_udp_packet(),
625 }
626
627 nonmatching = {
628 "tcp": simple_tcp_packet(),
629 "icmp": simple_icmp_packet(),
630 }
631
632 self.verify_match(match, matching, nonmatching)
633
634# TODO IPv6 protocol (UDP)
635
636class IPv4ProtoICMP(MatchTest):
637 """
638 Match on ipv4 protocol field (ICMP)
639 """
640 def runTest(self):
641 match = ofp.match([
642 ofp.oxm.eth_type(0x0800),
643 ofp.oxm.ip_proto(1),
644 ])
645
646 matching = {
647 "icmp": simple_icmp_packet(),
648 }
649
650 nonmatching = {
651 "tcp": simple_tcp_packet(),
652 "udp": simple_udp_packet(),
653 }
654
655 self.verify_match(match, matching, nonmatching)
656
657# TODO IPv6 protocol (ICMP)
Rich Lane05e756b2013-07-17 15:48:16 -0700658
Rich Lane3030a4f2013-07-17 16:21:45 -0700659class IPv4Src(MatchTest):
660 """
661 Match on ipv4 source address
662 """
663 def runTest(self):
664 match = ofp.match([
665 ofp.oxm.eth_type(0x0800),
666 ofp.oxm.ipv4_src(0xc0a80001), # 192.168.0.1
667 ])
668
669 matching = {
670 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
671 }
672
673 nonmatching = {
674 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
675 "255.255.255.255": simple_tcp_packet(ip_src='255.255.255.255'),
676 }
677
678 self.verify_match(match, matching, nonmatching)
679
680class IPv4SrcSubnetMasked(MatchTest):
681 """
682 Match on ipv4 source address (subnet masked)
683 """
684 def runTest(self):
685 match = ofp.match([
686 ofp.oxm.eth_type(0x0800),
687 # 192.168.0.0/20 (255.255.240.0)
688 ofp.oxm.ipv4_src_masked(0xc0a80000, 0xfffff000),
689 ])
690
691 matching = {
692 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
693 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
694 "192.168.4.2": simple_tcp_packet(ip_src='192.168.4.2'),
695 "192.168.0.0": simple_tcp_packet(ip_src='192.168.0.0'),
696 "192.168.15.255": simple_tcp_packet(ip_src='192.168.15.255'),
697 }
698
699 nonmatching = {
700 "192.168.16.0": simple_tcp_packet(ip_src='192.168.16.0'),
701 "192.167.255.255": simple_tcp_packet(ip_src='192.167.255.255'),
702 "192.168.31.1": simple_tcp_packet(ip_src='192.168.31.1'),
703 }
704
705 self.verify_match(match, matching, nonmatching)
706
707class IPv4SrcMasked(MatchTest):
708 """
709 Match on ipv4 source address (arbitrarily masked)
710 """
711 def runTest(self):
712 match = ofp.match([
713 ofp.oxm.eth_type(0x0800),
714 # 192.168.0.1 255.254.255.255
715 ofp.oxm.ipv4_src_masked(0xc0a80001, 0xfffeffff),
716 ])
717
718 matching = {
719 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
720 "192.169.0.1": simple_tcp_packet(ip_src='192.169.0.1'),
721 }
722
723 nonmatching = {
724 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
725 "192.167.0.1": simple_tcp_packet(ip_src='192.167.0.1'),
726 }
727
728 self.verify_match(match, matching, nonmatching)
729
730class IPv4Dst(MatchTest):
731 """
732 Match on ipv4 source address
733 """
734 def runTest(self):
735 match = ofp.match([
736 ofp.oxm.eth_type(0x0800),
737 ofp.oxm.ipv4_dst(0xc0a80001), # 192.168.0.1
738 ])
739
740 matching = {
741 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
742 }
743
744 nonmatching = {
745 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
746 "255.255.255.255": simple_tcp_packet(ip_dst='255.255.255.255'),
747 }
748
749 self.verify_match(match, matching, nonmatching)
750
751class IPv4DstSubnetMasked(MatchTest):
752 """
753 Match on ipv4 source address (subnet masked)
754 """
755 def runTest(self):
756 match = ofp.match([
757 ofp.oxm.eth_type(0x0800),
758 # 192.168.0.0/20 (255.255.240.0)
759 ofp.oxm.ipv4_dst_masked(0xc0a80000, 0xfffff000),
760 ])
761
762 matching = {
763 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
764 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
765 "192.168.4.2": simple_tcp_packet(ip_dst='192.168.4.2'),
766 "192.168.0.0": simple_tcp_packet(ip_dst='192.168.0.0'),
767 "192.168.15.255": simple_tcp_packet(ip_dst='192.168.15.255'),
768 }
769
770 nonmatching = {
771 "192.168.16.0": simple_tcp_packet(ip_dst='192.168.16.0'),
772 "192.167.255.255": simple_tcp_packet(ip_dst='192.167.255.255'),
773 "192.168.31.1": simple_tcp_packet(ip_dst='192.168.31.1'),
774 }
775
776 self.verify_match(match, matching, nonmatching)
777
778class IPv4DstMasked(MatchTest):
779 """
780 Match on ipv4 source address (arbitrarily masked)
781 """
782 def runTest(self):
783 match = ofp.match([
784 ofp.oxm.eth_type(0x0800),
785 # 192.168.0.1 255.254.255.255
786 ofp.oxm.ipv4_dst_masked(0xc0a80001, 0xfffeffff),
787 ])
788
789 matching = {
790 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
791 "192.169.0.1": simple_tcp_packet(ip_dst='192.169.0.1'),
792 }
793
794 nonmatching = {
795 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
796 "192.167.0.1": simple_tcp_packet(ip_dst='192.167.0.1'),
797 }
798
799 self.verify_match(match, matching, nonmatching)
800
801# TODO IPv6 source address
802# TODO IPv6 destination address
803
Rich Lane05e756b2013-07-17 15:48:16 -0700804class IPv4TCPSrc(MatchTest):
805 """
806 Match on ipv4 tcp source port
807 """
808 def runTest(self):
809 match = ofp.match([
810 ofp.oxm.eth_type(0x0800),
811 ofp.oxm.ip_proto(6),
812 ofp.oxm.tcp_src(53),
813 ])
814
815 matching = {
816 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
817 }
818
819 nonmatching = {
820 "tcp sport=52": simple_tcp_packet(tcp_sport=52),
821 "udp sport=53": simple_udp_packet(udp_sport=53),
822 }
823
824 self.verify_match(match, matching, nonmatching)
825
826# TODO IPv6 tcp source port
827
828class IPv4TCPDst(MatchTest):
829 """
830 Match on ipv4 tcp destination port
831 """
832 def runTest(self):
833 match = ofp.match([
834 ofp.oxm.eth_type(0x0800),
835 ofp.oxm.ip_proto(6),
836 ofp.oxm.tcp_dst(53),
837 ])
838
839 matching = {
840 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
841 }
842
843 nonmatching = {
844 "tcp dport=52": simple_tcp_packet(tcp_dport=52),
845 "udp dport=53": simple_udp_packet(udp_dport=53),
846 }
847
848 self.verify_match(match, matching, nonmatching)
849
850# TODO IPv6 tcp destination port
851
852class IPv4UDPSrc(MatchTest):
853 """
854 Match on ipv4 udp source port
855 """
856 def runTest(self):
857 match = ofp.match([
858 ofp.oxm.eth_type(0x0800),
859 ofp.oxm.ip_proto(17),
860 ofp.oxm.udp_src(53),
861 ])
862
863 matching = {
864 "udp sport=53": simple_udp_packet(udp_sport=53),
865 }
866
867 nonmatching = {
868 "udp sport=52": simple_udp_packet(udp_sport=52),
869 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
870 }
871
872 self.verify_match(match, matching, nonmatching)
873
874# TODO IPv6 udp source port
875
876class IPv4UDPDst(MatchTest):
877 """
878 Match on ipv4 udp destination port
879 """
880 def runTest(self):
881 match = ofp.match([
882 ofp.oxm.eth_type(0x0800),
883 ofp.oxm.ip_proto(17),
884 ofp.oxm.udp_dst(53),
885 ])
886
887 matching = {
888 "udp dport=53": simple_udp_packet(udp_dport=53),
889 }
890
891 nonmatching = {
892 "udp dport=52": simple_udp_packet(udp_dport=52),
893 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
894 }
895
896 self.verify_match(match, matching, nonmatching)
897
898# TODO IPv6 udp destination port
Rich Laneee574362013-07-17 16:40:07 -0700899
900class IPv4ICMPType(MatchTest):
901 """
902 Match on ipv4 icmp type
903 """
904 def runTest(self):
905 match = ofp.match([
906 ofp.oxm.eth_type(0x0800),
907 ofp.oxm.ip_proto(1),
908 ofp.oxm.icmpv4_type(3),
909 ])
910
911 matching = {
912 "type=3 code=1": simple_icmp_packet(icmp_type=3, icmp_code=1),
913 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
914 }
915
916 nonmatching = {
917 "type=2 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
918 }
919
920 self.verify_match(match, matching, nonmatching)
921
922class IPv4ICMPCode(MatchTest):
923 """
924 Match on ipv4 icmp code
925 """
926 def runTest(self):
927 match = ofp.match([
928 ofp.oxm.eth_type(0x0800),
929 ofp.oxm.ip_proto(1),
930 ofp.oxm.icmpv4_code(2),
931 ])
932
933 matching = {
934 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
935 "type=5 code=2": simple_icmp_packet(icmp_type=5, icmp_code=2),
936 }
937
938 nonmatching = {
939 "type=3 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
940 }
941
942 self.verify_match(match, matching, nonmatching)
943
944# TODO ipv6 icmp type
945# TODO ipv6 icmp code
Rich Lane6b770992013-07-17 17:11:24 -0700946
947class ArpOp(MatchTest):
948 """
949 Match on ARP operation
950 """
951 def runTest(self):
952 match = ofp.match([
953 ofp.oxm.eth_type(0x0806),
954 ofp.oxm.arp_op(3),
955 ])
956
957 matching = {
958 "op=3": simple_arp_packet(arp_op=3),
959 }
960
961 nonmatching = {
962 "op=4": simple_arp_packet(arp_op=4),
963 }
964
965 self.verify_match(match, matching, nonmatching)
Rich Lane503a2de2013-07-17 17:20:58 -0700966
967class ArpSPA(MatchTest):
968 """
969 Match on ARP sender IP
970 """
971 def runTest(self):
972 match = ofp.match([
973 ofp.oxm.eth_type(0x0806),
974 ofp.oxm.arp_spa(0xc0a80001), # 192.168.0.1
975 ])
976
977 matching = {
978 "192.168.0.1": simple_arp_packet(ip_snd="192.168.0.1"),
979 }
980
981 nonmatching = {
982 "192.168.0.2": simple_arp_packet(ip_snd="192.168.0.2"),
983 }
984
985 self.verify_match(match, matching, nonmatching)
986
987class ArpTPA(MatchTest):
988 """
989 Match on ARP target IP
990 """
991 def runTest(self):
992 match = ofp.match([
993 ofp.oxm.eth_type(0x0806),
994 ofp.oxm.arp_tpa(0xc0a80001), # 192.168.0.1
995 ])
996
997 matching = {
998 "192.168.0.1": simple_arp_packet(ip_tgt="192.168.0.1"),
999 }
1000
1001 nonmatching = {
1002 "192.168.0.2": simple_arp_packet(ip_tgt="192.168.0.2"),
1003 }
1004
1005 self.verify_match(match, matching, nonmatching)