blob: 7b03fbffaa061842fda976d417d30e73012ffdbf [file] [log] [blame]
Rich Lane629393f2013-01-10 15:37:33 -08001"""
2OpenFlow instruction list class
3"""
4
5import action as action
6import instruction as instruction
7from action_list import action_list
8from base_list import ofp_base_list
9from cstruct import ofp_header
10import unittest
11
12# Instruction list
13
14instruction_object_map = {
15 action.OFPIT_GOTO_TABLE : instruction.instruction_goto_table,
16 action.OFPIT_WRITE_METADATA : instruction.instruction_write_metadata,
17 action.OFPIT_WRITE_ACTIONS : instruction.instruction_write_actions,
18 action.OFPIT_APPLY_ACTIONS : instruction.instruction_apply_actions,
19 action.OFPIT_CLEAR_ACTIONS : instruction.instruction_clear_actions,
20}
21
22class instruction_list(ofp_base_list):
23 """
24 Maintain a list of instructions
25
26 Data members:
27 @arg instructions An array of instructions such as write_actions
28
29 Methods:
30 @arg pack: Pack the structure into a string
31 @arg unpack: Unpack a string to objects, with proper typing
32 @arg add: Add an action to the list; you can directly access
33 the action member, but add will validate that the added object
34 is an action.
35
36 """
37
38 def __init__(self):
39 ofp_base_list.__init__(self)
40 self.instructions = self.items
41 self.name = "instruction"
42 self.class_list = instruction.instruction_class_list
43
44 def unpack(self, binary_string, bytes=None):
45 """
46 Unpack a list of instructions
47
48 Unpack instructions from a binary string, creating an array
49 of objects of the appropriate type
50
51 @param binary_string The string to be unpacked
52
53 @param bytes The total length of the instruction list in bytes.
54 Ignored if decode is True. If bytes is None and decode is false, the
55 list is assumed to extend through the entire string.
56
57 @return The remainder of binary_string that was not parsed
58
59 """
60 if bytes == None:
61 bytes = len(binary_string)
62 bytes_done = 0
63 count = 0
64 cur_string = binary_string
65 while bytes_done < bytes:
66 hdr = instruction.ofp_instruction()
67 hdr.unpack(cur_string)
68 if hdr.len < action.OFP_ACTION_HEADER_BYTES:
69 print "ERROR: Action too short"
70 break
71 if not hdr.type in instruction_object_map.keys():
72 print "WARNING: Skipping unknown action ", hdr.type, hdr.len
73 else:
74 self.instructions.append(instruction_object_map[hdr.type]())
75 self.instructions[count].unpack(cur_string)
76 count += 1
77 cur_string = cur_string[hdr.len:]
78 bytes_done += hdr.len
79 return cur_string
80
81class Instruction_List_Test(unittest.TestCase):
82 def runTest(self):
83 # instructions header is 8 bytes
84 l = instruction_list()
85 act = action.action_output()
86 act.port = 7
87 inst = instruction.instruction_apply_actions()
88 self.assertTrue(inst.actions.add(act))
89 self.assertTrue(l.add(inst))
90 pkt = l.pack()
91 # 24 == 8 (list header) + (apply header) 8 + (output action) 8
92 self.assertEqual(len(pkt),24)
93
94 l = instruction_list()
95 self.assertTrue(l.add(instruction.instruction_goto_table()))
96