Flow decomposer support for Tech Profile Reference in metadata instead of using Flow Table ID as reference in Table 1.

Also in this patch:
 - Update flow count field of meter stats
 - ONU root field was True and because of this flow decomposer was not working properly - it is fixed (now onu root field is false) - related to VOL-1354
 - Meter & write metadata support is added to vcli
 - No-action (drop) flow support is added.
 - Removed broken wildcard inport support and in-band control support
 - Meter functions (meter stats reply, meter modify etc.) are fixed
 - Metadata information  passed on to the OLT and ONU Adapters.
 - Meter Reference in all Flow Tables passed on to the OLT and ONU Adapters.
 - Fixed unit tests and added more unit tests
 - Fixed ponsim (partially) to deal with changes to flow decomposer

Change-Id: Id4b16fc05a6740a3f521b2cc4f6fdbff88da4fa5
diff --git a/ofagent/converter.py b/ofagent/converter.py
index fb7aae5..7156d60 100644
--- a/ofagent/converter.py
+++ b/ofagent/converter.py
@@ -31,6 +31,7 @@
     FieldDescriptor.TYPE_STRING: str
 })
 
+
 def pb2dict(pb):
     """
     Convert protobuf to a dict of values good for instantiating
@@ -41,33 +42,53 @@
     """
     return protobuf_to_dict(pb, type_callable_map)
 
+
 def to_loxi(grpc_object):
     cls = grpc_object.__class__
     converter = to_loxi_converters[cls.__name__]
     return converter(grpc_object)
 
+
 def to_grpc(loxi_object):
     cls = loxi_object.__class__
     converter = to_grpc_converters[cls]
     return converter(loxi_object)
 
+
 def ofp_port_to_loxi_port_desc(pb):
     kw = pb2dict(pb)
     return of13.common.port_desc(**kw)
 
+
 def ofp_port_status_to_loxi_port_status(pb):
     return of13.message.port_status(
         reason=pb.reason,
         desc=ofp_port_to_loxi_port_desc(pb.desc)
     )
 
+
 def ofp_port_stats_to_loxi_port_stats(pb):
     kw = pb2dict(pb)
     return of13.port_stats_entry(**kw)
 
+
 def ofp_meter_stats_to_loxi_meter_stats(pb):
-    kw = pb2dict(pb)
-    return of13.meter_stats(**kw)
+    return of13.meter_stats(
+        meter_id=pb.meter_id,
+        flow_count=pb.flow_count,
+        packet_in_count=pb.packet_in_count,
+        byte_in_count=pb.byte_in_count,
+        duration_sec=pb.duration_sec,
+        duration_nsec=pb.duration_nsec,
+        band_stats=[to_loxi(band_stat) for band_stat in pb.band_stats])
+
+
+def ofp_meter_band_stats_to_loxi_meter_stats(pb):
+    return of13.meter_band_stats(
+        packet_band_count=pb.packet_band_count,
+        byte_band_count=pb.byte_band_count
+    )
+
 
 def make_loxi_field(oxm_field):
     assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
@@ -87,6 +108,9 @@
             of13.oxm.ip_proto(value=ofb_field['ip_proto']))
 
     elif field_type == pb2.OFPXMT_OFB_VLAN_VID:
+        if ofb_field.get('has_mask', 0):
+            return of13.oxm.vlan_vid_masked(value=ofb_field['vlan_vid'],
+                                            value_mask=ofb_field['vlan_vid_mask'])
         return (
             of13.oxm.vlan_vid(value=ofb_field['vlan_vid']))
 
@@ -118,6 +142,7 @@
         raise NotImplementedError(
             'OXM match field for type %s' % field_type)
 
+
 def make_loxi_match(match):
     assert match.get('type', pb2.OFPMT_STANDARD) == pb2.OFPMT_OXM
     loxi_match_fields = []
@@ -174,12 +199,20 @@
             return of13.instruction.write_actions(
                 actions=[make_loxi_action(a)
                          for a in inst['actions']['actions']])
+        elif type == pb2.OFPIT_WRITE_METADATA:
+            return of13.instruction.write_metadata(
+                metadata=inst['write_metadata']['metadata'])
+        elif type == pb2.OFPIT_METER:
+            return of13.instruction.meter(
+                meter_id=inst['meter']['meter_id'])
 
         else:
             raise NotImplementedError('Instruction type %d' % type)
 
     kw['match'] = make_loxi_match(kw['match'])
-    kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
+    # if the flow action is drop, then the instruction is not found in the dict
+    if 'instructions' in kw:
+        kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
     del kw['id']
     return of13.flow_stats_entry(**kw)
 
@@ -195,6 +228,7 @@
     )
     return packet_in
 
+
 def ofp_group_desc_to_loxi_group_desc(pb):
     return of13.group_desc_stats_entry(
         group_type=pb.type,
@@ -239,7 +273,8 @@
     'ofp_bucket': ofp_bucket_to_loxi_bucket,
     'ofp_action': make_loxi_action,
     'ofp_port_stats': ofp_port_stats_to_loxi_port_stats,
-    'ofp_meter_stats': ofp_meter_stats_to_loxi_meter_stats
+    'ofp_meter_stats': ofp_meter_stats_to_loxi_meter_stats,
+    'ofp_meter_band_stats': ofp_meter_band_stats_to_loxi_meter_stats
 }
 
 
@@ -259,6 +294,7 @@
         match=to_grpc(lo.match),
         instructions=[to_grpc(i) for i in lo.instructions])
 
+
 def loxi_meter_mod_to_ofp_meter_mod(lo):
     return pb2.ofp_meter_mod(
         command=lo.command,
@@ -368,6 +404,16 @@
             vlan_vid=lo.value))
 
 
+def loxi_oxm_vlan_vid_masked_to_ofp_oxm(lo):
+    return pb2.ofp_oxm_field(
+        oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
+        ofb_field=pb2.ofp_oxm_ofb_field(
+            type=pb2.OFPXMT_OFB_VLAN_VID,
+            has_mask=True,
+            vlan_vid=lo.value,
+            vlan_vid_mask=lo.value_mask))
+
+
 def loxi_oxm_vlan_pcp_to_ofp_oxm(lo):
     return pb2.ofp_oxm_field(
         oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
@@ -425,6 +471,20 @@
         goto_table=pb2.ofp_instruction_goto_table(table_id=lo.table_id))
 
 
+def loxi_write_metadata_to_ofp_instruction(lo):
+    return pb2.ofp_instruction(
+        type=pb2.OFPIT_WRITE_METADATA,
+        write_metadata=pb2.ofp_instruction_write_metadata(
+            metadata=lo.metadata,
+            metadata_mask=lo.metadata_mask))
+
+
+def loxi_meter_to_ofp_instruction(lo):
+    return pb2.ofp_instruction(
+        type=pb2.OFPIT_METER,
+        meter=pb2.ofp_instruction_meter(meter_id=lo.meter_id))
+
+
 def loxi_output_action_to_ofp_action(lo):
     return pb2.ofp_action(
         type=pb2.OFPAT_OUTPUT,
@@ -486,6 +546,7 @@
     of13.oxm.in_port: loxi_oxm_in_port_to_ofp_oxm,
     of13.oxm.ip_proto: loxi_oxm_ip_proto_to_ofp_oxm,
     of13.oxm.vlan_vid: loxi_oxm_vlan_vid_to_ofp_oxm,
+    of13.oxm.vlan_vid_masked: loxi_oxm_vlan_vid_masked_to_ofp_oxm,
     of13.oxm.vlan_pcp: loxi_oxm_vlan_pcp_to_ofp_oxm,
     of13.oxm.ipv4_dst: loxi_oxm_ipv4_dst_to_ofp_oxm,
     of13.oxm.udp_src: loxi_oxm_udp_src_to_ofp_oxm,
@@ -496,6 +557,8 @@
     of13.instruction.clear_actions: loxi_clear_actions_to_ofp_instruction,
     of13.instruction.write_actions: loxi_write_actions_to_ofp_instruction,
     of13.instruction.goto_table: loxi_goto_table_to_ofp_instruction,
+    of13.instruction.write_metadata: loxi_write_metadata_to_ofp_instruction,
+    of13.instruction.meter: loxi_meter_to_ofp_instruction,
 
     of13.action.output: loxi_output_action_to_ofp_action,
     of13.action.group: loxi_group_action_to_ofp_action,