initial OpenFlow 1.3 match tests
The only tests currently implemented are for the VLAN tag.
diff --git a/tests-1.3/match.py b/tests-1.3/match.py
new file mode 100644
index 0000000..3d5f453
--- /dev/null
+++ b/tests-1.3/match.py
@@ -0,0 +1,213 @@
+# Distributed under the OpenFlow Software License (see LICENSE)
+# Copyright (c) 2010 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+"""
+Flow match test cases
+
+These tests check the behavior of each match field. The only action used is a
+single output.
+"""
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+
+from oftest.testutils import *
+
+class MatchTest(base_tests.SimpleDataPlane):
+ """
+ Base class for match tests
+ """
+
+ def verify_match(self, match, matching, nonmatching):
+ """
+ Verify matching behavior
+
+ Checks that all the packets in 'matching' match 'match', and that
+ the packets in 'nonmatching' do not.
+
+ 'match' is a LOXI match object. 'matching' and 'nonmatching' are
+ dicts mapping from string names (used in log messages) to string
+ packet data.
+ """
+ ports = sorted(config["port_map"].keys())
+ in_port = ports[0]
+ out_port = ports[1]
+
+ logging.info("Running match test for %s", match.show())
+
+ delete_all_flows(self.controller)
+
+ logging.info("Inserting flow sending matching packets to port %d", out_port)
+ request = ofp.message.flow_add(
+ table_id=0,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.output(
+ port=out_port,
+ max_len=ofp.OFPCML_NO_BUFFER)])],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1000)
+ self.controller.message_send(request)
+
+ logging.info("Inserting match-all flow sending packets to controller")
+ request = ofp.message.flow_add(
+ table_id=0,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.output(
+ port=ofp.OFPP_CONTROLLER,
+ max_len=ofp.OFPCML_NO_BUFFER)])],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ self.controller.message_send(request)
+
+ do_barrier(self.controller)
+
+ for name, pkt in matching.items():
+ logging.info("Sending matching packet %s, expecting output to port %d", repr(name), out_port)
+ pktstr = str(pkt)
+ self.dataplane.send(in_port, pktstr)
+ receive_pkt_verify(self, [out_port], pktstr, in_port)
+
+ for name, pkt in nonmatching.items():
+ logging.info("Sending non-matching packet %s, expecting packet-in", repr(name))
+ pktstr = str(pkt)
+ self.dataplane.send(in_port, pktstr)
+ verify_packet_in(self, pktstr, in_port, ofp.OFPR_ACTION)
+
+class VlanExact(MatchTest):
+ """
+ Match on VLAN VID and PCP
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
+ ofp.oxm.vlan_pcp(3),
+ ])
+
+ matching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ }
+
+ nonmatching = {
+ "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "vid=4 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "vid=2 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "no vlan tag": simple_tcp_packet(),
+ }
+
+ self.verify_match(match, matching, nonmatching)
+
+class VlanVID(MatchTest):
+ """
+ Match on VLAN VID
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
+ ])
+
+ matching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ "vid=2 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=7),
+ }
+
+ nonmatching = {
+ "vid=4 pcp=2": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=4, vlan_pcp=2),
+ "no vlan tag": simple_tcp_packet(),
+ }
+
+ self.verify_match(match, matching, nonmatching)
+
+class VlanPCP(MatchTest):
+ """
+ Match on VLAN PCP (VID matched)
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT|2),
+ ofp.oxm.vlan_pcp(3),
+ ])
+
+ matching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ }
+
+ nonmatching = {
+ "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
+ "no vlan tag": simple_tcp_packet(),
+ }
+
+ self.verify_match(match, matching, nonmatching)
+
+class VlanPCPAnyVID(MatchTest):
+ """
+ Match on VLAN PCP (VID present)
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
+ ofp.oxm.vlan_pcp(3),
+ ])
+
+ matching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ "vid=0 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=3),
+ }
+
+ nonmatching = {
+ "vid=2 pcp=4": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=4),
+ "no vlan tag": simple_tcp_packet(),
+ }
+
+ self.verify_match(match, matching, nonmatching)
+
+class VlanPresent(MatchTest):
+ """
+ Match on any VLAN tag (but must be present)
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT),
+ ])
+
+ matching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
+ "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
+ }
+
+ nonmatching = {
+ "no vlan tag": simple_tcp_packet()
+ }
+
+ self.verify_match(match, matching, nonmatching)
+
+class VlanAbsent(MatchTest):
+ """
+ Match on absent VLAN tag
+ """
+ def runTest(self):
+ match = ofp.match([
+ ofp.oxm.vlan_vid(ofp.OFPVID_NONE),
+ ])
+
+ matching = {
+ "no vlan tag": simple_tcp_packet()
+ }
+
+ nonmatching = {
+ "vid=2 pcp=3": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=3),
+ "vid=0 pcp=7": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=0, vlan_pcp=7),
+ "vid=2 pcp=0": simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2, vlan_pcp=0),
+ }
+
+ self.verify_match(match, matching, nonmatching)