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/cli/logical_device.py b/cli/logical_device.py
index 0545c69..9c53519 100644
--- a/cli/logical_device.py
+++ b/cli/logical_device.py
@@ -23,7 +23,7 @@
 
 from cli.table import print_pb_as_table, print_pb_list_as_table
 from cli.utils import pb2dict
-from cli.utils import print_flows, print_groups
+from cli.utils import print_flows, print_groups, print_meters
 from voltha.protos import third_party
 from google.protobuf.empty_pb2 import Empty
 
@@ -98,6 +98,16 @@
             groups=logical_device['flow_groups']['items']
         )
 
+    def do_meters(self, _):
+        """Show flow meter table for logical device"""
+        logical_device = pb2dict(self.get_logical_device(-1))
+        print_meters(
+            'Logical Device',
+            self.logical_device_id,
+            type='n/a',
+            meters=logical_device['meters']['items']
+        )
+
     def do_devices(self, line):
         """List devices that belong to this logical device"""
         logical_device = self.get_logical_device()
diff --git a/cli/utils.py b/cli/utils.py
index 544c764..82d6a12 100644
--- a/cli/utils.py
+++ b/cli/utils.py
@@ -132,8 +132,6 @@
         for field in flow['match']['oxm_fields']:
             assert field['oxm_class'].endswith('OPENFLOW_BASIC')
             ofb = field['ofb_field']
-            # see CORD-816 (https://jira.opencord.org/browse/CORD-816)
-            assert not ofb['has_mask'], 'masked match not handled yet'
             type = ofb['type'][len('OFPXMT_OFB_'):]
             table.add_cell(i, *field_printers[type](ofb))
 
@@ -146,8 +144,14 @@
             elif itype == 1:
                 table.add_cell(i, 10000, 'goto-table',
                                instruction['goto_table']['table_id'])
+            elif itype == 2:
+                table.add_cell(i, 10001, 'write-metadata',
+                               instruction['write_metadata']['metadata'])
             elif itype == 5:
-                table.add_cell(i, 10000, 'clear-actions', [])
+                table.add_cell(i, 10002, 'clear-actions', [])
+            elif itype == 6:
+                table.add_cell(i, 10003, 'meter',
+                               instruction['meter']['meter_id'])
             else:
                 raise NotImplementedError(
                     'not handling instruction type {}'.format(itype))
@@ -176,6 +180,26 @@
 
     table.print_table(header, printfn)
 
+
+def print_meters(what, id, type, meters, printfn=_printfn):
+    header = ''.join([
+        '{} '.format(what),
+        colored(id, color='green', attrs=['bold']),
+        ' (type: ',
+        colored(type, color='blue'),
+        ')'
+    ]) + '\nMeters ({}):'.format(len(meters))
+
+    table = TablePrinter()
+    for i, meter in enumerate(meters):
+        bands = []
+        for meter_band in meter['config']['bands']:
+            bands.append(meter_band)
+        table.add_cell(i, 0, 'meter_id', value=str(meter['config']['meter_id']))
+        table.add_cell(i, 1, 'meter_bands', value=str(dict(bands=bands)))
+
+    table.print_table(header, printfn)
+
 def dict2line(d):
     assert isinstance(d, dict)
     return ', '.join('{}: {}'.format(k, v) for k, v in sorted(d.items()))