loxi-prep: use plain lists to hold OF actions

Some callsites needed to be changed because they depended on action_list.append
taking a shallow copy.
diff --git a/src/python/of10/message.py b/src/python/of10/message.py
index 4f5a43f..849c15a 100644
--- a/src/python/of10/message.py
+++ b/src/python/of10/message.py
@@ -904,8 +904,6 @@
                 setattr(self, k, v)
             else:
                 raise NameError("field %s does not exist in %s" % (k, self.__class__))
-        # Coerce keyword arg into list type
-        self.actions = action_list(self.actions)
 
 
     def pack(self):
@@ -919,7 +917,7 @@
         packed = self.header.pack()
 
         packed += ofp_flow_mod.pack(self)
-        packed += self.actions.pack()
+        packed += action_list(self.actions).pack()
         return packed
 
     def unpack(self, binary_string):
@@ -935,7 +933,9 @@
 
         binary_string = ofp_flow_mod.unpack(self, binary_string)
         ai_len = self.header.length - (OFP_FLOW_MOD_BYTES + OFP_HEADER_BYTES)
-        binary_string = self.actions.unpack(binary_string, bytes=ai_len)
+        obj = action_list()
+        binary_string = obj.unpack(binary_string, bytes=ai_len)
+        self.actions = list(obj)
         # Fixme: If no self.data, add check for data remaining
         return binary_string
 
@@ -950,7 +950,8 @@
         length = OFP_HEADER_BYTES
 
         length += ofp_flow_mod.__len__(self)
-        length += len(self.actions)
+        for obj in self.actions:
+            length += len(obj)
         return length
 
     def show(self, prefix=''):
@@ -1580,8 +1581,6 @@
                 setattr(self, k, v)
             else:
                 raise NameError("field %s does not exist in %s" % (k, self.__class__))
-        # Coerce keyword arg into list type
-        self.actions = action_list(self.actions)
 
 
     def pack(self):
@@ -1594,9 +1593,11 @@
         self.header.length = len(self)
         packed = self.header.pack()
 
-        self.actions_len = len(self.actions)
+        self.actions_len = 0
+        for obj in self.actions:
+            self.actions_len += len(obj)
         packed += ofp_packet_out.pack(self)
-        packed += self.actions.pack()
+        packed += action_list(self.actions).pack()
         packed += self.data
         return packed
 
@@ -1612,7 +1613,9 @@
         binary_string = self.header.unpack(binary_string)
 
         binary_string = ofp_packet_out.unpack(self, binary_string)
-        binary_string = self.actions.unpack(binary_string, bytes=self.actions_len)
+        obj = action_list()
+        binary_string = obj.unpack(binary_string, bytes=self.actions_len)
+        self.actions = list(obj)
         self.data = binary_string
         binary_string = ''
         return binary_string
@@ -1628,7 +1631,8 @@
         length = OFP_HEADER_BYTES
 
         length += ofp_packet_out.__len__(self)
-        length += len(self.actions)
+        for obj in self.actions:
+            length += len(obj)
         length += len(self.data)
         return length
 
@@ -2642,12 +2646,12 @@
     """
     def __init__(self):
         ofp_flow_stats.__init__(self)
-        self.actions = action_list()
+        self.actions = []
 
     def pack(self, assertstruct=True):
         self.length = len(self)
         packed = ofp_flow_stats.pack(self, assertstruct)
-        packed += self.actions.pack()
+        packed += action_list(self.actions).pack()
         if len(packed) != self.length:
             print("ERROR: flow_stats_entry pack length not equal",
                   self.length, len(packed))
@@ -2659,7 +2663,9 @@
         if ai_len < 0:
             print("ERROR: flow_stats_entry unpack length too small",
                   self.length)
-        binary_string = self.actions.unpack(binary_string, bytes=ai_len)
+        obj = action_list()
+        binary_string = obj.unpack(binary_string, bytes=ai_len)
+        self.actions = list(obj)
         return binary_string
 
     def __len__(self):
diff --git a/tests/flow_query.py b/tests/flow_query.py
index ee72fc3..2d5c7b5 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -69,7 +69,6 @@
 import oftest.controller  as controller
 import ofp
 import oftest.dataplane   as dataplane
-import oftest.action_list as action_list
 import oftest.parse       as parse
 import pktact
 import oftest.base_tests as base_tests
@@ -333,7 +332,7 @@
     # - idle_timeout
     # - hard_timeout
     # - priority
-    # - action_list
+    # - actions
 
     def __init__(self):
         self.priority        = 0
@@ -341,7 +340,7 @@
         self.match.wildcards = ofp.OFPFW_ALL
         self.idle_timeout    = 0
         self.hard_timeout    = 0
-        self.actions         = action_list.action_list()
+        self.actions         = []
 
     # {pri, match} is considered a flow key
     def key_equal(self, x):
@@ -396,8 +395,8 @@
         if test_param_get("conservative_ordered_actions", True):
             # Compare actions lists as unordered
             
-            aa = copy.deepcopy(x.actions.actions)
-            for a in self.actions.actions:
+            aa = copy.deepcopy(x.actions)
+            for a in self.actions:
                 i = 0
                 while i < len(aa):
                     if a == aa[i]:
@@ -473,7 +472,7 @@
         result = result + (", cookie=%d" % self.cookie)
         result = result + (", idle_timeout=%d" % self.idle_timeout)
         result = result + (", hard_timeout=%d" % self.hard_timeout)
-        for a in self.actions.actions:
+        for a in self.actions:
             result = result + (", action=%s" % ofp.ofp_action_type_map[a.type])
             if a.type == ofp.OFPAT_OUTPUT:
                 result = result + ("(%d)" % (a.port))
@@ -519,7 +518,7 @@
 
         set_vlanf   = False
         strip_vlanf = False
-        self.actions = action_list.action_list()
+        self.actions = []
         for a in actions:
             act = None
             if a == ofp.OFPAT_OUTPUT:
@@ -627,7 +626,7 @@
 
         actions = shuffle(actions)
 
-        self.actions = action_list.action_list()
+        self.actions = []
         for a in actions:
             if a == ofp.OFPAT_OUTPUT:
                 # TBD - Output actions are clustered in list, spread them out?
diff --git a/tests/pktact.py b/tests/pktact.py
index 9e81af6..bd3e79f 100644
--- a/tests/pktact.py
+++ b/tests/pktact.py
@@ -501,7 +501,6 @@
         match.wildcards &= ~ofp.OFPFW_IN_PORT
         self.assertTrue(match is not None, 
                         "Could not generate flow match from pkt")
-        act = ofp.action.output()
 
         for idx in range(len(of_ports)):
             delete_all_flows(self.controller)
@@ -518,10 +517,8 @@
             request = ofp.message.flow_mod()
             request.match = match
             request.buffer_id = 0xffffffff
-            act.port = egress_port1
-            request.actions.append(act)
-            act.port = egress_port2
-            request.actions.append(act)
+            request.actions.append(ofp.action.output(port=egress_port1))
+            request.actions.append(ofp.action.output(port=egress_port2))
             # logging.info(request.show())
 
             logging.info("Inserting flow")
@@ -559,7 +556,6 @@
         match.wildcards &= ~ofp.OFPFW_IN_PORT
         self.assertTrue(match is not None, 
                         "Could not generate flow match from pkt")
-        act = ofp.action.output()
 
         for ingress_port in of_ports:
             delete_all_flows(self.controller)
@@ -574,8 +570,7 @@
             for egress_port in of_ports:
                 if egress_port == ingress_port:
                     continue
-                act.port = egress_port
-                request.actions.append(act)
+                request.actions.append(ofp.action.output(port=egress_port))
             logging.debug(request.show())
 
             logging.info("Inserting flow")
@@ -611,7 +606,6 @@
         match.wildcards &= ~ofp.OFPFW_IN_PORT
         self.assertTrue(match is not None, 
                         "Could not generate flow match from pkt")
-        act = ofp.action.output()
 
         for ingress_port in of_ports:
             delete_all_flows(self.controller)
@@ -623,6 +617,7 @@
             request.match = match
             request.buffer_id = 0xffffffff
             for egress_port in of_ports:
+                act = ofp.action.output()
                 if egress_port == ingress_port:
                     act.port = ofp.OFPP_IN_PORT
                 else:
@@ -713,7 +708,6 @@
         match.wildcards &= ~ofp.OFPFW_IN_PORT
         self.assertTrue(match is not None, 
                         "Could not generate flow match from pkt")
-        act = ofp.action.output()
 
         for ingress_port in of_ports:
             delete_all_flows(self.controller)
@@ -724,10 +718,8 @@
             request = ofp.message.flow_mod()
             request.match = match
             request.buffer_id = 0xffffffff
-            act.port = ofp.OFPP_FLOOD
-            request.actions.append(act)
-            act.port = ofp.OFPP_IN_PORT
-            request.actions.append(act)
+            request.actions.append(ofp.action.output(port=ofp.OFPP_FLOOD))
+            request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
             logging.info(request.show())
 
             logging.info("Inserting flow")
@@ -804,7 +796,6 @@
         match.wildcards &= ~ofp.OFPFW_IN_PORT
         self.assertTrue(match is not None, 
                         "Could not generate flow match from pkt")
-        act = ofp.action.output()
 
         for ingress_port in of_ports:
             delete_all_flows(self.controller)
@@ -815,10 +806,8 @@
             request = ofp.message.flow_mod()
             request.match = match
             request.buffer_id = 0xffffffff
-            act.port = ofp.OFPP_ALL
-            request.actions.append(act)
-            act.port = ofp.OFPP_IN_PORT
-            request.actions.append(act)
+            request.actions.append(ofp.action.output(port=ofp.OFPP_ALL))
+            request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
             logging.info(request.show())
 
             logging.info("Inserting flow")
diff --git a/tools/munger/scripts/message_gen.py b/tools/munger/scripts/message_gen.py
index 6761935..5d771e3 100644
--- a/tools/munger/scripts/message_gen.py
+++ b/tools/munger/scripts/message_gen.py
@@ -310,9 +310,6 @@
     _p4('setattr(self, k, v)')
     _p3('else:')
     _p4('raise NameError("field %s does not exist in %s" % (k, self.__class__))')
-    if has_list and list_type != None:
-        _p2('# Coerce keyword arg into list type')
-        _p2('self.%(list_var)s = %(list_type)s(self.%(list_var)s)' % dict(list_type=list_type, list_var=list_var))
 
     print """
 
@@ -329,7 +326,9 @@
 
     # Have to special case the action length calculation for pkt out
     if msg == 'packet_out':
-        _p2('self.actions_len = len(self.actions)')
+        _p2('self.actions_len = 0')
+        _p2('for obj in self.actions:')
+        _p3('self.actions_len += len(obj)')
     if has_core_members:
         _p2("packed += " + parent + ".pack(self)")
     if has_list:
@@ -337,7 +336,7 @@
             _p2('for obj in self.' + list_var + ':')
             _p3('packed += obj.pack()')
         else:
-            _p2('packed += self.' + list_var + '.pack()')
+            _p2('packed += ' + list_type + '(self.' + list_var + ').pack()')
     if has_string:
         _p2('packed += self.data')
     _p2("return packed")
@@ -367,15 +366,21 @@
             _p2("for obj in self." + list_var + ":")
             _p3("binary_string = obj.unpack(binary_string)")
         elif msg == "packet_out":  # Special case this
-            _p2('binary_string = self.actions.unpack(' + 
+            _p2("obj = action_list()")
+            _p2('binary_string = obj.unpack(' + 
                 'binary_string, bytes=self.actions_len)')
+            _p2("self.actions = list(obj)")
         elif msg == "flow_mod":  # Special case this
             _p2("ai_len = self.header.length - (OFP_FLOW_MOD_BYTES + " + 
                 "OFP_HEADER_BYTES)")
-            _p2("binary_string = self.actions.unpack(binary_string, " +
+            _p2("obj = action_list()")
+            _p2("binary_string = obj.unpack(binary_string, " +
                 "bytes=ai_len)")
+            _p2("self.actions = list(obj)")
         else:
-            _p2("binary_string = self." + list_var + ".unpack(binary_string)")
+            _p2("obj = " + list_type + "()")
+            _p2("binary_string = obj.unpack(binary_string)")
+            _p2("self." + list_var + " = list(obj)")
     if has_string:
         _p2("self.data = binary_string")
         _p2("binary_string = ''")
@@ -397,11 +402,8 @@
     if has_core_members:
         _p2("length += " + parent + ".__len__(self)")
     if has_list:
-        if list_type == None:
-            _p2("for obj in self." + list_var + ":")
-            _p3("length += len(obj)")
-        else:
-            _p2("length += len(self." + list_var + ")")
+        _p2("for obj in self." + list_var + ":")
+        _p3("length += len(obj)")
     if has_string:
         _p2("length += len(self.data)")
     _p2("return length")
@@ -680,12 +682,12 @@
     \"""
     def __init__(self):
         ofp_flow_stats.__init__(self)
-        self.actions = action_list()
+        self.actions = []
 
     def pack(self, assertstruct=True):
         self.length = len(self)
         packed = ofp_flow_stats.pack(self, assertstruct)
-        packed += self.actions.pack()
+        packed += action_list(self.actions).pack()
         if len(packed) != self.length:
             print("ERROR: flow_stats_entry pack length not equal",
                   self.length, len(packed))
@@ -697,7 +699,9 @@
         if ai_len < 0:
             print("ERROR: flow_stats_entry unpack length too small",
                   self.length)
-        binary_string = self.actions.unpack(binary_string, bytes=ai_len)
+        obj = action_list()
+        binary_string = obj.unpack(binary_string, bytes=ai_len)
+        self.actions = list(obj)
         return binary_string
 
     def __len__(self):