blob: 4ef2ee80175d1e6bb2d95cf427784a09e94e2664 [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 Lane059f0122013-07-17 11:54:13 -070085class EthDst(MatchTest):
86 """
87 Match on ethernet destination
88 """
89 def runTest(self):
90 match = ofp.match([
91 ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05])
92 ])
93
94 matching = {
95 "correct": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
96 }
97
98 nonmatching = {
99 "incorrect": simple_tcp_packet(eth_dst='00:01:02:03:04:06'),
100 "multicast": simple_tcp_packet(eth_dst='01:01:02:03:04:05'),
101 "local": simple_tcp_packet(eth_dst='02:01:02:03:04:05'),
102 }
103
104 self.verify_match(match, matching, nonmatching)
105
106class EthDstBroadcast(MatchTest):
107 """
108 Match on ethernet destination (broadcast)
109 """
110 def runTest(self):
111 match = ofp.match([
112 ofp.oxm.eth_dst([0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
113 ])
114
115 matching = {
116 "ff:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:ff:ff:ff:ff:ff'),
117 }
118
119 nonmatching = {
120 "fd:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fd:ff:ff:ff:ff:ff'),
121 "fe:ff:ff:ff:ff:ff": simple_tcp_packet(eth_dst='fe:ff:ff:ff:ff:ff'),
122 "ff:fe:ff:ff:ff:ff": simple_tcp_packet(eth_dst='ff:fe:ff:ff:ff:ff'),
123 }
124
125 self.verify_match(match, matching, nonmatching)
126
127class EthDstMulticast(MatchTest):
128 """
129 Match on ethernet destination (IPv4 multicast)
130 """
131 def runTest(self):
132 match = ofp.match([
133 ofp.oxm.eth_dst([0x01, 0x00, 0x5e, 0xed, 0x99, 0x02])
134 ])
135
136 matching = {
137 "correct": simple_tcp_packet(eth_dst='01:00:5e:ed:99:02'),
138 }
139
140 nonmatching = {
141 "incorrect": simple_tcp_packet(eth_dst='01:00:5e:ed:99:03'),
142 "unicast": simple_tcp_packet(eth_dst='00:00:5e:ed:99:02'),
143 "local": simple_tcp_packet(eth_dst='03:00:5e:ed:99:02'),
144 }
145
146 self.verify_match(match, matching, nonmatching)
147
148class EthDstMasked(MatchTest):
149 """
150 Match on ethernet destination (masked)
151 """
152 def runTest(self):
153 match = ofp.match([
154 ofp.oxm.eth_dst_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
155 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
156 ])
157
158 matching = {
159 "00:01:02:03:04:05": simple_tcp_packet(eth_dst='00:01:02:03:04:05'),
160 "ff:01:02:f3:04:05": simple_tcp_packet(eth_dst='ff:01:02:f3:04:05'),
161 }
162
163 nonmatching = {
164 "00:02:02:03:04:05": simple_tcp_packet(eth_dst='00:02:02:03:04:05'),
165 "00:01:02:07:04:05": simple_tcp_packet(eth_dst='00:01:02:07:04:05'),
166 }
167
168 self.verify_match(match, matching, nonmatching)
169
170class EthSrc(MatchTest):
171 """
172 Match on ethernet source
173 """
174 def runTest(self):
175 match = ofp.match([
176 ofp.oxm.eth_src([0,1,2,3,4,5])
177 ])
178
179 matching = {
180 "correct": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
181 }
182
183 nonmatching = {
184 "incorrect": simple_tcp_packet(eth_src='00:01:02:03:04:06'),
185 "multicast": simple_tcp_packet(eth_src='01:01:02:03:04:05'),
186 "local": simple_tcp_packet(eth_src='02:01:02:03:04:05'),
187 }
188
189 self.verify_match(match, matching, nonmatching)
190
191class EthSrcMasked(MatchTest):
192 """
193 Match on ethernet source (masked)
194 """
195 def runTest(self):
196 match = ofp.match([
197 ofp.oxm.eth_src_masked([0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
198 [0x00, 0xff, 0xff, 0x0f, 0xff, 0xff])
199 ])
200
201 matching = {
202 "00:01:02:03:04:05": simple_tcp_packet(eth_src='00:01:02:03:04:05'),
203 "ff:01:02:f3:04:05": simple_tcp_packet(eth_src='ff:01:02:f3:04:05'),
204 }
205
206 nonmatching = {
207 "00:02:02:03:04:05": simple_tcp_packet(eth_src='00:02:02:03:04:05'),
208 "00:01:02:07:04:05": simple_tcp_packet(eth_src='00:01:02:07:04:05'),
209 }
210
211 self.verify_match(match, matching, nonmatching)
212
Rich Lane14f10e22013-07-17 14:24:35 -0700213class EthTypeIPv4(MatchTest):
214 """
215 Match on ethertype (IPv4)
216 """
217 def runTest(self):
218 match = ofp.match([
219 ofp.oxm.eth_type(0x0800)
220 ])
221
222 snap_pkt = \
223 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=48)/ \
224 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
225 scapy.SNAP(OUI=0x000000, code=0x0800)/ \
226 scapy.IP(src='192.168.0.1', dst='192.168.0.2', proto=6)/ \
227 scapy.TCP(sport=1234, dport=80)
228
229 llc_pkt = \
230 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=17)/ \
231 scapy.LLC(dsap=0xaa, ssap=0xab, ctrl=0x03)
232
233 matching = {
234 "ipv4/tcp": simple_tcp_packet(),
235 "ipv4/udp": simple_udp_packet(),
236 "ipv4/icmp": simple_icmp_packet(),
237 "vlan tagged": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
238 "llc/snap": snap_pkt,
239 }
240
241 nonmatching = {
242 "arp": simple_arp_packet(),
243 "llc": llc_pkt,
244 # TODO ipv6
245 }
246
247 self.verify_match(match, matching, nonmatching)
248
249class EthTypeARP(MatchTest):
250 """
251 Match on ethertype (ARP)
252 """
253 def runTest(self):
254 match = ofp.match([
255 ofp.oxm.eth_type(0x0806)
256 ])
257
258 matching = {
259 "arp": simple_arp_packet(),
260 # TODO vlan tagged
261 }
262
263 nonmatching = {
264 "ipv4/tcp": simple_tcp_packet(),
265 }
266
267 self.verify_match(match, matching, nonmatching)
268
269class EthTypeNone(MatchTest):
270 """
271 Match on no ethertype (IEEE 802.3 without SNAP header)
272 """
273 def runTest(self):
274 match = ofp.match([
275 ofp.oxm.eth_type(0x05ff)
276 ])
277
278 snap_pkt = \
279 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=48)/ \
280 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
281 scapy.SNAP(OUI=0x000000, code=0x0800)/ \
282 scapy.IP(src='192.168.0.1', dst='192.168.0.2', proto=6)/ \
283 scapy.TCP(sport=1234, dport=80)
284
285 llc_pkt = \
286 scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=17)/ \
287 scapy.LLC(dsap=0xaa, ssap=0xab, ctrl=0x03)
288
289 matching = {
290 "llc": llc_pkt,
291 }
292
293 nonmatching = {
294 "ipv4/tcp": simple_tcp_packet(),
295 "llc/snap": snap_pkt,
296 }
297
298 self.verify_match(match, matching, nonmatching)
299
Rich Lanea8d74912013-07-16 10:10:39 -0700300class VlanExact(MatchTest):
301 """
302 Match on VLAN VID and PCP
303 """
304 def runTest(self):
305 match = ofp.match([
306 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
307 ofp.oxm.vlan_pcp(3),
308 ])
309
310 matching = {
311 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
312 }
313
314 nonmatching = {
315 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
316 "vid=4 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
317 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
318 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
319 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
320 "no vlan tag": simple_tcp_packet(),
321 }
322
323 self.verify_match(match, matching, nonmatching)
324
325class VlanVID(MatchTest):
326 """
327 Match on VLAN VID
328 """
329 def runTest(self):
330 match = ofp.match([
331 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
332 ])
333
334 matching = {
335 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
336 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
337 }
338
339 nonmatching = {
340 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
341 "no vlan tag": simple_tcp_packet(),
342 }
343
344 self.verify_match(match, matching, nonmatching)
345
Rich Laned51b94f2013-07-16 13:29:55 -0700346class VlanVIDMasked(MatchTest):
347 """
348 Match on VLAN VID (masked)
349 """
350 def runTest(self):
351 match = ofp.match([
352 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT|3, ofp.OFPVID_PRESENT|3),
353 ])
354
355 matching = {
356 "vid=3 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=3, vlan_pcp=2),
357 "vid=7 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=7, vlan_pcp=2),
358 "vid=11 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=11, vlan_pcp=2),
359 }
360
361 nonmatching = {
362 "vid=0 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=2),
363 "vid=1 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=1, vlan_pcp=2),
364 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
365 "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
366 "no vlan tag": simple_tcp_packet(),
367 }
368
369 self.verify_match(match, matching, nonmatching)
370
Rich Lanea8d74912013-07-16 10:10:39 -0700371class VlanPCP(MatchTest):
372 """
373 Match on VLAN PCP (VID matched)
374 """
375 def runTest(self):
376 match = ofp.match([
377 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
378 ofp.oxm.vlan_pcp(3),
379 ])
380
381 matching = {
382 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
383 }
384
385 nonmatching = {
386 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
387 "no vlan tag": simple_tcp_packet(),
388 }
389
390 self.verify_match(match, matching, nonmatching)
391
Rich Laned51b94f2013-07-16 13:29:55 -0700392@nonstandard
393class VlanPCPMasked(MatchTest):
394 """
395 Match on VLAN PCP (masked, VID matched)
396 """
397 def runTest(self):
398 match = ofp.match([
399 ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
400 ofp.oxm.vlan_pcp_masked(3, 3),
401 ])
402
403 matching = {
404 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
405 "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
406 }
407
408 nonmatching = {
409 "vid=2 pcp=1": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=1),
410 "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=2),
411 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
412 "vid=2 pcp=5": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=5),
413 "vid=2 pcp=6": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=6),
414 "no vlan tag": simple_tcp_packet(),
415 }
416
417 self.verify_match(match, matching, nonmatching)
418
Rich Lanea8d74912013-07-16 10:10:39 -0700419class VlanPCPAnyVID(MatchTest):
420 """
421 Match on VLAN PCP (VID present)
422 """
423 def runTest(self):
424 match = ofp.match([
425 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
426 ofp.oxm.vlan_pcp(3),
427 ])
428
429 matching = {
430 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
431 "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=3),
432 }
433
434 nonmatching = {
435 "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
436 "no vlan tag": simple_tcp_packet(),
437 }
438
439 self.verify_match(match, matching, nonmatching)
440
441class VlanPresent(MatchTest):
442 """
443 Match on any VLAN tag (but must be present)
444 """
445 def runTest(self):
446 match = ofp.match([
447 ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
448 ])
449
450 matching = {
451 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
452 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
453 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
454 }
455
456 nonmatching = {
457 "no vlan tag": simple_tcp_packet()
458 }
459
460 self.verify_match(match, matching, nonmatching)
461
462class VlanAbsent(MatchTest):
463 """
464 Match on absent VLAN tag
465 """
466 def runTest(self):
467 match = ofp.match([
468 ofp.oxm.vlan_vid(ofp.OFPVID_NONE),
469 ])
470
471 matching = {
472 "no vlan tag": simple_tcp_packet()
473 }
474
475 nonmatching = {
476 "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
477 "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
478 "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
479 }
480
481 self.verify_match(match, matching, nonmatching)
Rich Lane11f6d772013-07-17 15:27:46 -0700482
483class IPv4Dscp(MatchTest):
484 """
485 Match on ipv4 dscp
486 """
487 def runTest(self):
488 match = ofp.match([
489 ofp.oxm.eth_type(0x0800),
490 ofp.oxm.ip_dscp(4),
491 ])
492
493 matching = {
494 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
495 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
496 }
497
498 nonmatching = {
499 "dscp=5 ecn=0": simple_tcp_packet(ip_tos=0x14),
500 }
501
502 self.verify_match(match, matching, nonmatching)
503
504# TODO IPv6 dscp
505
506class IPv4Ecn(MatchTest):
507 """
508 Match on ipv4 ecn
509 """
510 def runTest(self):
511 match = ofp.match([
512 ofp.oxm.eth_type(0x0800),
513 ofp.oxm.ip_ecn(2),
514 ])
515
516 matching = {
517 "dscp=4 ecn=2": simple_tcp_packet(ip_tos=0x12),
518 "dscp=6 ecn=2": simple_tcp_packet(ip_tos=0x1a),
519 }
520
521 nonmatching = {
522 "dscp=4 ecn=0": simple_tcp_packet(ip_tos=0x10),
523 "dscp=4 ecn=3": simple_tcp_packet(ip_tos=0x13),
524 }
525
526 self.verify_match(match, matching, nonmatching)
527
528# TODO IPv6 ecn
Rich Lane6b848af2013-07-17 15:35:36 -0700529
530class IPv4ProtoTCP(MatchTest):
531 """
532 Match on ipv4 protocol field (TCP)
533 """
534 def runTest(self):
535 match = ofp.match([
536 ofp.oxm.eth_type(0x0800),
537 ofp.oxm.ip_proto(6),
538 ])
539
540 matching = {
541 "tcp": simple_tcp_packet(),
542 }
543
544 nonmatching = {
545 "udp": simple_udp_packet(),
546 "icmp": simple_icmp_packet(),
547 }
548
549 self.verify_match(match, matching, nonmatching)
550
551# TODO IPv6 protocol (TCP)
552
553class IPv4ProtoUDP(MatchTest):
554 """
555 Match on ipv4 protocol field (UDP)
556 """
557 def runTest(self):
558 match = ofp.match([
559 ofp.oxm.eth_type(0x0800),
560 ofp.oxm.ip_proto(17),
561 ])
562
563 matching = {
564 "udp": simple_udp_packet(),
565 }
566
567 nonmatching = {
568 "tcp": simple_tcp_packet(),
569 "icmp": simple_icmp_packet(),
570 }
571
572 self.verify_match(match, matching, nonmatching)
573
574# TODO IPv6 protocol (UDP)
575
576class IPv4ProtoICMP(MatchTest):
577 """
578 Match on ipv4 protocol field (ICMP)
579 """
580 def runTest(self):
581 match = ofp.match([
582 ofp.oxm.eth_type(0x0800),
583 ofp.oxm.ip_proto(1),
584 ])
585
586 matching = {
587 "icmp": simple_icmp_packet(),
588 }
589
590 nonmatching = {
591 "tcp": simple_tcp_packet(),
592 "udp": simple_udp_packet(),
593 }
594
595 self.verify_match(match, matching, nonmatching)
596
597# TODO IPv6 protocol (ICMP)
Rich Lane05e756b2013-07-17 15:48:16 -0700598
Rich Lane3030a4f2013-07-17 16:21:45 -0700599class IPv4Src(MatchTest):
600 """
601 Match on ipv4 source address
602 """
603 def runTest(self):
604 match = ofp.match([
605 ofp.oxm.eth_type(0x0800),
606 ofp.oxm.ipv4_src(0xc0a80001), # 192.168.0.1
607 ])
608
609 matching = {
610 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
611 }
612
613 nonmatching = {
614 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
615 "255.255.255.255": simple_tcp_packet(ip_src='255.255.255.255'),
616 }
617
618 self.verify_match(match, matching, nonmatching)
619
620class IPv4SrcSubnetMasked(MatchTest):
621 """
622 Match on ipv4 source address (subnet masked)
623 """
624 def runTest(self):
625 match = ofp.match([
626 ofp.oxm.eth_type(0x0800),
627 # 192.168.0.0/20 (255.255.240.0)
628 ofp.oxm.ipv4_src_masked(0xc0a80000, 0xfffff000),
629 ])
630
631 matching = {
632 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
633 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
634 "192.168.4.2": simple_tcp_packet(ip_src='192.168.4.2'),
635 "192.168.0.0": simple_tcp_packet(ip_src='192.168.0.0'),
636 "192.168.15.255": simple_tcp_packet(ip_src='192.168.15.255'),
637 }
638
639 nonmatching = {
640 "192.168.16.0": simple_tcp_packet(ip_src='192.168.16.0'),
641 "192.167.255.255": simple_tcp_packet(ip_src='192.167.255.255'),
642 "192.168.31.1": simple_tcp_packet(ip_src='192.168.31.1'),
643 }
644
645 self.verify_match(match, matching, nonmatching)
646
647class IPv4SrcMasked(MatchTest):
648 """
649 Match on ipv4 source address (arbitrarily masked)
650 """
651 def runTest(self):
652 match = ofp.match([
653 ofp.oxm.eth_type(0x0800),
654 # 192.168.0.1 255.254.255.255
655 ofp.oxm.ipv4_src_masked(0xc0a80001, 0xfffeffff),
656 ])
657
658 matching = {
659 "192.168.0.1": simple_tcp_packet(ip_src='192.168.0.1'),
660 "192.169.0.1": simple_tcp_packet(ip_src='192.169.0.1'),
661 }
662
663 nonmatching = {
664 "192.168.0.2": simple_tcp_packet(ip_src='192.168.0.2'),
665 "192.167.0.1": simple_tcp_packet(ip_src='192.167.0.1'),
666 }
667
668 self.verify_match(match, matching, nonmatching)
669
670class IPv4Dst(MatchTest):
671 """
672 Match on ipv4 source address
673 """
674 def runTest(self):
675 match = ofp.match([
676 ofp.oxm.eth_type(0x0800),
677 ofp.oxm.ipv4_dst(0xc0a80001), # 192.168.0.1
678 ])
679
680 matching = {
681 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
682 }
683
684 nonmatching = {
685 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
686 "255.255.255.255": simple_tcp_packet(ip_dst='255.255.255.255'),
687 }
688
689 self.verify_match(match, matching, nonmatching)
690
691class IPv4DstSubnetMasked(MatchTest):
692 """
693 Match on ipv4 source address (subnet masked)
694 """
695 def runTest(self):
696 match = ofp.match([
697 ofp.oxm.eth_type(0x0800),
698 # 192.168.0.0/20 (255.255.240.0)
699 ofp.oxm.ipv4_dst_masked(0xc0a80000, 0xfffff000),
700 ])
701
702 matching = {
703 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
704 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
705 "192.168.4.2": simple_tcp_packet(ip_dst='192.168.4.2'),
706 "192.168.0.0": simple_tcp_packet(ip_dst='192.168.0.0'),
707 "192.168.15.255": simple_tcp_packet(ip_dst='192.168.15.255'),
708 }
709
710 nonmatching = {
711 "192.168.16.0": simple_tcp_packet(ip_dst='192.168.16.0'),
712 "192.167.255.255": simple_tcp_packet(ip_dst='192.167.255.255'),
713 "192.168.31.1": simple_tcp_packet(ip_dst='192.168.31.1'),
714 }
715
716 self.verify_match(match, matching, nonmatching)
717
718class IPv4DstMasked(MatchTest):
719 """
720 Match on ipv4 source address (arbitrarily masked)
721 """
722 def runTest(self):
723 match = ofp.match([
724 ofp.oxm.eth_type(0x0800),
725 # 192.168.0.1 255.254.255.255
726 ofp.oxm.ipv4_dst_masked(0xc0a80001, 0xfffeffff),
727 ])
728
729 matching = {
730 "192.168.0.1": simple_tcp_packet(ip_dst='192.168.0.1'),
731 "192.169.0.1": simple_tcp_packet(ip_dst='192.169.0.1'),
732 }
733
734 nonmatching = {
735 "192.168.0.2": simple_tcp_packet(ip_dst='192.168.0.2'),
736 "192.167.0.1": simple_tcp_packet(ip_dst='192.167.0.1'),
737 }
738
739 self.verify_match(match, matching, nonmatching)
740
741# TODO IPv6 source address
742# TODO IPv6 destination address
743
Rich Lane05e756b2013-07-17 15:48:16 -0700744class IPv4TCPSrc(MatchTest):
745 """
746 Match on ipv4 tcp source port
747 """
748 def runTest(self):
749 match = ofp.match([
750 ofp.oxm.eth_type(0x0800),
751 ofp.oxm.ip_proto(6),
752 ofp.oxm.tcp_src(53),
753 ])
754
755 matching = {
756 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
757 }
758
759 nonmatching = {
760 "tcp sport=52": simple_tcp_packet(tcp_sport=52),
761 "udp sport=53": simple_udp_packet(udp_sport=53),
762 }
763
764 self.verify_match(match, matching, nonmatching)
765
766# TODO IPv6 tcp source port
767
768class IPv4TCPDst(MatchTest):
769 """
770 Match on ipv4 tcp destination port
771 """
772 def runTest(self):
773 match = ofp.match([
774 ofp.oxm.eth_type(0x0800),
775 ofp.oxm.ip_proto(6),
776 ofp.oxm.tcp_dst(53),
777 ])
778
779 matching = {
780 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
781 }
782
783 nonmatching = {
784 "tcp dport=52": simple_tcp_packet(tcp_dport=52),
785 "udp dport=53": simple_udp_packet(udp_dport=53),
786 }
787
788 self.verify_match(match, matching, nonmatching)
789
790# TODO IPv6 tcp destination port
791
792class IPv4UDPSrc(MatchTest):
793 """
794 Match on ipv4 udp source port
795 """
796 def runTest(self):
797 match = ofp.match([
798 ofp.oxm.eth_type(0x0800),
799 ofp.oxm.ip_proto(17),
800 ofp.oxm.udp_src(53),
801 ])
802
803 matching = {
804 "udp sport=53": simple_udp_packet(udp_sport=53),
805 }
806
807 nonmatching = {
808 "udp sport=52": simple_udp_packet(udp_sport=52),
809 "tcp sport=53": simple_tcp_packet(tcp_sport=53),
810 }
811
812 self.verify_match(match, matching, nonmatching)
813
814# TODO IPv6 udp source port
815
816class IPv4UDPDst(MatchTest):
817 """
818 Match on ipv4 udp destination port
819 """
820 def runTest(self):
821 match = ofp.match([
822 ofp.oxm.eth_type(0x0800),
823 ofp.oxm.ip_proto(17),
824 ofp.oxm.udp_dst(53),
825 ])
826
827 matching = {
828 "udp dport=53": simple_udp_packet(udp_dport=53),
829 }
830
831 nonmatching = {
832 "udp dport=52": simple_udp_packet(udp_dport=52),
833 "tcp dport=53": simple_tcp_packet(tcp_dport=53),
834 }
835
836 self.verify_match(match, matching, nonmatching)
837
838# TODO IPv6 udp destination port
Rich Laneee574362013-07-17 16:40:07 -0700839
840class IPv4ICMPType(MatchTest):
841 """
842 Match on ipv4 icmp type
843 """
844 def runTest(self):
845 match = ofp.match([
846 ofp.oxm.eth_type(0x0800),
847 ofp.oxm.ip_proto(1),
848 ofp.oxm.icmpv4_type(3),
849 ])
850
851 matching = {
852 "type=3 code=1": simple_icmp_packet(icmp_type=3, icmp_code=1),
853 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
854 }
855
856 nonmatching = {
857 "type=2 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
858 }
859
860 self.verify_match(match, matching, nonmatching)
861
862class IPv4ICMPCode(MatchTest):
863 """
864 Match on ipv4 icmp code
865 """
866 def runTest(self):
867 match = ofp.match([
868 ofp.oxm.eth_type(0x0800),
869 ofp.oxm.ip_proto(1),
870 ofp.oxm.icmpv4_code(2),
871 ])
872
873 matching = {
874 "type=3 code=2": simple_icmp_packet(icmp_type=3, icmp_code=2),
875 "type=5 code=2": simple_icmp_packet(icmp_type=5, icmp_code=2),
876 }
877
878 nonmatching = {
879 "type=3 code=1": simple_icmp_packet(icmp_type=2, icmp_code=1),
880 }
881
882 self.verify_match(match, matching, nonmatching)
883
884# TODO ipv6 icmp type
885# TODO ipv6 icmp code
Rich Lane6b770992013-07-17 17:11:24 -0700886
887class ArpOp(MatchTest):
888 """
889 Match on ARP operation
890 """
891 def runTest(self):
892 match = ofp.match([
893 ofp.oxm.eth_type(0x0806),
894 ofp.oxm.arp_op(3),
895 ])
896
897 matching = {
898 "op=3": simple_arp_packet(arp_op=3),
899 }
900
901 nonmatching = {
902 "op=4": simple_arp_packet(arp_op=4),
903 }
904
905 self.verify_match(match, matching, nonmatching)
Rich Lane503a2de2013-07-17 17:20:58 -0700906
907class ArpSPA(MatchTest):
908 """
909 Match on ARP sender IP
910 """
911 def runTest(self):
912 match = ofp.match([
913 ofp.oxm.eth_type(0x0806),
914 ofp.oxm.arp_spa(0xc0a80001), # 192.168.0.1
915 ])
916
917 matching = {
918 "192.168.0.1": simple_arp_packet(ip_snd="192.168.0.1"),
919 }
920
921 nonmatching = {
922 "192.168.0.2": simple_arp_packet(ip_snd="192.168.0.2"),
923 }
924
925 self.verify_match(match, matching, nonmatching)
926
927class ArpTPA(MatchTest):
928 """
929 Match on ARP target IP
930 """
931 def runTest(self):
932 match = ofp.match([
933 ofp.oxm.eth_type(0x0806),
934 ofp.oxm.arp_tpa(0xc0a80001), # 192.168.0.1
935 ])
936
937 matching = {
938 "192.168.0.1": simple_arp_packet(ip_tgt="192.168.0.1"),
939 }
940
941 nonmatching = {
942 "192.168.0.2": simple_arp_packet(ip_tgt="192.168.0.2"),
943 }
944
945 self.verify_match(match, matching, nonmatching)