VOL-1023 - Supporting multiple UNI per ONU

Added support for multiple UNIs per ONU by enabling an opt-in parameter in Resource Manager Profile
attribute key "uni_id_start" and "uni_id_end". This represents the 0 based local-device uni
index range. So, for an ONU to support a single UNI, the default (including omitted) value is 0.
To support multiple UNIs per ONU, set "uni_id_end" to the maximum (0-based) index on the ONU.

Plumbed in support throughout for multiple UNIs. Each UNI receives a dedicated TCONT/GEM from
TechProfile and is applied a dedicated MAC Bridge Instance in the ONU. Each UNI is effectively
treated the same whether on the same or different ONUs.

uni_id is used throughout to be the ONU-relative device port number (0-based)
port_no is the logical port number

Change-Id: I443d2322a2d414a358f1e0c629779c4929ce13c8
diff --git a/voltha/adapters/brcm_openomci_onu/uni_port.py b/voltha/adapters/brcm_openomci_onu/uni_port.py
index a887531..c8aca6b 100644
--- a/voltha/adapters/brcm_openomci_onu/uni_port.py
+++ b/voltha/adapters/brcm_openomci_onu/uni_port.py
@@ -35,7 +35,7 @@
 class UniPort(object):
     """Wraps southbound-port(s) support for ONU"""
 
-    def __init__(self, handler, name, port_no, ofp_port_no,
+    def __init__(self, handler, name, uni_id, port_no, ofp_port_no,
                  type=UniType.PPTP):
         self.log = structlog.get_logger(device_id=handler.device_id,
                                         port_no=port_no)
@@ -49,6 +49,7 @@
         self._entity_id = None
         self._mac_bridge_port_num = 0
         self._type = type
+        self._uni_id = uni_id
 
         self._admin_state = AdminState.ENABLED
         self._oper_status = OperStatus.ACTIVE
@@ -57,8 +58,8 @@
         return "UniPort: {}:{}".format(self.name, self.port_number)
 
     @staticmethod
-    def create(handler, name, port_no, ofp_port_no, type):
-        port = UniPort(handler, name, port_no, ofp_port_no, type)
+    def create(handler, name, uni_id, port_no, ofp_port_no, type):
+        port = UniPort(handler, name, uni_id, port_no, ofp_port_no, type)
         return port
 
     def _start(self):
@@ -99,6 +100,15 @@
                 self._stop()
 
     @property
+    def uni_id(self):
+        """
+        Physical prt index on ONU 0 - N
+        :return: (int) uni id
+        """
+        return self._uni_id
+
+
+    @property
     def mac_bridge_port_num(self):
         """
         Port number used when creating MacBridgePortConfigurationDataFrame port number
@@ -178,9 +188,9 @@
         return self._port
 
     def port_id_name(self):
-        return 'uni-{}'.format(self._logical_port_number)
+        return 'uni-{}'.format(self._port_number)
 
-    def add_logical_port(self, openflow_port_no,
+    def add_logical_port(self, openflow_port_no, multi_uni_naming,
                          capabilities=OFPPF_10GB_FD | OFPPF_FIBER,
                          speed=OFPPF_10GB_FD):
 
@@ -209,12 +219,13 @@
             # leave the ports down until omci mib download has finished.  otherwise flows push before time
             openflow_port = ofp_port(
                 port_no=port_no,
-                hw_addr=mac_str_to_tuple('08:00:%02x:%02x:%02x:%02x' %
+                hw_addr=mac_str_to_tuple('08:%02x:%02x:%02x:%02x:%02x' %
                                          ((device.parent_port_no >> 8 & 0xff),
                                           device.parent_port_no & 0xff,
+                                          (port_no >> 16) & 0xff,
                                           (port_no >> 8) & 0xff,
                                           port_no & 0xff)),
-                name=device.serial_number,
+                name=device.serial_number + ['', '-' + str(self._mac_bridge_port_num)][multi_uni_naming],
                 config=0,
                 state=OFPPS_LINK_DOWN,
                 curr=capabilities,
@@ -230,4 +241,4 @@
                                                              device_id=device.id,
                                                              device_port_no=self._port_number))
 
-            self.log.debug('logical-port', openflow_port=openflow_port)
+            self.log.debug('logical-port', id=self.port_id_name(), device_port_no=self._port_number, openflow_port=openflow_port)