Many CLI cleanups and flow preintegration

Changes:
- auto-completion for device and logical device IDs
- a set of test CLI commands to push down various flows
  to Voltha (aids test and integration)
- sample code in simulated_olt and onu to show how
  to process incoming bulk flow table
- extended Tibit OLT and ONU code with remaining flow
  directives they need to handle in the PON use-case

Change-Id: Id101e087cc79f4493805e3b4a051a10a4619bf53
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 1d7f279..1ab620d 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -30,6 +30,7 @@
 from twisted.internet.defer import DeferredQueue, inlineCallbacks
 from twisted.internet import reactor
 
+from voltha.core.flow_decomposer import *
 from voltha.core.logical_device_agent import mac_str_to_tuple
 
 from voltha.adapters.interface import IAdapterInterface
@@ -197,6 +198,145 @@
         log.debug('bulk-flow-update', device_id=device.id,
                   flows=flows, groups=groups)
 
+        # sample code that analyzes the incoming flow table
+        assert len(groups.items) == 0, "Cannot yet deal with groups"
+
+        for flow in flows.items:
+            in_port = get_in_port(flow)
+            assert in_port is not None
+
+            if in_port == 2:
+
+                # Downstream rule
+
+                for field in get_ofb_fields(flow):
+                    if field.type == ETH_TYPE:
+                        _type = field.eth_type
+                        pass  # construct ether type based condition here
+
+                    elif field.type == IP_PROTO:
+                        _proto = field.ip_proto
+                        pass  # construct ip_proto based condition here
+
+                    elif field.type == IN_PORT:
+                        _port = field.port
+                        pass  # construct in_port based condition here
+
+                    elif field.type == VLAN_VID:
+                        _vlan_vid = field.vlan_vid
+                        pass  # construct VLAN ID based filter condition here
+
+                    elif field.type == VLAN_PCP:
+                        _vlan_pcp = field.vlan_pcp
+                        pass  # construct VLAN PCP based filter condition here
+
+                    # TODO
+                    else:
+                        raise NotImplementedError('field.type={}'.format(
+                            field.type))
+
+                for action in get_actions(flow):
+
+                    if action.type == OUTPUT:
+                        pass  # construct packet emit rule here
+
+                    elif action.type == PUSH_VLAN:
+                        if action.push.ethertype != 0x8100:
+                            log.error('unhandled-ether-type',
+                                      ethertype=action.push.ethertype)
+                        pass  # construct vlan push command here
+
+                    elif action.type == POP_VLAN:
+                        pass  # construct vlan pop command here
+
+                    elif action.type == SET_FIELD:
+                        assert (action.set_field.field.oxm_class ==
+                                ofp.OFPXMC_OPENFLOW_BASIC)
+                        field = action.set_field.field.ofb_field
+                        if field.type == VLAN_VID:
+                            pass  # construct vlan_id set command here
+                        else:
+                            log.error('unsupported-action-set-field-type',
+                                      field_type=field.type)
+
+                    else:
+                        log.error('unsupported-action-type',
+                                  action_type=action.type)
+
+                # final assembly of low level device flow rule and pushing it
+                # down to device
+                pass
+
+            elif in_port == 1:
+
+                # Upstream rule
+
+                for field in get_ofb_fields(flow):
+                    if field.type == ETH_TYPE:
+                        _type = field.eth_type
+                        pass  # construct ether type based condition here
+
+                    elif field.type == IP_PROTO:
+                        _proto = field.ip_proto
+                        pass  # construct ip_proto based condition here
+
+                    elif field.type == IN_PORT:
+                        _port = field.port
+                        pass  # construct in_port based condition here
+
+                    elif field.type == VLAN_VID:
+                        _vlan_vid = field.vlan_vid
+                        pass  # construct VLAN ID based filter condition here
+
+                    elif field.type == VLAN_PCP:
+                        _vlan_pcp = field.vlan_pcp
+                        pass  # construct VLAN PCP based filter condition here
+
+                    elif field.type == IPV4_DST:
+                        _ipv4_dst = field.ipv4_dst
+                        pass  # construct IPv4 DST address based condition
+
+                    elif field.type == UDP_DST:
+                        _udp_dst = field.udp_dst
+                        pass  # construct UDP SDT based filter here
+
+                    # TODO
+                    else:
+                        raise NotImplementedError('field.type={}'.format(
+                            field.type))
+
+                for action in get_actions(flow):
+
+                    if action.type == OUTPUT:
+                        pass  # construct packet emit rule here
+
+                    elif action.type == PUSH_VLAN:
+                        if action.push.ethertype != 0x8100:
+                            log.error('unhandled-ether-type',
+                                      ethertype=action.push.ethertype)
+                        pass  # construct vlan push command here
+
+                    elif action.type == SET_FIELD:
+                        assert (action.set_field.field.oxm_class ==
+                                ofp.OFPXMC_OPENFLOW_BASIC)
+                        field = action.set_field.field.ofb_field
+                        if field.type == VLAN_VID:
+                            pass  # construct vlan_id set command here
+                        else:
+                            log.error('unsupported-action-set-field-type',
+                                      field_type=field.type)
+
+                    else:
+                        log.error('unsupported-action-type',
+                                  action_type=action.type)
+
+                # final assembly of low level device flow rule and pushing it
+                # down to device
+                pass
+
+            else:
+                raise Exception('Port should be 1 or 2 by our convention')
+
     def update_flows_incrementally(self, device, flow_changes, group_changes):
         raise NotImplementedError()