blob: 5fd57f04f7fd001a9588395856d720145a16ca27 [file] [log] [blame]
Dan Talaycof75360a2010-02-05 22:22:54 -08001"""
2OpenFlow actions list class
3"""
4
5from action import *
Dan Talaycob9cb5482010-02-09 15:23:12 -08006from cstruct import ofp_header
Dan Talayco3afcf722010-05-11 15:05:11 -07007import copy
Dan Talaycof75360a2010-02-05 22:22:54 -08008
9# # Map OFP action identifiers to the actual structures used on the wire
10# action_object_map = {
11# OFPAT_OUTPUT : ofp_action_output,
12# OFPAT_SET_VLAN_VID : ofp_action_vlan_vid,
13# OFPAT_SET_VLAN_PCP : ofp_action_vlan_pcp,
14# OFPAT_STRIP_VLAN : ofp_action_header,
15# OFPAT_SET_DL_SRC : ofp_action_dl_addr,
16# OFPAT_SET_DL_DST : ofp_action_dl_addr,
17# OFPAT_SET_NW_SRC : ofp_action_nw_addr,
18# OFPAT_SET_NW_DST : ofp_action_nw_addr,
19# OFPAT_SET_NW_TOS : ofp_action_nw_tos,
20# OFPAT_SET_TP_SRC : ofp_action_tp_port,
21# OFPAT_SET_TP_DST : ofp_action_tp_port,
22# OFPAT_ENQUEUE : ofp_action_enqueue
23# }
24
Dan Talaycof75360a2010-02-05 22:22:54 -080025action_object_map = {
26 OFPAT_OUTPUT : action_output,
27 OFPAT_SET_VLAN_VID : action_set_vlan_vid,
28 OFPAT_SET_VLAN_PCP : action_set_vlan_pcp,
29 OFPAT_STRIP_VLAN : action_strip_vlan,
30 OFPAT_SET_DL_SRC : action_set_dl_src,
31 OFPAT_SET_DL_DST : action_set_dl_dst,
32 OFPAT_SET_NW_SRC : action_set_nw_src,
33 OFPAT_SET_NW_DST : action_set_nw_dst,
34 OFPAT_SET_NW_TOS : action_set_nw_tos,
35 OFPAT_SET_TP_SRC : action_set_tp_src,
36 OFPAT_SET_TP_DST : action_set_tp_dst,
Dan Talayco56eb48d2010-02-10 22:38:24 -080037 OFPAT_ENQUEUE : action_enqueue,
38 OFPAT_VENDOR : action_vendor
Dan Talaycof75360a2010-02-05 22:22:54 -080039}
40
41class action_list(object):
42 """
43 Maintain a list of actions
44
45 Data members:
46 @arg actions: An array of action objects such as action_output, etc.
47
48 Methods:
49 @arg pack: Pack the structure into a string
50 @arg unpack: Unpack a string to objects, with proper typing
51 @arg add: Add an action to the list; you can directly access
52 the action member, but add will validate that the added object
53 is an action.
54
55 """
56
Rich Lane72a0cfe2013-01-04 14:37:53 -080057 def __init__(self, actions=None):
58 if actions == None:
59 actions = []
60 self.actions = actions
Dan Talaycof75360a2010-02-05 22:22:54 -080061
62 def pack(self):
63 """
64 Pack a list of actions
65
66 Returns the packed string
67 """
68
69 packed = ""
70 for act in self.actions:
71 packed += act.pack()
72 return packed
73
74 def unpack(self, binary_string, bytes=None):
75 """
76 Unpack a list of actions
77
78 Unpack actions from a binary string, creating an array
79 of objects of the appropriate type
80
81 @param binary_string The string to be unpacked
82
83 @param bytes The total length of the action list in bytes.
84 Ignored if decode is True. If None and decode is false, the
85 list is assumed to extend through the entire string.
86
87 @return The remainder of binary_string that was not parsed
88
89 """
90 if bytes == None:
91 bytes = len(binary_string)
92 bytes_done = 0
93 count = 0
94 cur_string = binary_string
95 while bytes_done < bytes:
96 hdr = ofp_action_header()
97 hdr.unpack(cur_string)
Dan Talaycoc398ca92010-02-07 22:57:28 -080098 if hdr.len < OFP_ACTION_HEADER_BYTES:
99 print "ERROR: Action too short"
100 break
Dan Talaycof75360a2010-02-05 22:22:54 -0800101 if not hdr.type in action_object_map.keys():
Dan Talayco56eb48d2010-02-10 22:38:24 -0800102 print "WARNING: Skipping unknown action ", hdr.type, hdr.len
Dan Talaycof75360a2010-02-05 22:22:54 -0800103 else:
Dan Talaycof75360a2010-02-05 22:22:54 -0800104 self.actions.append(action_object_map[hdr.type]())
Dan Talayco56eb48d2010-02-10 22:38:24 -0800105 self.actions[count].unpack(cur_string)
Dan Talaycof75360a2010-02-05 22:22:54 -0800106 count += 1
107 cur_string = cur_string[hdr.len:]
108 bytes_done += hdr.len
109 return cur_string
110
Rich Lanec495d9e2013-03-08 17:43:36 -0800111 def append(self, action):
Dan Talaycof75360a2010-02-05 22:22:54 -0800112 """
Rich Lanec495d9e2013-03-08 17:43:36 -0800113 Append an action to an action list
Dan Talaycof75360a2010-02-05 22:22:54 -0800114
Rich Lanec495d9e2013-03-08 17:43:36 -0800115 @param action The action to append
Dan Talaycof75360a2010-02-05 22:22:54 -0800116
Dan Talaycof75360a2010-02-05 22:22:54 -0800117 """
Rich Lanee30455b2013-01-03 16:24:44 -0800118 if not isinstance(action, action_class_list):
119 raise ValueError("%s is not an action" % type(action))
120 self.actions.append(copy.deepcopy(action))
121 return True # for backwards compatibility
Dan Talaycof75360a2010-02-05 22:22:54 -0800122
Dan Talaycoc398ca92010-02-07 22:57:28 -0800123 def remove_type(self, type):
124 """
125 Remove the first action on the list of the given type
126
127 @param type The type of action to search
128
129 @return The object removed, if any; otherwise None
130
131 """
132 for index in xrange(len(self.actions)):
133 if self.actions[index].type == type:
134 return self.actions.pop(index)
135 return None
136
137 def find_type(self, type):
138 """
139 Find the first action on the list of the given type
140
141 @param type The type of action to search
142
143 @return The object with the matching type if any; otherwise None
144
145 """
146 for index in xrange(len(self.actions)):
147 if self.actions[index].type == type:
148 return self.actions[index]
149 return None
150
151 def extend(self, other):
152 """
153 Add the actions in other to this list
154
155 @param other An object of type action_list whose
156 entries are to be merged into this list
157
158 @return True if successful. If not successful, the list
159 may have been modified.
160
161 @todo Check if this is proper deep copy or not
162
163 """
164 for act in other.actions:
Rich Lanee30455b2013-01-03 16:24:44 -0800165 self.add(act)
166 return True # for backwards compatibility
Dan Talaycoc398ca92010-02-07 22:57:28 -0800167
Dan Talaycof75360a2010-02-05 22:22:54 -0800168 def __len__(self):
169 length = 0
170 for act in self.actions:
171 length += act.__len__()
172 return length
173
174 def __eq__(self, other):
175 if type(self) != type(other): return False
176 if self.actions != other.actions: return False
177 return True
178
179 def __ne__(self, other): return not self.__eq__(other)
180
181 def show(self, prefix=''):
Dan Talayco46755fa2010-03-09 21:44:29 -0800182 outstr = prefix + "Action List with " + str(len(self.actions)) + \
183 " actions\n"
Dan Talaycof75360a2010-02-05 22:22:54 -0800184 count = 0
185 for obj in self.actions:
186 count += 1
Dan Talayco46755fa2010-03-09 21:44:29 -0800187 outstr += prefix + " Action " + str(count) + ": \n"
188 outstr += obj.show(prefix + ' ')
189 return outstr