コード例 #1
0
    def test_push_pop_vlan(self):
        """Test push pop combo is ignored

                      rule1                        rule2
        M: VLAN_VID:1                         M: VLAN_VID:1
        A: PUSH_VLAN, VLAN_VID:2, POP_VLAN    A:

        Expected rule1
        Then try combos without rule1 match, and without rule2 match
        """

        rule1 = Rule(priority=0, match=self.vlan_vid_1)
        rule1.instructions.apply_actions.append("PUSH_VLAN", 0x800)
        rule1.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 2))
        rule1.instructions.apply_actions.append("POP_VLAN", None)
        rule2 = Rule(priority=0, match=self.vlan_vid_1)
        self.assertEqual(rule1.merge(rule2, False), rule1)
        # Check without rule2 match
        self.assertEqual(rule1.merge(Rule(priority=0), False), rule1)
        # Check without rule1 match
        rule1_nomatch = Rule(priority=0)
        rule1_nomatch.instructions.apply_actions = rule1.instructions.apply_actions.copy(
        )
        self.assertEqual(rule1_nomatch.merge(rule2, False), rule1)
        # The resulting rule is valid openflow
        self.assertEqual(rule1_nomatch.merge(rule2, True), rule1)
        self.assertEqual(rule1_nomatch + rule2, rule1)
コード例 #2
0
    def test_merge_complex_match(self):
        """ Test merging """
        part1 = Rule(priority=0,
                     match=Match([("IPV4_SRC", 0x12340000, 0xFFFF0000)]))
        part2 = Rule(priority=0,
                     match=Match([("IPV4_SRC", 0x00005678, 0x0000FFFF)]))
        expct = Rule(priority=0,
                     match=Match([("IPV4_SRC", 0x12345678, 0xFFFFFFFF)]))

        self.assertEqual(part1 + part2, expct)
コード例 #3
0
    def test_simple(self):
        a = Rule(priority=0)
        b = Rule(priority=0)
        c = Rule(priority=1)
        self.assertEqual(a, b)
        self.assertNotEqual(a, c)

        with UniqueRules():
            self.assertNotEqual(a, b)
            self.assertNotEqual(a, c)

        self.assertEqual(a, b)
        self.assertNotEqual(a, c)
コード例 #4
0
    def setUp(self):
        self.f = Rule()
        self.fg1 = Group()
        self.fg1.type_ = 'INDIRECT'
        self.fg1.buckets = [ActionList([("OUTPUT", 7)])]

        self.fg2 = Group()
        self.fg2.type_ = 'INDIRECT'
        self.fg2.buckets = [ActionList(
            [("POP_MPLS", 0x800), ("OUTPUT", 8)])]
        self.act_apply1 = ActionList(
            [('GROUP', self.fg1), ("SET_FIELD", ("ETH_DST", 0x1002)), ("OUTPUT", 1)])

        self.act_apply2 = ActionList(
            [("SET_FIELD", ("ETH_DST", 0x1002)), ("OUTPUT", 4), ('GROUP', self.fg2)])

        self.act_set1 = ActionSet(
            [("SET_FIELD", ("IPV4_SRC", 123)), ("OUTPUT", 5)])

        self.act_set2 = ActionSet(
            [("SET_FIELD", ("IPV4_SRC", 321)), ("POP_VLAN", None), ("OUTPUT", 6)])

        self.inst1 = Instructions()
        self.inst1.apply_actions = self.act_apply1
        self.inst1.write_actions = self.act_set1

        self.inst2 = Instructions()
        self.inst2.apply_actions = self.act_apply2
        self.inst2.write_actions = self.act_set2
コード例 #5
0
    def test_equal_matches(self):
        matcha = Match([("VLAN_VID", 0x1001, None)])
        matchb = Match([("VLAN_VID", 0x1001, None)])

        f1 = Rule(priority=100, match=matcha, instructions=self.inst1, table=1)
        f2 = Rule(priority=100, match=matcha, instructions=self.inst2, table=2)

        res = simulate_actions(f1, f2)
        self.assertEqual(res[0], None)
        # act_apply1 + act_apply2 + merge(act_set1, act_set2)
        self.assertEqual(res[1],
            ActionList(self.act_apply1+self.act_apply2+(self.act_set1+self.act_set2)))
        self.assertEqual(res[2], None)

        print(self.act_set1)
        print(self.act_set2)
        print(self.act_set1 + self.act_set2)
コード例 #6
0
    def test_convert_flow1(self):
        """ Test converting OFPFlowMod and OFPFlowStats from ovs """

        expected_insts = Instructions()
        expected_insts.apply_actions.append("POP_VLAN", None)
        expected_insts.apply_actions.append("SET_FIELD",
                                            ("ETH_DST", 0x101010101010))
        expected_insts.apply_actions.append("OUTPUT", 7)
        expected_insts.goto_table = 4

        expected = Rule(priority=789,
                        cookie=0xABCD,
                        table=3,
                        match=Match([("ETH_TYPE", 0x0800, None),
                                     ("IPV4_SRC", 1, None),
                                     ("VLAN_VID", 0x1100, None)]),
                        instructions=expected_insts)

        handcrafted = (
            "priority=789 cookie=0xABCD table=3 eth_type=0x800,ip_src=0.0.0.1,vlan_vid=0x1100 actions=pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7,goto_table:4"
        )

        # After going in and out of OVS, ovs-ofctl -O OpenFlowXX dumpflows br0
        ofctl10 = " cookie=0xabcd, duration=30.907s, table=3, n_packets=0, n_bytes=0, priority=789,ip,dl_vlan=256,nw_src=0.0.0.1 actions=strip_vlan,mod_dl_dst:10:10:10:10:10:10,output:7,resubmit(,4)"
        ofctl13 = " cookie=0xabcd, duration=24.104s, table=3, n_packets=0, n_bytes=0, priority=789,ip,dl_vlan=256,nw_src=0.0.0.1 actions=pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7,goto_table:4"
        ofctl13_nostats = " cookie=0xabcd, table=3, priority=789,ip,dl_vlan=256,nw_src=0.0.0.1 actions=pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7,goto_table:4"
        ofctl15 = " cookie=0xabcd, duration=28.969s, table=3, n_packets=0, n_bytes=0, idle_age=28, priority=789,ip,dl_vlan=256,nw_src=0.0.0.1 actions=pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7,goto_table:4"
        # From ovs-appctl bridge/dumpflows
        appctl = "table_id=3, duration=51s, n_packets=0, n_bytes=0, priority=789,ip,dl_vlan=256,nw_src=0.0.0.1,actions=pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7,goto_table:4"

        rule_hand = rule_from_ovs(handcrafted, {})
        rule_10 = rule_from_ovs(ofctl10, {})
        rule_13 = rule_from_ovs(ofctl13, {})
        rule_13nostats = rule_from_ovs(ofctl13_nostats, {})
        rule_15 = rule_from_ovs(ofctl15, {})
        rule_appctl = rule_from_ovs(appctl, {})

        self.assertEqual(rule_hand, expected)
        self.assertEqual(rule_10, expected)
        self.assertEqual(rule_13, expected)
        self.assertEqual(rule_13nostats, expected)
        self.assertEqual(rule_15, expected)

        # appctl output doesn't display cookies
        expected.cookie = None
        self.assertEqual(rule_appctl, expected)
コード例 #7
0
    def test_convert_flow2(self):
        """ Test converting OFPFlowMod and OFPFlowStats from ovs """

        match = Match([("IPV4_SRC", 1, None), ("ETH_TYPE", 0x800, None),
                       ("VLAN_VID", 0x1100, None)])
        instructions = Instructions()
        instructions.goto_table = 9
        instructions.clear_actions = True
        instructions.write_actions.append("POP_VLAN", None)
        instructions.write_actions.append("SET_FIELD",
                                          ("ETH_DST", 0x101010101010))
        instructions.write_actions.append("OUTPUT", 7)
        instructions.write_metadata = (0x99, 0xff)

        expected = Rule(priority=0x8000,
                        cookie=0xABCD,
                        table=0,
                        match=match,
                        instructions=instructions)

        # Now for write actions and clear actions etc.
        # Note priority=0x8000 is the default priority and ovs omits it,
        # Similarly table 0 is often omitted
        handcrafted = (
            "priority=0x8000 cookie=0xABCD table=0 eth_type=0x800,ip_src=0.0.0.1,vlan_vid=0x1100 actions=clear_actions,write_actions(pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7),write_metadata:0x99/0xff,goto_table:9"
        )

        ofctl11 = " cookie=0xabcd, duration=10.778s, table=0, n_packets=0, n_bytes=0, ip,dl_vlan=256,nw_src=0.0.0.1 actions=clear_actions,write_actions(pop_vlan,mod_dl_dst:10:10:10:10:10:10,output:7),write_metadata:0x99/0xff,goto_table:9"
        # Also the same for of12 to of15
        ofctl13 = " cookie=0xabcd, duration=24.097s, table=0, n_packets=0, n_bytes=0, ip,dl_vlan=256,nw_src=0.0.0.1 actions=clear_actions,write_actions(pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7),write_metadata:0x99/0xff,goto_table:9"
        # From ovs-appctl bridge/dumpflows
        appctl = "duration=369s, n_packets=0, n_bytes=0, ip,dl_vlan=256,nw_src=0.0.0.1,actions=clear_actions,write_actions(pop_vlan,set_field:10:10:10:10:10:10->eth_dst,output:7),write_metadata:0x99/0xff,goto_table:9"

        rule_hand = rule_from_ovs(handcrafted, {})
        rule_11 = rule_from_ovs(ofctl11, {})
        rule_13 = rule_from_ovs(ofctl13, {})
        rule_appctl = rule_from_ovs(appctl, {})

        self.assertEqual(rule_hand, expected)
        self.assertEqual(rule_11, expected)
        self.assertEqual(rule_13, expected)

        # appctl output doesn't display cookies
        expected.cookie = None
        self.assertEqual(rule_appctl, expected)
コード例 #8
0
    def test_action_independence_multiple(self):
        """ Testing messy combinations of mutliple set fields

            Combinations of multiple fields, some overlapping some not.
            And alternative values for different outputs.

            Base case:
            dst:0/31 -> dst:1, src:2, output:1, dst:2, src:1, output:2
        """
        DST1, DST2 = ('SET_FIELD', ('IPV4_DST', 0x1)), ('SET_FIELD', ('IPV4_DST', 0x2))
        SRC1, SRC2 = ('SET_FIELD', ('IPV4_SRC', 0x1)), ('SET_FIELD', ('IPV4_SRC', 0x2))
        OUT1, OUT2 = ('OUTPUT', 1), ('OUTPUT', 2)
        n1 = normalise([
            Rule(priority=10,
                 match=Match([('IPV4_DST', 0x0, 0xFFFFFFFE)]),
                 instructions=inst_from_acts([DST1, SRC2, OUT1, DST2, SRC1, OUT2])),
            Rule(priority=0)
            ], match_redundancy=True)
        """
            dst:1, src:2 -> output:1, dst:2, src:1, output:2
            dst:0/31 -> dst:1, src:2, output:1, dst:2, src:1, output:2
        """
        n2 = normalise([
            Rule(priority=10,
                 match=Match([('IPV4_DST', 1, None),
                              ('IPV4_SRC', 2, None)]),
                 instructions=inst_from_acts([OUT1, DST2, SRC1, OUT2])),
            Rule(priority=9,
                 match=Match([('IPV4_DST', 0x0, 0xFFFFFFFE)]),
                 instructions=inst_from_acts([DST1, SRC2, OUT1, DST2, SRC1, OUT2])),
            Rule(priority=0)
            ], match_redundancy=True)
        """
            dst:1 -> src:2, output:1, dst:2, src:1, output:2
            dst:0/31 -> dst:1, src:2, output:1, dst:2, src:1, output:2
        """
        n3 = normalise([
            Rule(priority=10,
                 match=Match([('IPV4_DST', 1, None)]),
                 instructions=inst_from_acts([SRC2, OUT1, DST2, SRC1, OUT2])),
            Rule(priority=9,
                 match=Match([('IPV4_DST', 0x0, 0xFFFFFFFE)]),
                 instructions=inst_from_acts([DST1, SRC2, OUT1, DST2, SRC1, OUT2])),
            Rule(priority=0)
            ], match_redundancy=True)

        self.assertTrue(check_equal(n1, n2))
        self.assertTrue(check_equal(n2, n3))
        self.assertTrue(check_equal(n1, n3))
コード例 #9
0
    def test_merging_priorities(self):
        """ Merging priorities is supposed to add priorities.

            Doing this works with merging rules (which have already been
            priority adjusted) to result in the correct priority.
        """
        rule1 = Rule(priority=1)
        rule2 = Rule(priority=2)
        rule100 = Rule(priority=100)
        rule200 = Rule(priority=200)

        self.assertEqual(rule1.merge(rule1).priority, 2)
        self.assertEqual(rule1.merge(rule2).priority, 3)
        self.assertEqual(rule200.merge(rule100).priority, 300)
        self.assertEqual((rule200 + rule100).priority, 300)
コード例 #10
0
    def test_convert_flow(self):
        """ Test converting OFPFlowMod and OFPFlowStats from ryu """
        ryu_match = OFPMatch(ipv4_src=1, eth_type=0x8100, vlan_vid=0x1100)
        ryu_write_actions = OFPInstructionActions(OFPIT_WRITE_ACTIONS, [
            OFPActionPopVlan(),
            OFPActionSetField(eth_dst="10:10:10:10:10:10"),
            OFPActionOutput(7)
        ])
        ryu_instructions = [
            OFPInstructionActions(OFPIT_CLEAR_ACTIONS, []), ryu_write_actions,
            OFPInstructionGotoTable(9),
            OFPInstructionWriteMetadata(0x99, 0xff)
        ]
        ryu_flow_mod = OFPFlowMod(datapath=None,
                                  cookie=0xABCD,
                                  table_id=3,
                                  command=OFPFC_ADD,
                                  priority=789,
                                  match=ryu_match,
                                  instructions=ryu_instructions)
        ryu_flow_stats = OFPFlowStats(cookie=0xABCD,
                                      table_id=3,
                                      priority=789,
                                      match=ryu_match,
                                      instructions=ryu_instructions)

        match = Match([("IPV4_SRC", 1, None), ("ETH_TYPE", 0x8100, None),
                       ("VLAN_VID", 0x1100, None)])
        instructions = Instructions()
        instructions.goto_table = 9
        instructions.clear_actions = True
        instructions.write_actions.append("POP_VLAN", None)
        instructions.write_actions.append("SET_FIELD",
                                          ("ETH_DST", 0x101010101010))
        instructions.write_actions.append("OUTPUT", 7)
        instructions.write_metadata = (0x99, 0xff)

        rule = Rule(priority=789,
                    cookie=0xABCD,
                    table=3,
                    match=match,
                    instructions=instructions)

        self.assertEqual(rule_from_ryu(ryu_flow_stats), rule)
        self.assertEqual(rule_from_ryu(ryu_flow_mod), rule)
コード例 #11
0
    def test_find_metadata_conflicting_paths(self):
        """ Metadata rewrite conflicting paths test

        As metadata can be set bitwise it uses a slightly different code
        path to a standard set field.

        * MD=0x10 GT=1      0x10 MD=0x1/0x1 GT=2   0x11 output1
                            *                      *
        vs. single table, note all traffic is different no set
        * drop
        """
        inst_a = Instructions()
        inst_a.goto_table = 1
        inst_a.write_metadata = (0x12, None)
        inst_b = Instructions()
        inst_b.goto_table = 2
        inst_b.write_metadata = (0x1, 0x3)
        # Note: Set VLAN applies the present bit mask so must included it
        ruleset_a = [
            Rule(priority=10, table=0,
                 instructions=inst_a),
            Rule(priority=10, table=1, match=Match([('METADATA', 0x12, None)]),
                 instructions=inst_b),
            Rule(priority=0, table=1),
            Rule(priority=10, table=2, match=Match([('METADATA', 0x11, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=0, table=2),
            ]
        ruleset_b = [
            Rule(priority=0, table=0)
            ]
        single_a = to_single_table(ruleset_a)
        single_b = to_single_table(ruleset_b)
        norm_a = normalise(single_a)
        norm_b = normalise(single_b)

        # Make sure the frozensets are made after to_single_table which changes
        # priorities which changes the Rule's hash in the frozenset
        result_ab = {
            (ruleset_a[0], ruleset_a[1], ruleset_a[3]): frozenset([(ruleset_b[0],)]),
            }
        result_ba = {
            (ruleset_b[0],): frozenset([(ruleset_a[0], ruleset_a[1], ruleset_a[3],)])
            }
        equal_ab, diff_ab = check_equal(norm_a, norm_b, diff=True)
        self.assertFalse(equal_ab)

        paths_ab = find_conflicting_paths(diff_ab, single_a, single_b)
        paths_ba = find_conflicting_paths(diff_ab, single_b, single_a)
        self.assertEqual(paths_ab, result_ab)
        self.assertNotEqual(paths_ab, result_ba)  # Sanity check
        self.assertEqual(paths_ba, result_ba)
コード例 #12
0
    def test_find_rewrite_conflicting_paths(self):
        """ Rewritten conflicting paths test

        VLAN_VID=0 SetVLAN(1), goto1      VLAN_VID=0 output:1
        *                                 VLAN_VID=1 drop
                                          *
        vs. single table, note all traffic is different no set
        * output1
        """
        inst_a = Instructions()
        inst_a.goto_table = 1
        inst_a.apply_actions.append("SET_FIELD", ("VLAN_VID", 1))
        # Note: Set VLAN applies the present bit mask so must included it
        ruleset_a = [
            Rule(priority=10, table=0,
                 match=Match([('VLAN_VID', 0x1000 | 0, None)]),
                 instructions=Instructions(dup=inst_a)),
            Rule(priority=0, table=0),
            Rule(priority=20, table=1,
                 match=Match([('VLAN_VID', 0x1000 | 0, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=20, table=1,
                 match=Match([('VLAN_VID', 0x1000 | 1, None)])),
            Rule(priority=0, table=1)
            ]
        ruleset_b = [
            Rule(priority=0, table=0, instructions=Instructions(dup=output1))
            ]
        single_a = to_single_table(ruleset_a)
        single_b = to_single_table(ruleset_b)
        norm_a = normalise(single_a)
        norm_b = normalise(single_b)

        # Make sure the frozensets are made after to_single_table which changes
        # priorities which changes the Rule's hash in the frozenset
        result_ab = {
            (ruleset_a[0], ruleset_a[3]): frozenset([(ruleset_b[0],)]),
            (ruleset_a[1],): frozenset([(ruleset_b[0],)])
            }
        result_ba = {
            (ruleset_b[0],): frozenset([(ruleset_a[0], ruleset_a[3]),
                                        (ruleset_a[1],)])
            }

        equal_ab, diff_ab = check_equal(norm_a, norm_b, diff=True)
        self.assertFalse(equal_ab)

        paths_ab = find_conflicting_paths(diff_ab, single_a, single_b)
        paths_ba = find_conflicting_paths(diff_ab, single_b, single_a)
        self.assertEqual(paths_ab, result_ab)
        self.assertNotEqual(paths_ab, result_ba)  # Sanity check
        self.assertEqual(paths_ba, result_ba)
コード例 #13
0
    def test_simple_merge_match(self):
        """ Test merging matches works """
        fsrc2 = Rule(priority=0, match=self.ipv4_src2)
        fdst2 = Rule(priority=0, match=self.ipv4_dst2)
        fsrc1 = Rule(priority=0, match=self.ipv4_src1)

        f_expected = Rule(priority=0, match=self.ipv4_src2_dst2)
        # Merge with two different fields
        self.assertEqual(fsrc2.merge(fdst2), f_expected)
        self.assertEqual(fdst2.merge(fsrc2), f_expected)
        self.assertEqual(fsrc2 + fdst2, f_expected)
        self.assertEqual(fdst2 + fsrc2, f_expected)

        # Merge self with self
        self.assertEqual(fsrc2 + fsrc2, fsrc2)

        # Sanity checks
        self.assertNotEqual(fsrc2, fdst2)
        self.assertNotEqual(fsrc2 + fsrc2, fdst2)

        # Exception if match set becomes empty IP:1 intersect IP:2
        self.assertRaises(MergeException, lambda: fsrc2 + fsrc1)
        self.assertRaises(MergeException, lambda: (fdst2 + fsrc1) + fsrc2)
コード例 #14
0
    def test_pop_vlan(self):
        """
        Test the POP_VLAN, MATCH VLAN_VID case
        """

        # Test single pop, i.e. match 2nd header
        rule1 = Rule(priority=0, match=self.vlan_vid_1)
        rule1.instructions.apply_actions.append("POP_VLAN", None)
        rule2 = Rule(priority=0, match=self.vlan_vid_2)

        expt_m = Match([("VLAN_VID", 0x1001, None),
                        ("VLAN_VID1", 0x1002, None)])
        expt = Rule(priority=0, match=expt_m)
        expt.instructions.apply_actions.append("POP_VLAN", None)
        self.assertEqual(rule1.merge(rule2, False), expt)
        # Merging fails to return a valid openflow rule
        self.assertRaises(MergeException, lambda: rule1.merge(rule2, True))
        self.assertRaises(MergeException, lambda: rule1 + rule2)
コード例 #15
0
    def test_hash_sanity(self):
        rules = [
            Rule(priority=0),
            Rule(priority=1),
            Rule(priority=3),
            Rule(priority=5),
            Rule(priority=10),
            Rule(priority=18)
        ]
        as_set = set(rules)
        as_dict = dict(zip(rules, range(6)))

        with UniqueRules():
            unique_set = set(rules)
            unique_dict = dict(zip(rules, range(6)))

        # Sanity check everything will be hashed wrong, almost certain to fail
        self.assertNotEqual(as_set, unique_set)
        self.assertNotEqual(as_dict, unique_dict)
コード例 #16
0
    def test_set_and_match(self):
        """ Test the handling of setting a field which is later matched """
        rule1 = Rule(priority=0, match=self.ipv4_src1)
        rule1.instructions.apply_actions.append("SET_FIELD", ("IPV4_SRC", 1))
        rule2 = Rule(priority=0, match=self.ipv4_src2)
        rule2.instructions.apply_actions.append("SET_FIELD", ("IPV4_SRC", 1))
        rule3 = Rule(priority=0, match=self.ipv4_src1)
        rule4 = Rule(priority=0, match=self.ipv4_src2)
        rule5 = Rule(priority=0, match=self.ipv4_src1m)
        rule6 = Rule(priority=0, match=self.ipv4_src2m)
        rule6.instructions.apply_actions.append("SET_FIELD", ("IPV4_SRC", 1))
        """
        Working case, check IPV4_SRC is removed

        Input:
        IPV4_SRC: 2                     +   IPV4_SRC: 1
        Apply(set_field: IPV4_SRC = 1)  +   Apply()

        Expected:
        IPV4_SRC: 2
        Apply(set_field: IPV4_SRC = 1)
        """
        self.assertEqual(rule2 + rule3, rule2)
        # Check setting the field to the same is not removed
        self.assertEqual(rule1 + rule3, rule1)
        # And when masked
        self.assertEqual(rule1 + rule5, rule1)
        self.assertEqual(rule6 + rule5, rule6)
        """
        Error case, check IPV4_SRC is removed

        Input:
        IPV4_SRC: 2                     +   IPV4_SRC: 2
        Apply(set_field: IPV4_SRC = 1)  +   Apply()

        Expected:
        Error, Empty match. As traffic with IPV4_SRC: 1 cannot possibly
        match IPV4_SRC: 2 in the second rule.
        """
        self.assertRaises(MergeException, lambda: rule1 + rule4)
        # And when masked
        self.assertRaises(MergeException, lambda: rule1 + rule6)
コード例 #17
0
    def test_push_vlan(self):
        """ Push and match, later pop """
        rule1 = Rule(priority=0)
        rule1.instructions.apply_actions.append("PUSH_VLAN", 0x800)
        rule1.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 6))
        rule2 = Rule(priority=0,
                     match=Match([('VLAN_VID', 0x1006, None),
                                  ('VLAN_VID1', 0x1002, None)]))
        rule2.instructions.apply_actions.append("POP_VLAN", None)
        rule2.instructions.apply_actions.append("OUTPUT", 1)
        expt = Rule(priority=0, match=Match([('VLAN_VID', 0x1002, None)]))
        expt.instructions.apply_actions.append("PUSH_VLAN", 0x800)
        expt.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 6))
        expt.instructions.apply_actions.append("POP_VLAN", None)
        expt.instructions.apply_actions.append("OUTPUT", 1)

        self.assertEqual(rule1.merge(rule2, False), expt)
        # The resulting rule is valid openflow
        self.assertEqual(rule1.merge(rule2, True), expt)
        self.assertEqual(rule1 + rule2, expt)
コード例 #18
0
    def test_clear_action_sets(self):
        rule1 = Rule(priority=0, match=self.ipv4_src2)
        rule1.instructions.write_actions.append("SET_FIELD", ("IPV4_SRC", 1))
        rule2 = Rule(priority=0, match=self.ipv4_src2)
        rule2.instructions.write_actions.append("SET_FIELD", ("IPV4_SRC", 2))
        rule3 = Rule(priority=0, match=self.ipv4_src2)
        rule3.instructions.write_actions.append("SET_FIELD", ("IPV4_DST", 2))
        rule4 = rule3.copy()
        rule4.instructions.clear_actions = True

        # Check overwrite occurs
        self.assertEqual(rule1 + rule2, rule2)
        self.assertEqual(rule2 + rule1, rule1)

        # Check adding a mix is supported
        expected = rule1.copy()
        expected.instructions.write_actions.append("SET_FIELD",
                                                   ("IPV4_DST", 2))
        self.assertEqual(rule1 + rule3, expected)
        # sanity check
        self.assertNotEqual(rule1, expected)

        # Check Clear works
        self.assertEqual(rule1 + rule4, rule4)
コード例 #19
0

output1 = Instructions()
output1.apply_actions = ActionList([('OUTPUT', 6)])
goto1 = Instructions()
goto1.goto_table = 1
goto2 = Instructions()
goto2.goto_table = 2

"""
arp  -> drop
ip=1 -> output:1
*    -> drop
"""
data1 = [
    Rule(priority=10,
         match=Match([('ETH_TYPE', 60, None)])),
    Rule(priority=9,
         match=Match([('IPV4_DST', 1, None)]),
         instructions=Instructions(dup=output1)),
    Rule(priority=0)
    ]

"""
ip=1, arp -> drop
ip=1      -> output:1
*         -> drop
"""
data2 = [
    Rule(priority=10,
         match=Match([('IPV4_DST', 1, None),
                      ('ETH_TYPE', 60, None)])),
コード例 #20
0
    def test_redundant_vlans(self):
        """ Test the push pop combinations are correctly removed """
        PUSH, POP = ('PUSH_VLAN', 0x8100), ('POP_VLAN', None)
        VID1, VID2 = ('SET_FIELD', ('VLAN_VID', 1)), ('SET_FIELD', ('VLAN_VID', 2))
        PCP5, OUT = ('SET_FIELD', ('VLAN_PCP', 5)), ('OUTPUT', 1)
        IP = ('SET_FIELD', ('IPV4_SRC', 1))
        MATCH = Match([('IPV4_DST', 1, None)])

        # Base case
        n1 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([VID1, IP, OUT])),
            Rule(priority=0)
            ])
        # Check that VLAN set fields between PUSH and POP are removed, but not others
        n2 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([VID2, PUSH, IP, PCP5, POP, VID1, OUT])),
            Rule(priority=0)
            ])
        self.assertTrue(check_equal(n1, n2))

        # Check with multiple set fields between
        n3 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([IP, PUSH, VID2, VID2, POP, VID1, OUT])),
            Rule(priority=0)
            ])
        self.assertTrue(check_equal(n1, n3))

        # Check with nested push pop operations
        n4 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([IP, PUSH, PUSH, VID2, POP, VID2, POP, VID1, OUT])),
            Rule(priority=0)
            ])
        self.assertTrue(check_equal(n1, n4))

        # Check we don't remove a pop, push case!!
        # A very strict set of conditions would be needed to remove this:
        # 1). All fields are set after the push, that is VID and PCP,
        #     and we keep the set fields, (or)
        #     - All fields are set back to their original value based on the match
        #       and this becomes a nop
        # 2). We can be sure that the push'd VLAN ethertype is the same
        #      as the original VLAN ethertype
        # For now we don't account for this case as it is too complex
        n5 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([IP, POP, PUSH, VID2, OUT])),
            Rule(priority=0)
            ])

        self.assertFalse(check_equal(n1, n5))

        # We should remove any set fields before the POP
        n6 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([IP, VID1, PCP5, POP, PUSH, VID2, OUT])),
            Rule(priority=0)
            ])
        self.assertTrue(check_equal(n5, n6))

        # Check that a double tagging is correct and doesn't remove set_fields
        # push_vlan, vid: 1, push_vlan, vid: 2
        n7 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([PUSH, VID1, PUSH, VID2, OUT])),
            Rule(priority=0)
            ])

        # != push_vlan, push_vlan, vid:2
        n8 = normalise([
            Rule(priority=10, match=MATCH,
                 instructions=inst_from_acts([PUSH, PUSH, VID2, OUT])),
            Rule(priority=0)
            ])
        self.assertFalse(check_equal(n7, n8))
コード例 #21
0
    def test_redundant_set_field(self):
        """ Check that additional set fields are removed """
        SF1, SF2 = ("SET_FIELD", ("IPV4_DST", 1)), ("SET_FIELD", ("IPV4_DST", 2))
        SF3, SF4 = ("SET_FIELD", ("IPV4_DST", 3)), ("SET_FIELD", ("IPV4_DST", 4))
        OUT = ("OUTPUT", 1)
        n1 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF2, OUT])),
            Rule(priority=0)
            ])
        n2 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF1, SF2, OUT])),
            Rule(priority=0)
            ])
        n3 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF3, SF2, OUT])),
            Rule(priority=0)
            ])
        n4 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF4, SF3, SF1, SF2, OUT])),
            Rule(priority=0)
            ])
        n5 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF2, SF2, SF2, SF2, OUT])),
            Rule(priority=0)
            ])
        self.assertTrue(check_equal(n1, n2))
        self.assertTrue(check_equal(n1, n3))
        self.assertTrue(check_equal(n1, n4))
        self.assertTrue(check_equal(n1, n5))

        # Sanity check
        n6 = normalise([
            Rule(priority=10,
                 instructions=inst_from_acts([SF4, SF3, SF1, SF1, OUT])),
            Rule(priority=0)
            ])
        self.assertFalse(check_equal(n1, n6))
コード例 #22
0
    def test_push_pop_vlan_complex(self):
        """ Test complex combinations work associatively
        # rule1
        # M: 1
        # A: SET:2
        # rule2
        # M: *
        # A: Push: 6
        # rule3
        # M: 6
        # A: POP
        # rule4
        # M: 2
        # A: Output:1
        """

        rule1 = Rule(priority=0, match=self.vlan_vid_1)
        rule1.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 2))
        rule2 = Rule(priority=0)
        rule2.instructions.apply_actions.append("PUSH_VLAN", 0x800)
        rule2.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 6))
        rule3 = Rule(priority=0, match=self.vlan_vid_6)
        rule3.instructions.apply_actions.append("POP_VLAN", None)
        rule4 = Rule(priority=0, match=self.vlan_vid_2)
        rule4.instructions.apply_actions.append("OUTPUT", 1)

        expt = Rule(priority=0, match=self.vlan_vid_1)
        expt.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 2))
        expt.instructions.apply_actions.append("PUSH_VLAN", 0x800)
        expt.instructions.apply_actions.append("SET_FIELD", ('VLAN_VID', 6))
        expt.instructions.apply_actions.append("POP_VLAN", None)
        expt.instructions.apply_actions.append("OUTPUT", 1)
        self.assertEqual(
            rule1.merge(rule2, False).merge(rule3, False).merge(rule4, False),
            expt)
        self.assertEqual(
            rule1.merge(rule2.merge(rule3, False).merge(rule4, False), False),
            expt)
        self.assertEqual(
            rule1.merge(rule2.merge(rule3.merge(rule4, False), False), False),
            expt)
        self.assertEqual(
            rule1.merge(rule2.merge(rule3, False), False).merge(rule4, False),
            expt)
コード例 #23
0
 def test_action_independence_single(self):
     """ Test cases where the match cancels a set field """
     SF1, OUT = ('SET_FIELD', ('IPV4_DST', 0x01010101)), ('OUTPUT', 6)
     DEC_TTL = ('DEC_NW_TTL', None)
     # 0.1.1.0/30 -> ip:1.1.1.1, output:1
     n1 = normalise([
         Rule(priority=10,
              match=Match([('IPV4_DST', 0x01010100, 0xFFFFFFFE)]),
              instructions=inst_from_acts([SF1, OUT])),
         Rule(priority=0)
         ])
     # 1.1.1.1/32 -> output:1
     # 1.1.1.0/31 -> ip:1.1.1.1, output:1
     n2 = normalise([
         Rule(priority=10,
              match=Match([('IPV4_DST', 0x01010101, None)]),
              instructions=inst_from_acts([OUT])),
         Rule(priority=9,
              match=Match([('IPV4_DST', 0x01010100, 0xFFFFFFFE)]),
              instructions=inst_from_acts([SF1, OUT])),
         Rule(priority=0)
         ])
     # 1.1.1.0/32 -> ip:1.1.1.1, output1
     # 1.1.1.0/31 -> output:1
     n3 = normalise([
         Rule(priority=10,
              match=Match([('IPV4_DST', 0x01010100, None)]),
              instructions=inst_from_acts([SF1, OUT])),
         Rule(priority=9,
              match=Match([('IPV4_DST', 0x01010100, 0xFFFFFFFE)]),
              instructions=inst_from_acts([OUT])),
         Rule(priority=0)
         ])
     n4 = normalise([
         Rule(priority=10,
              match=Match([('IPV4_DST', 0x01010101, None)]),
              instructions=inst_from_acts([OUT])),
         Rule(priority=9,
              match=Match([('IPV4_DST', 0x01010100, 0xFFFFFFFE)]),
              instructions=inst_from_acts([DEC_TTL, SF1, OUT])),
         Rule(priority=0)
         ])
     self.assertTrue(check_equal(n1, n2))
     self.assertFalse(check_equal(n1, n4))
     self.assertTrue(check_equal(n2, n3))
     self.assertTrue(check_equal(n1, n3))
コード例 #24
0
    def test_find_simple_conflicting_paths(self):
        """ Simple single table conflicting paths test
        Difference test
        ip=1 -> output:1
        *    -> drop

        vs.

        ip=1 -> drop
        *    -> drop

        vs.

        *  -> drop
        """
        ruleset_a = [
            Rule(priority=9, table=0,
                 match=Match([('IPV4_DST', 1, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=0, table=0)
            ]

        ruleset_b = [
            Rule(priority=9, table=0,
                 match=Match([('IPV4_DST', 1, None)])),
            Rule(priority=0, table=0)
            ]

        ruleset_c = [
            Rule(priority=0, table=0)
            ]
        # Expected results
        result_ab = {
            (ruleset_a[0],): frozenset([(ruleset_b[0],)])
        }
        result_ba = {
            (ruleset_b[0],): frozenset([(ruleset_a[0],)])
        }
        result_ac = {
            (ruleset_a[0],): frozenset([(ruleset_c[0],)])
        }
        result_ca = {
            (ruleset_c[0],): frozenset([(ruleset_a[0],)])
        }
        single_a = to_single_table(ruleset_a)
        single_b = to_single_table(ruleset_b)
        single_c = to_single_table(ruleset_c)
        norm_a = normalise(single_a)
        norm_b = normalise(single_b)
        norm_c = normalise(single_c)
        equal_ab, diff_ab = check_equal(norm_a, norm_b, diff=True)
        self.assertFalse(equal_ab)
        equal_ac, diff_ac = check_equal(norm_a, norm_b, diff=True)
        self.assertFalse(equal_ac)
        self.assertTrue(check_equal(norm_b, norm_c))

        paths_ab = find_conflicting_paths(diff_ab, single_a, single_b)
        self.assertEqual(paths_ab, result_ab)
        self.assertNotEqual(paths_ab, result_ba)  # Sanity check

        paths_ba = find_conflicting_paths(diff_ab, single_b, single_a)
        self.assertEqual(paths_ba, result_ba)
        self.assertNotEqual(paths_ba, result_ab)  # Sanity check

        paths_ca = find_conflicting_paths(diff_ac, single_c, single_a)
        self.assertEqual(paths_ca, result_ca)

        paths_ac = find_conflicting_paths(diff_ac, single_a, single_c)
        self.assertEqual(paths_ac, result_ac)
コード例 #25
0
    def test_metadata(self):
        rule1 = Rule(priority=0, match=self.ipv4_src2)
        rule1.instructions.write_metadata = (0xFEFCFDFA, None)
        rule2 = Rule(priority=0, match=self.ipv4_src2)
        rule2.instructions.write_metadata = (0x0000FFFF, None)
        # This is half the match as these are 64 byte
        rule3 = Rule(priority=0, match=self.ipv4_src2)
        rule3.instructions.write_metadata = (0xFEFCFDFA, 0xFFFFFFFF)
        rule4 = Rule(priority=0, match=self.ipv4_src2)
        rule4.instructions.write_metadata = (0x0000FFFF, 0xFFFFFFFF)
        rule5 = Rule(priority=0, match=self.ipv4_src2)
        rule5.instructions.write_metadata = (0xFEFCFDFA00000000,
                                             0xFFFFFFFF00000000)
        rule6 = Rule(priority=0, match=self.ipv4_src2)
        rule6.instructions.write_metadata = (0xFEFCFDFA0000FFFF,
                                             0xFFFFFFFFFFFFFFFF)
        rule7 = Rule(priority=0, match=self.ipv4_src2)
        rule7.instructions.write_metadata = (0x0, 0xFFFFFFFFFFFFFFF0)

        # Test cases
        self.assertEqual(rule1 + rule2, rule2)
        self.assertEqual(rule2 + rule1, rule1)
        self.assertEqual(rule1 + rule4, rule2)
        self.assertEqual(rule1 + rule3, rule1)
        self.assertEqual(rule3 + rule4, rule4)
        self.assertEqual(rule4 + rule5, rule6)
        self.assertEqual(rule5 + rule4, rule6)

        # Now check masking and matching
        # Check an invalid match will fail
        mrule1 = Rule(priority=0, match=self.meta_1)
        self.assertRaises(MergeException, lambda: rule1 + mrule1)

        # Merging partial metadata sets and matches
        #
        # The correct behaviour is to remove matching set values.
        # More correctly one should remove set bits, in the case of
        # metadata the result is a partial metadata match.
        #
        # Match:  *                         + Metadata=(1, None)
        # Action: WriteMeta:(0x0, 0xFF..F0) +
        #
        # Expecting:
        # Match:  Meta=(1,0xF)
        # Action: WriteMeta:(0x0, 0xFF..F0)

        expected = rule7.copy()
        expected.match.append('METADATA', 0x1, 0xF)
        self.assertEqual(rule7 + mrule1, expected)

        # Try a complex case
        d1 = Rule(priority=0, match=Match())
        d1.instructions.write_metadata = (0x10, 0x10)
        d2 = Rule(priority=0, match=Match())
        d2.instructions.write_metadata = (0x1, 0x1)
        d3 = Rule(priority=0, match=Match([('METADATA', 0x10, 0x10)]))
        d3.instructions.write_metadata = (0x100, 0x100)
        d4 = Rule(priority=0, match=Match([('METADATA', 0x111, 0x111)]))

        expected = Rule(priority=0, match=Match())
        expected.instructions.write_metadata = (0x111, 0x111)

        self.assertEqual(d1 + d2 + d3 + d4, expected)
        self.assertEqual((d1 + d2) + (d3 + d4), expected)
        self.assertEqual(d1 + (d2 + d3) + d4, expected)
        self.assertEqual(d1 + (d2 + (d3 + d4)), expected)

        # This should fail if table the first is set to 0
        d1.instructions.write_metadata = (0x00, 0x10)
        self.assertRaises(MergeException, lambda: d1 + d2 + d3 + d4)
        self.assertRaises(MergeException, lambda: (d1 + d2) + (d3 + d4))
        self.assertRaises(MergeException, lambda: d1 + (d2 + d3) + d4)
        self.assertRaises(MergeException, lambda: d1 + (d2 + (d3 + d4)))

        # Check original metadata match + set's intersection is calculated
        # correctly
        rule8 = Rule(priority=0, match=Match([("METADATA", 0x1, 0x1)]))
        rule8.instructions.write_metadata = (0x0, 0x2)
        rule9 = Rule(priority=0, match=Match([("METADATA", 0x0, None)]))
        self.assertRaises(MergeException, lambda: rule8 + rule9)

        rule10 = Rule(priority=0, match=Match([("METADATA", 0x1, None)]))
        expected = Rule(priority=0,
                        match=Match([("METADATA", 0x1, 0xFFFFFFFFFFFFFFFD)]))
        expected.instructions.write_metadata = (0x0, 0x2)
        self.assertEqual(rule8 + rule10, expected)
コード例 #26
0
ファイル: test_ruleset.py プロジェクト: wandsdn/ofequivalence
        inst.write_actions = ActionSet(write_actions)
    if goto_table:
        inst.goto_table = goto_table
    return inst


def priority_scale(first, second):
    """ This is how we scale priorities for a two table pipeline,
        if this changes we will need to update this code.
    """
    return first * (MAX_PRIORITY) + second


FORWARD_DROP = [
    Rule(priority=10, table=0, match=Match([("IPV4_DST", 0x1, 0x3)]),
         instructions=build_inst(write_actions=[("OUTPUT", 1)],
                                 goto_table=1)),
    Rule(priority=9, table=0, match=Match([("IPV4_DST", 0x2, 0x7)]),
         instructions=build_inst(write_actions=[("OUTPUT", 2)],
                                 goto_table=1)),
    Rule(priority=0, table=0, match=Match()),

    Rule(priority=100, table=1, match=Match([("IPV4_DST", 0x8, 0x8)]),
         instructions=build_inst(clear_actions=True)),
    Rule(priority=0, table=1, match=Match()),
    ]

# The expected single table
FORWARD_DROP_SINGLE = [
    Rule(priority=priority_scale(10, 100), table=0,  # A + D
         match=Match([("IPV4_DST", 0x9, 0xb)]),
コード例 #27
0
    def test_find_multitable_conflicting_paths(self):
        """ Multitable conflicting paths test

        vlan:1 GT(1)     ip:0/0xFFFFFFFE output1    ip:0
        vlan:2 GT(2)     ip:0 output1 (shadowed)    ip:1
        *                *                          *

        === As single table ===

        vlan:1,ip:0 output1
        vlan:1,ip:1 output1
        vlan:2,ip:0
        vlan:2,ip:1
        *

        vs.

        vlan:1,ip:0
        vlan:1,ip:1 output1
        vlan:2,ip:0 output1
        vlan:2,ip:1
        *
        """
        ruleset_a = [
            Rule(priority=10, table=0,
                 match=Match([('VLAN_VID', 1, None)]),
                 instructions=Instructions(dup=goto1)),
            Rule(priority=10, table=0,
                 match=Match([('VLAN_VID', 2, None)]),
                 instructions=Instructions(dup=goto2)),
            Rule(priority=0, table=0),
            Rule(priority=20, table=1,
                 match=Match([('IPV4_DST', 0, 0xFFFFFFFE)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=19, table=1,
                 match=Match([('IPV4_DST', 0, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=0, table=1),
            Rule(priority=30, table=2,
                 match=Match([('IPV4_DST', 0, None)]),
                 instructions=Instructions()),
            Rule(priority=30, table=2,
                 match=Match([('IPV4_DST', 1, None)]),
                 instructions=Instructions()),
            Rule(priority=0, table=2)
            ]

        ruleset_b = [
            Rule(priority=14, table=0,
                 match=Match([('VLAN_VID', 1, None), ('IPV4_DST', 0, None)])),
            Rule(priority=14, table=0,
                 match=Match([('VLAN_VID', 1, None), ('IPV4_DST', 1, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=14, table=0,
                 match=Match([('VLAN_VID', 2, None), ('IPV4_DST', 0, None)]),
                 instructions=Instructions(dup=output1)),
            Rule(priority=14, table=0,
                 match=Match([('VLAN_VID', 2, None), ('IPV4_DST', 1, None)])),
            Rule(priority=0, table=0)
            ]

        single_a = to_single_table(ruleset_a)
        single_b = to_single_table(ruleset_b)
        norm_a = normalise(single_a)
        norm_b = normalise(single_b)

        result_ab = {
            (ruleset_a[0], ruleset_a[3]): frozenset([(ruleset_b[0],)]),
            (ruleset_a[1], ruleset_a[6]): frozenset([(ruleset_b[2],)])
        }
        result_ba = {
            (ruleset_b[0],): frozenset([(ruleset_a[0], ruleset_a[3])]),
            (ruleset_b[2],): frozenset([(ruleset_a[1], ruleset_a[6])])
        }

        equal_ab, diff_ab = check_equal(norm_a, norm_b, diff=True)
        self.assertFalse(equal_ab)
        equal_ba, diff_ba = check_equal(norm_b, norm_a, diff=True)
        self.assertFalse(equal_ba)

        paths_ab = find_conflicting_paths(diff_ab, single_a, single_b)
        paths_ba = find_conflicting_paths(diff_ab, single_b, single_a)

        self.assertEqual(paths_ab, result_ab)
        self.assertNotEqual(paths_ab, result_ba)  # Sanity
        self.assertEqual(paths_ba, result_ba)
コード例 #28
0
    def test_find_vlans_conflicting_paths(self):
        """ VLAN rewrite paths test, check push/pop combinations
            Also due to internals of how this can be structured

        IN_PORT:1,VLAN:1         TCP:80: drop     VLAN:1 output:10
        IN_PORT:2 pushVLAN:2     * ->             VLAN:2 pop output:11
        IN_PORT:3 pushVLAN:1
        IN_PORT:4,VLAN:2
        * drop

        vs. A vlan can do things:

        IN_PORT:1,VLAN:1         VLAN:1 pop output:11
        IN_PORT:2 pushVLAN:2     VLAN:2 output:10
        IN_PORT:3 pushVLAN:1
        IN_PORT:4,VLAN:2
        * drop

        vs. single table, note all traffic is different no set
        * drop
        """
        push_vlan2 = Instructions()
        push_vlan2.goto_table = 1
        push_vlan2.apply_actions.append("PUSH_VLAN", 0x8100)
        push_vlan2.apply_actions.append("SET_FIELD", ("VLAN_VID", 2))
        push_vlan1 = Instructions()
        push_vlan1.goto_table = 1
        push_vlan1.apply_actions.append("PUSH_VLAN", 0x8100)
        push_vlan1.apply_actions.append("SET_FIELD", ("VLAN_VID", 1))
        trunk10 = Instructions()
        trunk10.write_actions.append("OUTPUT", 11)
        access11 = Instructions()
        access11.write_actions.append("POP_VLAN", None)
        access11.write_actions.append("OUTPUT", 11)
        # Note: Set VLAN applies the present bit mask so must included it
        ruleset_a = [
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 1, None), ('VLAN_VID', 0x1001, None)]),
                 instructions=goto1),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 2, None)]),
                 instructions=push_vlan2),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 3, None)]),
                 instructions=push_vlan1),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 4, None), ('VLAN_VID', 0x1002, None)]),
                 instructions=goto1),
            Rule(priority=0, table=0),
            Rule(priority=10, table=1, match=Match([('TCP_SRC', 80, None)])),
            Rule(priority=0, table=1, instructions=goto2),
            Rule(priority=10, table=2, match=Match([('VLAN_VID', 0x1001, None)]),
                 instructions=Instructions(dup=trunk10)),
            Rule(priority=10, table=2, match=Match([('VLAN_VID', 0x1002, None)]),
                 instructions=Instructions(dup=access11)),
            Rule(priority=0, table=2),
            ]
        ruleset_b = [
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 1, None), ('VLAN_VID', 0x1001, None)]),
                 instructions=goto1),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 2, None)]),
                 instructions=push_vlan2),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 3, None)]),
                 instructions=push_vlan1),
            Rule(priority=10, table=0,
                 match=Match([('IN_PORT', 4, None), ('VLAN_VID', 0x1002, None)]),
                 instructions=goto1),
            Rule(priority=0, table=0),
            Rule(priority=10, table=1, match=Match([('VLAN_VID', 0x1001, None)]),
                 instructions=Instructions(dup=access11)),
            Rule(priority=10, table=1, match=Match([('VLAN_VID', 0x1002, None)]),
                 instructions=Instructions(dup=trunk10)),
            Rule(priority=0, table=1)]
        ruleset_c = [
            Rule(priority=0, table=0)
            ]
        single_a = to_single_table(ruleset_a)
        single_b = to_single_table(ruleset_b)
        single_c = to_single_table(ruleset_c)
        norm_a = normalise(single_a)
        norm_b = normalise(single_b)
        norm_c = normalise(single_c)

        # Make sure the frozensets are made after to_single_table which changes
        # priorities which changes the Rule's hash in the frozenset
        result_ab = {
            (ruleset_a[0], ruleset_a[5]):
                frozenset([(ruleset_b[0], ruleset_b[5])]),
            (ruleset_a[0], ruleset_a[6], ruleset_a[7]):
                frozenset([(ruleset_b[0], ruleset_b[5])]),
            (ruleset_a[1], ruleset_a[5]):
                frozenset([(ruleset_b[1], ruleset_b[6])]),
            (ruleset_a[1], ruleset_a[6], ruleset_a[8]):
                frozenset([(ruleset_b[1], ruleset_b[6])]),
            (ruleset_a[2], ruleset_a[5]):
                frozenset([(ruleset_b[2], ruleset_b[5])]),
            (ruleset_a[2], ruleset_a[6], ruleset_a[7]):
                frozenset([(ruleset_b[2], ruleset_b[5])]),
            (ruleset_a[3], ruleset_a[5]):
                frozenset([(ruleset_b[3], ruleset_b[6])]),
            (ruleset_a[3], ruleset_a[6], ruleset_a[8]):
                frozenset([(ruleset_b[3], ruleset_b[6])]),
            }
        result_ba = {
            (ruleset_b[0], ruleset_b[5]):
                frozenset([(ruleset_a[0], ruleset_a[5]),
                           (ruleset_a[0], ruleset_a[6], ruleset_a[7])]),
            (ruleset_b[1], ruleset_b[6]):
                frozenset([(ruleset_a[1], ruleset_a[5]),
                           (ruleset_a[1], ruleset_a[6], ruleset_a[8])]),
            (ruleset_b[2], ruleset_b[5]):
                frozenset([(ruleset_a[2], ruleset_a[5]),
                           (ruleset_a[2], ruleset_a[6], ruleset_a[7])]),
            (ruleset_b[3], ruleset_b[6]):
                frozenset([(ruleset_a[3], ruleset_a[5]),
                           (ruleset_a[3], ruleset_a[6], ruleset_a[8])]),
            }
        result_ca = {
            (ruleset_c[0],):
                frozenset([(ruleset_a[0], ruleset_a[6], ruleset_a[7]),
                           (ruleset_a[1], ruleset_a[6], ruleset_a[8]),
                           (ruleset_a[2], ruleset_a[6], ruleset_a[7]),
                           (ruleset_a[3], ruleset_a[6], ruleset_a[8])])
            }
        equal_ab, diff_ab = check_equal(norm_a, norm_b, diff=True)
        equal_ca, diff_ca = check_equal(norm_c, norm_a, diff=True)
        self.assertFalse(equal_ab)
        self.assertFalse(equal_ca)

        paths_ab = find_conflicting_paths(diff_ab, single_a, single_b)
        paths_ba = find_conflicting_paths(diff_ab, single_b, single_a)
        paths_ca = find_conflicting_paths(diff_ca, single_c, single_a)
        self.assertEqual(paths_ab, result_ab)
        self.assertNotEqual(paths_ab, result_ba)  # Sanity check
        self.assertEqual(paths_ba, result_ba)
        self.assertEqual(paths_ca, result_ca)
コード例 #29
0

def I(goto=None, set_tcp=None):
    """ Short hand to generate instructions """
    i = Instructions()
    i.goto_table = goto
    if set_tcp is not None:
        i.apply_actions.append('SET_FIELD', ('TCP_DST', set_tcp))
    return i


R2M = match_from_ryu
COVISOR_RULESET = [
    Rule(
        priority=5,
        match=R2M(
            OFPMatch(  # 0
                ipv4_src=("1.0.0.0", "255.255.255.0"),
                ipv4_dst="2.0.0.1"))),
    Rule(
        priority=4,
        match=R2M(
            OFPMatch(  # 1
                ipv4_src=("1.0.0.0", "255.255.255.0"),
                ipv4_dst="2.0.0.2"))),
    Rule(
        priority=3,
        match=R2M(OFPMatch(  # 2
            ipv4_src=("1.0.0.0", "255.255.255.0")))),
    Rule(priority=2, match=R2M(OFPMatch(ipv4_dst="2.0.0.1"))),  # 3
    Rule(priority=1, match=R2M(OFPMatch(ipv4_dst="2.0.0.2"))),  # 4
    Rule(priority=0)  # 5