Exemple #1
0
    def test_index_slice_len(self):
        # These all have dependencies and cannot be interlaced
        action_list = self.action_list_nonreorderable
        actions = ActionList(action_list)

        self.assertEqual(len(action_list), len(actions))
        self.assertEqual(0, len(ActionList()))
        self.assertFalse(ActionList())
        self.assertTrue(actions)

        for i, orig_action in enumerate(action_list):
            # Check the correct item is returned
            self.assertEqual(orig_action, actions[i])
            # Check the correct index is returned
            self.assertEqual(i, actions.index(actions[i]))

        # Now lets check we can do some slicing - note length
        # Note slicing returns normal lists not Actions back
        self.assertListEqual(action_list[:], actions[:])
        self.assertListEqual(action_list[::-1], actions[::-1])
        self.assertListEqual(action_list[2:], actions[2:])
        self.assertListEqual(action_list[3::2], actions[3::2])
        self.assertListEqual(action_list[1:-1], actions[1:-1])
        self.assertListEqual(action_list[1:len(actions) - 1],
                             actions[1:len(actions) - 1])
Exemple #2
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
Exemple #3
0
    def test_adding_lists(self):
        # Tests the '+', '+=' and copy(add=) operations for Action Lists
        actions1 = ActionList(self.action_list_complex)
        actions2 = ActionList(self.action_list_nonreorderable)
        # This should be the same as adding the two original lists together
        expected = ActionList(self.action_list_complex +
                              self.action_list_nonreorderable)
        expected_rev = ActionList(self.action_list_nonreorderable +
                                  self.action_list_complex)

        self._test_add(actions1, actions2, expected, expected_rev)
Exemple #4
0
    def test_simple_fully_dep_reverse(self):
        """
        Reversed to ensure it was not fluke sorting
        """
        action_list1 = [("SET_FIELD", ("ETH_DST", 1)),
                        ("SET_FIELD", ("ETH_DST", 45))]
        action_list2 = [("SET_FIELD", ("VLAN_VID", 0x1015)),
                        ("PUSH_VLAN", 0x88a8),
                        ("SET_FIELD", ("VLAN_VID", 0x100F))]

        self.assertEqual(action_list1, list(ActionList(action_list1)))
        self.assertEqual(action_list2, list(ActionList(action_list2)))
Exemple #5
0
    def test_action_set_ordering(self):
        # Test adding sets together and set and list combos
        actlista = [('OUTPUT', 1), ('SET_FIELD', ('VLAN_VID', 0x1003)),
                    ('SET_FIELD', ('VLAN_PCP', 0x1)), ('PUSH_VLAN', None)]
        actlista_ordered = [('PUSH_VLAN', None),
                            ('SET_FIELD', ('VLAN_VID', 0x1003)),
                            ('SET_FIELD', ('VLAN_PCP', 0x1)), ('OUTPUT', 1)]
        actlistb = [('SET_QUEUE', 5), ('SET_FIELD', ('IPV4_SRC', 12))]
        actlistc = [('SET_FIELD', ('VLAN_PCP', 0x2)), ('PUSH_VLAN', None),
                    ('OUTPUT', 2)]
        actlistc_ordered = [('PUSH_VLAN', None),
                            ('SET_FIELD', ('VLAN_PCP', 0x2)), ('OUTPUT', 2)]
        actlistd = [('OUTPUT', 7)]
        actliste = [('GROUP', 8)]
        actlistf = [('GROUP', 9)]

        seta = ActionSet(actlista)
        setb = ActionSet(actlistb)
        setc = ActionSet(actlistc)
        setd = ActionSet(actlistd)
        sete = ActionSet(actliste)
        setf = ActionSet(actlistf)

        # Sanity check, check ordering is correct
        self.assertEqual(seta, ActionList(actlista_ordered))
        self.assertEqual(setc, ActionList(actlistc_ordered))

        # Now lets add some sets together!

        # Set a and b dont overlap, both orders should be equal
        expected = [('PUSH_VLAN', None), ('SET_FIELD', ('IPV4_SRC', 12)),
                    ('SET_FIELD', ('VLAN_VID', 0x1003)),
                    ('SET_FIELD', ('VLAN_PCP', 0x1)), ('SET_QUEUE', 5),
                    ('OUTPUT', 1)]
        expected = ActionList(expected)

        self._test_add(seta, setb, expected, expected)

        # Set a and c entirely overlap, OUTPUT, VLAN_PCP and QUEUE
        expected = [('PUSH_VLAN', None), ('SET_FIELD', ('VLAN_VID', 0x1003)),
                    ('SET_FIELD', ('VLAN_PCP', 0x2)), ('OUTPUT', 2)]
        expected = ActionList(expected)
        self._test_add(seta, setc, expected, ActionList(actlista_ordered))

        # Check special case with 'GROUP', groups overwrite 'OUTPUT' in the
        # result yet they both can be added

        expected = ActionSet([('GROUP', 8)])
        self._test_add(setd, sete, expected, expected)

        expectedb = ActionSet([('GROUP', 9)])
        self._test_add(sete, setf, expectedb, expected)
Exemple #6
0
    def test_simple_unordered(self):
        """
        Test on a couple of sets where order does not matter
        """
        import itertools
        action_list1 = [("SET_FIELD", ("ETH_DST", 1)),
                        ("SET_FIELD", ("VLAN_VID", 45)), ("SET_QUEUE", 1),
                        ("PUSH_MPLS", 0x8847)]

        expected = ActionList(action_list1)
        for permuation in itertools.permutations(action_list1):
            res = ActionList(permuation)
            self.assertEqual(expected, res)
Exemple #7
0
    def test_simple_fully_dep(self):
        """
        Tests some simple cases in which the order
        matters and as the such the same result should
        be expected
        """
        action_list1 = [("SET_FIELD", ("ETH_DST", 45)),
                        ("SET_FIELD", ("ETH_DST", 1))]
        action_list2 = [("SET_FIELD", ("VLAN_VID", 0x100F)),
                        ("PUSH_VLAN", 0x88a8),
                        ("SET_FIELD", ("VLAN_VID", 0x1015))]

        self.assertEqual(action_list1, list(ActionList(action_list1)))
        self.assertEqual(action_list2, list(ActionList(action_list2)))
Exemple #8
0
    def test_removal(self):
        # Check that removing an object works and that lists are
        # correctly reordered. In the case a something is removed
        # it may require other items to be placed into a higher level
        action_list = self.action_list_complex
        actions = ActionList(action_list)

        # Constant seed used here :)
        random = Random(143)

        # We will remove a random item until the list is empty
        # Checking each time the result matches a new list.
        while actions:
            random_item = actions[random.randint(0, len(actions) - 1)]
            actions.remove(random_item)
            action_list.remove(random_item)
            self.assertEqual(actions, ActionList(action_list))
Exemple #9
0
    def test_contains(self):
        actions = ActionList(self.action_list_complex)
        self.assertEqual(len(self.action_list_complex), len(actions))
        for action in self.action_list_complex:
            self.assertIn(action, actions)

        self.assertNotIn(("PUSH_MPLS", 0x8847), actions)
        self.assertNotIn(("POP_MPLS", 0x0800), actions)
        self.assertNotIn(("POP_MPLS", 0x0800), actions)
        self.assertNotIn(("OUTPUT", 20), actions)
Exemple #10
0
    def test_list_add_set(self):
        # Test that adding a set to a list works and a list to a set
        actlista = [('OUTPUT', 1), ('SET_FIELD', ('VLAN_VID', 0x1003)),
                    ('SET_FIELD', ('VLAN_PCP', 0x1)), ('PUSH_VLAN', None)]
        actlista_ordered = [('PUSH_VLAN', None),
                            ('SET_FIELD', ('VLAN_VID', 0x1003)),
                            ('SET_FIELD', ('VLAN_PCP', 0x1)), ('OUTPUT', 1)]
        act_list = self.action_list_nonreorderable
        lista = ActionList(act_list)
        seta = ActionSet(actlista)

        set_add_list = ActionList([("PUSH_VLAN", 0x88a8),
                                   ("SET_FIELD", ("ETH_DST", 1)),
                                   ("SET_FIELD", ("VLAN_VID", 0x1015)),
                                   ('SET_FIELD', ('VLAN_PCP', 0x1)),
                                   ("OUTPUT", 5)])
        list_add_set = ActionList(act_list + actlista_ordered)

        self._test_add(seta, lista, set_add_list, list_add_set)
Exemple #11
0
def build_inst(apply_actions=None, write_actions=None, goto_table=None,
               clear_actions=None):
    inst = Instructions()
    if clear_actions:
        inst.clear_actions = True
    if apply_actions:
        inst.apply_actions = ActionList(apply_actions)
    if write_actions:
        inst.write_actions = ActionSet(write_actions)
    if goto_table:
        inst.goto_table = goto_table
    return inst
Exemple #12
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)
Exemple #13
0
    def test_convert_instructions(self):
        """ Test converting instructions from ovs """
        inst = Instructions()
        inst.write_metadata = (0x56, 0xff)
        self.assertEqual(instructions_from_ovs("write_metadata:0x56/0xff", {}),
                         inst)

        inst = Instructions()
        inst.goto_table = 6
        self.assertEqual(instructions_from_ovs("goto_table:6", {}), inst)

        inst = Instructions()
        inst.apply_actions = ActionList([('OUTPUT', 1)])
        self.assertEqual(instructions_from_ovs("output:1", {}), inst)

        inst = Instructions()
        inst.write_actions = ActionSet([('OUTPUT', 2)])
        self.assertEqual(instructions_from_ovs("write_actions(output:2)", {}),
                         inst)
    def test_convert_instructions(self):
        """ Test converting instructions from ryu """
        ryu_inst = [OFPInstructionWriteMetadata(0x56, 0xff)]
        inst = Instructions()
        inst.write_metadata = (0x56, 0xff)
        self.assertEqual(instructions_from_ryu(ryu_inst), inst)

        ryu_inst = [OFPInstructionGotoTable(6)]
        inst = Instructions()
        inst.goto_table = 6
        self.assertEqual(instructions_from_ryu(ryu_inst), inst)

        output = OFPActionOutput(1)
        ryu_inst = [OFPInstructionActions(OFPIT_APPLY_ACTIONS, [output])]
        inst = Instructions()
        inst.apply_actions = ActionList([('OUTPUT', 1)])
        self.assertEqual(instructions_from_ryu(ryu_inst), inst)

        output = OFPActionOutput(2)
        ryu_inst = [OFPInstructionActions(OFPIT_WRITE_ACTIONS, [output])]
        inst = Instructions()
        inst.write_actions = ActionSet([('OUTPUT', 2)])
        self.assertEqual(instructions_from_ryu(ryu_inst), inst)
Exemple #15
0
    def test_complex_actions(self):
        """
        Test a huge dependency mess of rules
        """
        action_list1 = self.action_list_complex
        result = ActionList(action_list1)

        # The first 3 can be reordered amongst themselves
        self.assertSetEqual(set(action_list1[0:3]), set(result[0:3]))
        # And the next 4
        self.assertSetEqual(set(action_list1[3:7]), set(result[3:7]))
        # And the next 5
        self.assertSetEqual(set(action_list1[7:12]), set(result[7:12]))
        # However within that the push vlan must become the set vlan
        self.assertIsBefore(("PUSH_VLAN", 0x8100),
                            ("SET_FIELD", ("VLAN_VID", 45)), result)
        self.assertIsBefore(("PUSH_VLAN", 0x8100),
                            ("SET_FIELD", ("VLAN_PCP", 2)), result)
        # The next two can be reordered
        self.assertSetEqual(set(action_list1[12:14]), set(result[12:14]))
        # The SET_QUEUE must be before the final two outputs
        self.assertSetEqual(set(action_list1[14]), set(result[14]))
        # The final 2 can be reordered
        self.assertSetEqual(set(action_list1[15:17]), set(result[15:17]))
    def test_convert_actions(self):
        """ Test all action conversions work correctly """

        # First check set returns a set
        self.assertIs(type(actions_from_ryu([OFPActionOutput(6)], 'set')),
                      ActionSet)
        # And list a list
        self.assertIs(type(actions_from_ryu([OFPActionOutput(6)], 'list')),
                      ActionList)

        # Now check all the action types, OUTPUT etc
        self.assertEqual(actions_from_ryu([OFPActionOutput(6)], 'list'),
                         ActionList([('OUTPUT', 6)]))
        self.assertEqual(actions_from_ryu([OFPActionGroup(7)], 'list'),
                         ActionList([('GROUP', 7)]))
        self.assertEqual(actions_from_ryu([OFPActionSetQueue(8)], 'list'),
                         ActionList([('SET_QUEUE', 8)]))
        # Push/Pop
        self.assertEqual(actions_from_ryu([OFPActionPushVlan(0x8100)], 'list'),
                         ActionList([('PUSH_VLAN', 0x8100)]))
        self.assertEqual(actions_from_ryu([OFPActionPushVlan(0x88a8)], 'list'),
                         ActionList([('PUSH_VLAN', 0x88a8)]))
        self.assertEqual(actions_from_ryu([OFPActionPopVlan()], 'list'),
                         ActionList([('POP_VLAN', None)]))
        self.assertEqual(actions_from_ryu([OFPActionPushMpls(0x8847)], 'list'),
                         ActionList([('PUSH_MPLS', 0x8847)]))
        self.assertEqual(actions_from_ryu([OFPActionPushMpls(0x8848)], 'list'),
                         ActionList([('PUSH_MPLS', 0x8848)]))
        self.assertEqual(actions_from_ryu([OFPActionPopMpls(0x0800)], 'list'),
                         ActionList([('POP_MPLS', 0x0800)]))
        self.assertEqual(actions_from_ryu([OFPActionPushPbb(0x88e7)], 'list'),
                         ActionList([('PUSH_PBB', 0x88e7)]))
        self.assertEqual(actions_from_ryu([OFPActionPopPbb()], 'list'),
                         ActionList([('POP_PBB', None)]))

        # SET_FIELD, take this chance to check we can do MAC, IPv4/6 conversion
        # as ryu might be using those.
        set_field = OFPActionSetField(vlan_vid=100)
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('VLAN_VID', 100))]))
        set_field = OFPActionSetField(eth_dst="10:11:12:13:14:15")
        self.assertEqual(
            actions_from_ryu([set_field], 'list'),
            ActionList([("SET_FIELD", ('ETH_DST', 0x101112131415))]))
        set_field = OFPActionSetField(eth_src="10-11-12-13-14-15")
        self.assertEqual(
            actions_from_ryu([set_field], 'list'),
            ActionList([("SET_FIELD", ('ETH_SRC', 0x101112131415))]))
        set_field = OFPActionSetField(ipv4_dst="192.168.2.1")
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('IPV4_DST', 0xc0a80201))]))
        set_field = OFPActionSetField(ipv4_src="192.168.2.2")
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('IPV4_SRC', 0xc0a80202))]))
        set_field = OFPActionSetField(ipv6_src="::")
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('IPV6_SRC', 0x0))]))
        set_field = OFPActionSetField(
            ipv6_src="2001:DB8:0123:4567:89ab:cdef:a:a")
        ipv6_num = 0x20010DB80123456789abcdef000a000a
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('IPV6_SRC', ipv6_num))]))
        set_field = OFPActionSetField(ipv6_dst="2001:DB8::")
        ipv6_num = 0x20010DB8000000000000000000000000
        self.assertEqual(actions_from_ryu([set_field], 'list'),
                         ActionList([("SET_FIELD", ('IPV6_DST', ipv6_num))]))
        # TTL
        self.assertEqual(actions_from_ryu([OFPActionCopyTtlOut()], 'list'),
                         ActionList([('COPY_TTL_OUT', None)]))
        self.assertEqual(actions_from_ryu([OFPActionCopyTtlIn()], 'list'),
                         ActionList([('COPY_TTL_IN', None)]))
        self.assertEqual(actions_from_ryu([OFPActionSetMplsTtl(24)], 'list'),
                         ActionList([('SET_MPLS_TTL', 24)]))
        self.assertEqual(actions_from_ryu([OFPActionDecMplsTtl()], 'list'),
                         ActionList([('DEC_MPLS_TTL', None)]))
        self.assertEqual(actions_from_ryu([OFPActionSetNwTtl(0xff)], 'list'),
                         ActionList([('SET_NW_TTL', 0xff)]))
        self.assertEqual(actions_from_ryu([OFPActionDecNwTtl()], 'list'),
                         ActionList([('DEC_NW_TTL', None)]))
def inst_from_acts(actions):
    inst = Instructions()
    inst.apply_actions = ActionList(actions)
    return inst
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ofequivalence.rule import (Match, Rule, Instructions,
                                ActionList)
from ofequivalence.ruleset import (to_single_table,)


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)]),
Exemple #19
0
    def test_convert_actions(self):
        """ Test all action conversions work correctly """

        # Now check all the action types, OUTPUT etc
        self.assertEqual(actions_from_ovs("output:6", {}),
                         ActionList([('OUTPUT', 6)]))
        self.assertEqual(actions_from_ovs('group:7', {7: 7}),
                         ActionList([('GROUP', 7)]))
        self.assertEqual(actions_from_ovs("set_queue:8", {}),
                         ActionList([('SET_QUEUE', 8)]))
        # Push/Pop
        self.assertEqual(actions_from_ovs('push_vlan:0x8100', {}),
                         ActionList([('PUSH_VLAN', 0x8100)]))
        self.assertEqual(actions_from_ovs('push_vlan:0x88a8', {}),
                         ActionList([('PUSH_VLAN', 0x88a8)]))
        self.assertEqual(actions_from_ovs('pop_vlan', {}),
                         ActionList([('POP_VLAN', None)]))
        self.assertEqual(actions_from_ovs('strip_vlan', {}),
                         ActionList([('POP_VLAN', None)]))
        self.assertEqual(actions_from_ovs('push_mpls:0x8847', {}),
                         ActionList([('PUSH_MPLS', 0x8847)]))
        self.assertEqual(actions_from_ovs('push_mpls:0x8848', {}),
                         ActionList([('PUSH_MPLS', 0x8848)]))
        self.assertEqual(actions_from_ovs('pop_mpls:0x0800', {}),
                         ActionList([('POP_MPLS', 0x0800)]))
        # PBB not supported by ovs
        #self.assertEqual(actions_from_ovs([OFPActionPushPbb(0x88e7)], 'list'),
        #                 ActionList([('PUSH_PBB', 0x88e7)]))
        #self.assertEqual(actions_from_ovs([OFPActionPopPbb()], 'list'),
        #                 ActionList([('POP_PBB', None)]))

        # SET_FIELD, take this chance to check we can do MAC, IPv4/6 conversion
        # as ovs stores these in their respective format
        self.assertEqual(actions_from_ovs('set_field:100->vlan_vid', {}),
                         ActionList([("SET_FIELD", ('VLAN_VID', 100))]))
        self.assertEqual(actions_from_ovs('set_field:4196->vlan_vid', {}),
                         ActionList([("SET_FIELD", ('VLAN_VID', 100))]))
        self.assertEqual(
            actions_from_ovs('set_field:10:11:12:13:14:15->eth_dst', {}),
            ActionList([("SET_FIELD", ('ETH_DST', 0x101112131415))]))
        self.assertEqual(
            actions_from_ovs('set_field:10:11:12:13:14:15->eth_src', {}),
            ActionList([("SET_FIELD", ('ETH_SRC', 0x101112131415))]))
        self.assertEqual(actions_from_ovs("set_field:192.168.2.1->ip_dst", {}),
                         ActionList([("SET_FIELD", ('IPV4_DST', 0xc0a80201))]))
        self.assertEqual(actions_from_ovs("set_field:192.168.2.2->ip_src", {}),
                         ActionList([("SET_FIELD", ('IPV4_SRC', 0xc0a80202))]))
        self.assertEqual(actions_from_ovs('set_field:::->ipv6_src', {}),
                         ActionList([("SET_FIELD", ('IPV6_SRC', 0x0))]))
        ipv6_num = 0x20010DB80123456789abcdef000a000a
        self.assertEqual(
            actions_from_ovs(
                'set_field:2001:db8:123:4567:89ab:cdef:a:a->ipv6_src', {}),
            ActionList([("SET_FIELD", ('IPV6_SRC', ipv6_num))]))
        ipv6_num = 0x20010DB8000000000000000000000000
        self.assertEqual(
            actions_from_ovs('set_field:2001:db8::->ipv6_dst', {}),
            ActionList([("SET_FIELD", ('IPV6_DST', ipv6_num))]))
        # TTL
        #self.assertEqual(actions_from_ovs([OFPActionCopyTtlOut()], 'list'),
        #                 ActionList([('COPY_TTL_OUT', None)]))
        #self.assertEqual(actions_from_ovs([OFPActionCopyTtlIn()], 'list'),
        #                 ActionList([('COPY_TTL_IN', None)]))
        self.assertEqual(
            actions_from_ovs('set_field:12->mpls_ttl',
                             {}),  # documented as :24 but uses (24)
            ActionList([('SET_MPLS_TTL', 12)]))
        self.assertEqual(
            actions_from_ovs('set_mpls_ttl(24)',
                             {}),  # documented as :24 but uses (24)
            ActionList([('SET_MPLS_TTL', 24)]))
        self.assertEqual(actions_from_ovs('set_mpls_ttl:23', {}),
                         ActionList([('SET_MPLS_TTL', 23)]))
        self.assertEqual(actions_from_ovs('dec_mpls_ttl', {}),
                         ActionList([('DEC_MPLS_TTL', None)]))
        self.assertEqual(actions_from_ovs('mod_nw_ttl:255', {}),
                         ActionList([('SET_NW_TTL', 0xff)]))
        self.assertEqual(actions_from_ovs('set_nw_ttl:255', {}),
                         ActionList([('SET_NW_TTL', 0xff)]))
        self.assertEqual(actions_from_ovs('set_field:255->nw_ttl', {}),
                         ActionList([('SET_NW_TTL', 0xff)]))
        self.assertEqual(actions_from_ovs('dec_ttl', {}),
                         ActionList([('DEC_NW_TTL', None)]))