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/common/pon_resource_manager/resource_manager.py b/common/pon_resource_manager/resource_manager.py
index 9e249fb..a88b407 100644
--- a/common/pon_resource_manager/resource_manager.py
+++ b/common/pon_resource_manager/resource_manager.py
@@ -43,6 +43,7 @@
"""Implements APIs to initialize/allocate/release alloc/gemport/onu IDs."""
# Constants to identify resource pool
+ UNI_ID = 'UNI_ID'
ONU_ID = 'ONU_ID'
ALLOC_ID = 'ALLOC_ID'
GEMPORT_ID = 'GEMPORT_ID'
@@ -67,12 +68,16 @@
"gemport_id_end": 8960,
"flow_id_start": 1,
"flow_id_end": 16383,
+ "uni_id_start": 0,
+ "uni_id_end": 0,
"pon_ports": 16
}
'''
# constants used as keys to reference the resource range parameters from
# and external KV store.
+ UNI_ID_START_IDX = "uni_id_start"
+ UNI_ID_END_IDX = "uni_id_end"
ONU_ID_START_IDX = "onu_id_start"
ONU_ID_END_IDX = "onu_id_end"
ONU_ID_SHARED_IDX = "onu_id_shared"
@@ -202,7 +207,16 @@
resource_range_config = result
if resource_range_config is not None:
- self.pon_resource_ranges = json.loads(resource_range_config)
+ # update internal ranges from kv ranges. If there are missing
+ # values in the KV profile, continue to use the defaults
+ for key,value in json.loads(resource_range_config): self.pon_resource_ranges[key] = value
+
+ # initialize optional elements that may not be in the profile
+ if self.pon_resource_ranges[PONResourceManager.UNI_ID_START_IDX] is None:
+ self.pon_resource_ranges[PONResourceManager.UNI_ID_START_IDX] = 0
+ if self.pon_resource_ranges[PONResourceManager.UNI_ID_END_IDX] is None:
+ self.pon_resource_ranges[PONResourceManager.UNI_ID_END_IDX] = 0
+
self._log.debug("Init-resource-ranges-from-kvstore-success",
pon_resource_ranges=self.pon_resource_ranges,
path=path)
@@ -213,7 +227,8 @@
e=e)
return False
- def update_range_(self, start_idx, start, end_idx, end, shared_idx, shared_pool_id, shared_resource_mgr):
+ def update_range_(self, start_idx, start, end_idx, end, shared_idx = None, shared_pool_id = None,
+ shared_resource_mgr = None):
if (start is not None) and \
(start_idx not in self.pon_resource_ranges or self.pon_resource_ranges[start_idx] < start):
self.pon_resource_ranges[start_idx] = start
@@ -243,7 +258,9 @@
flow_id_start_idx=None,
flow_id_end_idx=None,
flow_id_shared_pool_id=None,
- flow_id_shared_resource_mgr=None):
+ flow_id_shared_resource_mgr=None,
+ uni_id_start_idx=None,
+ uni_id_end_idx=None):
self.update_range_(PONResourceManager.ONU_ID_START_IDX, onu_id_start_idx,
PONResourceManager.ONU_ID_END_IDX, onu_id_end_idx,
@@ -265,6 +282,9 @@
PONResourceManager.FLOW_ID_SHARED_IDX, flow_id_shared_pool_id,
flow_id_shared_resource_mgr)
+ self.update_range_(PONResourceManager.UNI_ID_START_IDX, uni_id_start_idx,
+ PONResourceManager.UNI_ID_END_IDX, uni_id_end_idx)
+
def init_default_pon_resource_ranges(self,
onu_id_start_idx=1,
onu_id_end_idx=127,
@@ -278,6 +298,8 @@
flow_id_start_idx=1,
flow_id_end_idx=16383,
flow_id_shared_pool_id=None,
+ uni_id_start_idx=0,
+ uni_id_end_idx=0,
num_of_pon_ports=16,
intf_ids=None):
"""
@@ -303,7 +325,8 @@
self.update_ranges(onu_id_start_idx, onu_id_end_idx, onu_id_shared_pool_id, None,
alloc_id_start_idx, alloc_id_end_idx, alloc_id_shared_pool_id, None,
gemport_id_start_idx, gemport_id_end_idx, gemport_id_shared_pool_id, None,
- flow_id_start_idx, flow_id_end_idx, flow_id_shared_pool_id, None)
+ flow_id_start_idx, flow_id_end_idx, flow_id_shared_pool_id, None,
+ uni_id_start_idx, uni_id_end_idx)
if intf_ids is None:
intf_ids = range(0, num_of_pon_ports)
@@ -468,6 +491,27 @@
return status
+ def assert_resource_limits(self, id, resource_type):
+ """
+ Assert the specified id value is in the limit bounds of he requested resource type.
+
+ :param id: The value to assert is in limits
+ :param resource_type: String to identify type of resource
+ """
+ start_idx = PONResourceManager.ONU_ID_START_IDX if resource_type == PONResourceManager.ONU_ID \
+ else PONResourceManager.ALLOC_ID_START_IDX if resource_type == PONResourceManager.ALLOC_ID \
+ else PONResourceManager.GEMPORT_ID_START_IDX if resource_type == PONResourceManager.GEMPORT_ID \
+ else PONResourceManager.FLOW_ID_START_IDX if resource_type == PONResourceManager.FLOW_ID \
+ else PONResourceManager.UNI_ID_START_IDX if resource_type == PONResourceManager.UNI_ID \
+ else None
+ end_idx = PONResourceManager.ONU_ID_END_IDX if resource_type == PONResourceManager.ONU_ID \
+ else PONResourceManager.ALLOC_ID_END_IDX if resource_type == PONResourceManager.ALLOC_ID \
+ else PONResourceManager.GEMPORT_ID_END_IDX if resource_type == PONResourceManager.GEMPORT_ID \
+ else PONResourceManager.FLOW_ID_END_IDX if resource_type == PONResourceManager.FLOW_ID \
+ else PONResourceManager.UNI_ID_END_IDX if resource_type == PONResourceManager.UNI_ID \
+ else None
+ assert id >= self.pon_resource_ranges[start_idx] and id <= self.pon_resource_ranges[end_idx]
+
def get_resource_id(self, pon_intf_id, resource_type, num_of_id=1):
"""
Create alloc/gemport/onu/flow id for given OLT PON interface.
diff --git a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index f3fdf9f..fde2591 100644
--- a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -21,6 +21,9 @@
import json
import ast
import structlog
+
+from collections import OrderedDict
+
from twisted.internet import reactor, task
from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue, TimeoutError
@@ -60,7 +63,6 @@
log = structlog.get_logger()
_STARTUP_RETRY_WAIT = 20
-_MAXIMUM_PORT = 128 # UNI ports
class BrcmOpenomciOnuHandler(object):
@@ -86,7 +88,6 @@
self._onu_indication = None
self._unis = dict() # Port # -> UniPort
- self._port_number_pool = IndexPool(_MAXIMUM_PORT, 0)
self._pon = None
# TODO: probably shouldnt be hardcoded, determine from olt maybe?
@@ -158,19 +159,13 @@
if uni.name == port_no_or_name), None)
assert isinstance(port_no_or_name, int), 'Invalid parameter type'
- return self._unis.get(port_no_or_name)
+ return next((uni for uni in self.uni_ports
+ if uni.logical_port_number == port_no_or_name), None)
@property
def pon_port(self):
return self._pon
- @property
- def _next_port_number(self):
- return self._port_number_pool.get_next()
-
- def _release_port_number(self, number):
- self._port_number_pool.release(number)
-
def receive_message(self, msg):
if self.omci_cc is not None:
self.omci_cc.receive_message(msg)
@@ -275,7 +270,8 @@
try:
if event_msg['event'] == 'download_tech_profile':
tp_path = event_msg['event_data']
- self.load_and_configure_tech_profile(tp_path)
+ uni_id = event_msg['uni_id']
+ self.load_and_configure_tech_profile(uni_id, tp_path)
except Exception as e:
self.log.error("exception-handling-onu-event", e=e)
@@ -328,7 +324,7 @@
else:
self.log.debug("parent-adapter-not-available")
- def _create_tconts(self, us_scheduler):
+ def _create_tconts(self, uni_id, us_scheduler):
alloc_id = us_scheduler['alloc_id']
q_sched_policy = us_scheduler['q_sched_policy']
self.log.debug('create-tcont', us_scheduler=us_scheduler)
@@ -336,6 +332,7 @@
tcontdict = dict()
tcontdict['alloc-id'] = alloc_id
tcontdict['q_sched_policy'] = q_sched_policy
+ tcontdict['uni_id'] = uni_id
# TODO: Not sure what to do with any of this...
tddata = dict()
@@ -353,7 +350,7 @@
self.log.debug('pon-add-tcont', tcont=tcont)
# Called when there is an olt up indication, providing the gem port id chosen by the olt handler
- def _create_gemports(self, gem_ports, alloc_id_ref, direction):
+ def _create_gemports(self, uni_id, gem_ports, alloc_id_ref, direction):
self.log.debug('create-gemport',
gem_ports=gem_ports, direction=direction)
@@ -376,6 +373,7 @@
gemdict['priority_q'] = gem_port['priority_q']
gemdict['scheduling_policy'] = gem_port['scheduling_policy']
gemdict['weight'] = gem_port['weight']
+ gemdict['uni_id'] = uni_id
gem_port = OnuGemPort.create(self, gem_port=gemdict, entity_id=self._pon.next_gem_entity_id)
@@ -383,24 +381,31 @@
self.log.debug('pon-add-gemport', gem_port=gem_port)
- def _do_tech_profile_configuration(self, tp):
+ def _do_tech_profile_configuration(self, uni_id, tp):
num_of_tconts = tp['num_of_tconts']
us_scheduler = tp['us_scheduler']
alloc_id = us_scheduler['alloc_id']
- self._create_tconts(us_scheduler)
+ self._create_tconts(uni_id, us_scheduler)
upstream_gem_port_attribute_list = tp['upstream_gem_port_attribute_list']
- self._create_gemports(upstream_gem_port_attribute_list, alloc_id, "UPSTREAM")
+ self._create_gemports(uni_id, upstream_gem_port_attribute_list, alloc_id, "UPSTREAM")
downstream_gem_port_attribute_list = tp['downstream_gem_port_attribute_list']
- self._create_gemports(downstream_gem_port_attribute_list, alloc_id, "DOWNSTREAM")
+ self._create_gemports(uni_id, downstream_gem_port_attribute_list, alloc_id, "DOWNSTREAM")
- def load_and_configure_tech_profile(self, tp_path):
+ def load_and_configure_tech_profile(self, uni_id, tp_path):
self.log.debug("loading-tech-profile-configuration")
- if tp_path not in self._tech_profile_download_done:
- self._tech_profile_download_done[tp_path] = False
- if not self._tech_profile_download_done[tp_path]:
+ if uni_id not in self._tp_service_specific_task:
+ self._tp_service_specific_task[uni_id] = dict()
+
+ if uni_id not in self._tech_profile_download_done:
+ self._tech_profile_download_done[uni_id] = dict()
+
+ if tp_path not in self._tech_profile_download_done[uni_id]:
+ self._tech_profile_download_done[uni_id][tp_path] = False
+
+ if not self._tech_profile_download_done[uni_id][tp_path]:
try:
- if tp_path in self._tp_service_specific_task:
+ if tp_path in self._tp_service_specific_task[uni_id]:
self.log.info("tech-profile-config-already-in-progress",
tp_path=tp_path)
return
@@ -408,16 +413,16 @@
tp = self.kv_client[tp_path]
tp = ast.literal_eval(tp)
self.log.debug("tp-instance", tp=tp)
- self._do_tech_profile_configuration(tp)
+ self._do_tech_profile_configuration(uni_id, tp)
def success(_results):
self.log.info("tech-profile-config-done-successfully")
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'tech-profile-config-download-success'
self.adapter_agent.update_device(device)
- if tp_path in self._tp_service_specific_task:
- del self._tp_service_specific_task[tp_path]
- self._tech_profile_download_done[tp_path] = True
+ if tp_path in self._tp_service_specific_task[uni_id]:
+ del self._tp_service_specific_task[uni_id][tp_path]
+ self._tech_profile_download_done[uni_id][tp_path] = True
def failure(_reason):
self.log.warn('tech-profile-config-failure-retrying',
@@ -425,16 +430,16 @@
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'tech-profile-config-download-failure-retrying'
self.adapter_agent.update_device(device)
- if tp_path in self._tp_service_specific_task:
- del self._tp_service_specific_task[tp_path]
+ if tp_path in self._tp_service_specific_task[uni_id]:
+ del self._tp_service_specific_task[uni_id][tp_path]
self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT, self.load_and_configure_tech_profile,
- tp_path)
+ uni_id, tp_path)
self.log.info('downloading-tech-profile-configuration')
- self._tp_service_specific_task[tp_path] = \
- BrcmTpServiceSpecificTask(self.omci_agent, self)
+ self._tp_service_specific_task[uni_id][tp_path] = \
+ BrcmTpServiceSpecificTask(self.omci_agent, self, uni_id)
self._deferred = \
- self._onu_omci_device.task_runner.queue_task(self._tp_service_specific_task[tp_path])
+ self._onu_omci_device.task_runner.queue_task(self._tp_service_specific_task[uni_id][tp_path])
self._deferred.addCallbacks(success, failure)
except Exception as e:
@@ -489,15 +494,18 @@
_in_port = fd.get_in_port(flow)
assert _in_port is not None
+ _out_port = fd.get_out_port(flow) # may be None
+
if is_downstream(_in_port):
- self.log.debug('downstream-flow')
+ self.log.debug('downstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_out_port)
elif is_upstream(_in_port):
- self.log.debug('upstream-flow')
+ self.log.debug('upstream-flow', in_port=_in_port, out_port=_out_port)
+ uni_port = self.uni_port(_in_port)
else:
raise Exception('port should be 1 or 2 by our convention')
- _out_port = fd.get_out_port(flow) # may be None
- self.log.debug('out-port', out_port=_out_port)
+ self.log.debug('flow-ports', in_port=_in_port, out_port=_out_port, uni_port=str(uni_port))
for field in fd.get_ofb_fields(flow):
if field.type == fd.ETH_TYPE:
@@ -596,13 +604,16 @@
elif _set_vlan_vid is None or _set_vlan_vid == 0:
self.log.warn('ignorning-flow-that-does-not-set-vlanid')
else:
- self._add_vlan_filter_task(device, _set_vlan_vid)
+ self.log.warn('set-vlanid', uni_id=uni_port.port_number, set_vlan_vid=_set_vlan_vid)
+ self._add_vlan_filter_task(device, uni_port, _set_vlan_vid)
except Exception as e:
self.log.exception('failed-to-install-flow', e=e, flow=flow)
- def _add_vlan_filter_task(self, device, _set_vlan_vid):
+ def _add_vlan_filter_task(self, device, uni_port, _set_vlan_vid):
+ assert uni_port is not None
+
def success(_results):
self.log.info('vlan-tagging-success', _results=_results)
device.reason = 'omci-flows-pushed'
@@ -612,10 +623,10 @@
self.log.warn('vlan-tagging-failure', _reason=_reason)
device.reason = 'omci-flows-failed-retrying'
self._vlan_filter_task = reactor.callLater(_STARTUP_RETRY_WAIT,
- self._add_vlan_filter_task, device, _set_vlan_vid)
+ self._add_vlan_filter_task, device, uni_port, _set_vlan_vid)
self.log.info('setting-vlan-tag')
- self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self.device_id, _set_vlan_vid)
+ self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self.device_id, uni_port, _set_vlan_vid)
self._deferred = self._onu_omci_device.task_runner.queue_task(self._vlan_filter_task)
self._deferred.addCallbacks(success, failure)
@@ -653,8 +664,8 @@
reactor.callLater(0, self._onu_omci_device.stop)
# Let TP download happen again
- self._tp_service_specific_task.clear()
- self._tech_profile_download_done.clear()
+ for i in self._tp_service_specific_task: i.clear()
+ for i in self._tech_profile_download_done: i.clear()
self.disable_ports(onu_device)
onu_device.reason = "stopping-openomci"
@@ -674,8 +685,8 @@
reactor.callLater(0, self._onu_omci_device.stop)
# Let TP download happen again
- self._tp_service_specific_task.clear()
- self._tech_profile_download_done.clear()
+ for i in self._tp_service_specific_task: i.clear()
+ for i in self._tech_profile_download_done: i.clear()
self.disable_ports(onu_device)
onu_device.reason = "stopping-openomci"
@@ -720,8 +731,8 @@
reactor.callLater(0, self._onu_omci_device.stop)
# Let TP download happen again
- self._tp_service_specific_task.clear()
- self._tech_profile_download_done.clear()
+ for i in self._tp_service_specific_task: i.clear()
+ for i in self._tech_profile_download_done: i.clear()
self.disable_ports(device)
device.oper_status = OperStatus.UNKNOWN
@@ -895,18 +906,30 @@
uni_value = config.uni_g_entities[entity_id]
self.log.debug("discovered-uni", entity_id=entity_id, value=uni_value)
- # TODO: can only support one UNI per ONU at this time. break out as soon as we have a good UNI
+ uni_entities = OrderedDict()
for entity_id in pptp_list:
pptp_value = config.pptp_entities[entity_id]
self.log.debug("discovered-pptp", entity_id=entity_id, value=pptp_value)
- self._add_uni_port(entity_id, uni_type=UniType.PPTP)
- break
+ uni_entities[entity_id] = UniType.PPTP
for entity_id in veip_list:
veip_value = config.veip_entities[entity_id]
self.log.debug("discovered-veip", entity_id=entity_id, value=veip_value)
- self._add_uni_port(entity_id, uni_type=UniType.VEIP)
- break
+ uni_entities[entity_id] = UniType.VEIP
+
+ uni_id = 0
+ for entity_id, uni_type in uni_entities.iteritems():
+ try:
+ self._add_uni_port(entity_id, uni_id, uni_type)
+ uni_id += 1
+ except AssertionError as e:
+ self.log.warn("could not add UNI", entity_id=entity_id, uni_type=uni_type, e=e)
+
+ multi_uni = len(self._unis) > 1
+ for uni_port in self._unis.itervalues():
+ uni_port.add_logical_port(uni_port.port_number, multi_uni)
+
+ self.adapter_agent.update_device(device)
self._qos_flexibility = config.qos_configuration_flexibility or 0
self._omcc_version = config.omcc_version or OMCCVersion.Unknown
@@ -957,7 +980,7 @@
self.log.info('device-info-not-loaded-skipping-mib-download')
- def _add_uni_port(self, entity_id, uni_type=UniType.PPTP):
+ def _add_uni_port(self, entity_id, uni_id, uni_type=UniType.PPTP):
self.log.debug('function-entry')
device = self.adapter_agent.get_device(self.device_id)
@@ -970,24 +993,21 @@
# TODO: This knowledge is locked away in openolt. and it assumes one onu equals one uni...
parent_device = self.adapter_agent.get_device(device.parent_id)
parent_adapter = parent_adapter_agent.adapter.devices[parent_device.id]
- uni_no_start = parent_adapter.platform.mk_uni_port_num(
- self._onu_indication.intf_id, self._onu_indication.onu_id)
+ uni_no = parent_adapter.platform.mk_uni_port_num(
+ self._onu_indication.intf_id, self._onu_indication.onu_id, uni_id)
# TODO: Some or parts of this likely need to move to UniPort. especially the format stuff
- working_port = self._next_port_number
- uni_no = uni_no_start + working_port
uni_name = "uni-{}".format(uni_no)
- mac_bridge_port_num = working_port + 1
+ mac_bridge_port_num = uni_id + 1 # TODO +1 is only to test non-zero index
- self.log.debug('uni-port-inputs', uni_no=uni_no, uni_name=uni_name, uni_type=uni_type,
+ self.log.debug('uni-port-inputs', uni_no=uni_no, uni_id=uni_id, uni_name=uni_name, uni_type=uni_type,
entity_id=entity_id, mac_bridge_port_num=mac_bridge_port_num)
- uni_port = UniPort.create(self, uni_name, uni_no, uni_name, uni_type)
+ uni_port = UniPort.create(self, uni_name, uni_id, uni_no, uni_name, uni_type)
uni_port.entity_id = entity_id
uni_port.enabled = True
uni_port.mac_bridge_port_num = mac_bridge_port_num
- uni_port.add_logical_port(uni_port.port_number)
self.log.debug("created-uni-port", uni=uni_port)
@@ -1000,14 +1020,19 @@
uni_ports=self._unis.values())
# TODO: this should be in the PonPortclass
pon_port = self._pon.get_port()
- self.adapter_agent.delete_port_reference_from_parent(self.device_id,
- pon_port)
- pon_port.peers.extend([Port.PeerPort(device_id=device.parent_id,
- port_no=uni_port.port_number)])
+ # Delete reference to my own UNI as peer from parent.
+ # TODO why is this here, add_port_reference_to_parent already prunes duplicates
+ me_as_peer = Port.PeerPort(device_id=device.parent_id, port_no=uni_port.port_number)
+ partial_pon_port = Port(port_no=pon_port.port_no, label=pon_port.label,
+ type=pon_port.type, admin_state=pon_port.admin_state,
+ oper_status=pon_port.oper_status,
+ peers=[me_as_peer]) # only list myself as a peer to avoid deleting all other UNIs from parent
+ self.adapter_agent.delete_port_reference_from_parent(self.device_id, partial_pon_port)
+
+ pon_port.peers.extend([me_as_peer])
self._pon._port = pon_port
self.adapter_agent.add_port_reference_to_parent(self.device_id,
- pon_port)
- self.adapter_agent.update_device(device)
+ pon_port)
\ No newline at end of file
diff --git a/voltha/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py b/voltha/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
index 14041a4..6dea69e 100644
--- a/voltha/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
+++ b/voltha/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
@@ -81,9 +81,6 @@
# Frame size
self._max_gem_payload = DEFAULT_GEM_PAYLOAD
- # TODO: only using a single UNI/ethernet port
- self._uni_port = self._handler.uni_ports[0]
-
self._pon = handler.pon_port
# Port numbers
@@ -188,22 +185,32 @@
device.reason = 'performing-initial-mib-download'
self._handler.adapter_agent.update_device(device)
- try:
- # Lock the UNI ports to prevent any alarms during initial configuration
- # of the ONU
- self.strobe_watchdog()
- yield self.enable_uni(self._uni_port, True)
+ try:
+ # Lock the UNI ports to prevent any alarms during initial configuration
+ # of the ONU
+ self.strobe_watchdog()
+
+ # Provision the initial bridge configuration
+ yield self.perform_initial_bridge_setup()
+
+ for uni_port in self._handler.uni_ports:
+ yield self.enable_uni(uni_port, True)
# Provision the initial bridge configuration
- yield self.perform_initial_bridge_setup()
+ yield self.perform_uni_initial_bridge_setup(uni_port)
# And re-enable the UNIs if needed
- yield self.enable_uni(self._uni_port, False)
+ yield self.enable_uni(uni_port, False)
self.deferred.callback('initial-download-success')
- except TimeoutError as e:
- self.deferred.errback(failure.Failure(e))
+ except TimeoutError as e:
+ self.log.error('initial-download-failure', e=e)
+ self.deferred.errback(failure.Failure(e))
+
+ except Exception as e:
+ self.log.exception('initial-download-failure', e=e)
+ self.deferred.errback(failure.Failure(e))
else:
e = MibResourcesFailure('Required resources are not available',
@@ -237,6 +244,22 @@
results = yield omci_cc.send(frame)
self.check_status_and_state(results, 'create-gal-ethernet-profile')
+ except TimeoutError as e:
+ self.log.warn('rx-timeout-0', e=e)
+ raise
+
+ except Exception as e:
+ self.log.exception('omci-setup-0', e=e)
+ raise
+
+ returnValue(None)
+
+ @inlineCallbacks
+ def perform_uni_initial_bridge_setup(self, uni_port):
+ self.log.debug('function-entry')
+ omci_cc = self._onu_device.omci_cc
+ frame = None
+ try:
################################################################################
# Common - PON and/or UNI #
################################################################################
@@ -258,7 +281,7 @@
'unknown_mac_address_discard': True
}
msg = MacBridgeServiceProfileFrame(
- self._mac_bridge_service_profile_entity_id,
+ self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num,
attributes
)
frame = msg.create()
@@ -277,7 +300,7 @@
# - Nothing at this point. When a GEM port is created, this entity will
# be updated to reference the GEM Interworking TP
- msg = Ieee8021pMapperServiceProfileFrame(self._ieee_mapper_service_profile_entity_id)
+ msg = Ieee8021pMapperServiceProfileFrame(self._ieee_mapper_service_profile_entity_id + uni_port.mac_bridge_port_num)
frame = msg.create()
self.log.debug('openomci-msg', omci_msg=msg)
results = yield omci_cc.send(frame)
@@ -300,11 +323,11 @@
# TODO: magic. make a static variable for tp_type
msg = MacBridgePortConfigurationDataFrame(
- self._mac_bridge_port_ani_entity_id,
- bridge_id_pointer=self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
- port_num=self._pon_port_num, # Port ID ##TODO associated with what?
- tp_type=3, # TP Type (IEEE 802.1p mapper service)
- tp_pointer=self._ieee_mapper_service_profile_entity_id # TP ID, 8021p mapper ID
+ self._mac_bridge_port_ani_entity_id + uni_port.mac_bridge_port_num,
+ bridge_id_pointer=self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
+ port_num= 0xff, # Port ID - unique number within the bridge
+ tp_type=3, # TP Type (IEEE 802.1p mapper service)
+ tp_pointer=self._ieee_mapper_service_profile_entity_id + uni_port.mac_bridge_port_num # TP ID, 8021p mapper ID
)
frame = msg.create()
self.log.debug('openomci-msg', omci_msg=msg)
@@ -323,8 +346,8 @@
# TODO: magic. make a static variable for forward_op
msg = VlanTaggingFilterDataFrame(
- self._mac_bridge_port_ani_entity_id, # Entity ID
- vlan_tcis=[self._vlan_tcis_1], # VLAN IDs
+ self._mac_bridge_port_ani_entity_id + uni_port.mac_bridge_port_num, # Entity ID
+ vlan_tcis=[self._vlan_tcis_1], # VLAN IDs
forward_operation=0x10
)
frame = msg.create()
@@ -348,19 +371,20 @@
# TODO: magic. make a static variable for tp_type
# default to PPTP
- if self._uni_port.type is UniType.VEIP:
+ tp_type = None
+ if uni_port.type is UniType.VEIP:
tp_type = 11
- elif self._uni_port.type is UniType.PPTP:
+ elif uni_port.type is UniType.PPTP:
tp_type = 1
else:
tp_type = 1
msg = MacBridgePortConfigurationDataFrame(
- self._uni_port.entity_id, # Entity ID - This is read-only/set-by-create !!!
- bridge_id_pointer=self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
- port_num=self._uni_port.mac_bridge_port_num, # Port ID
- tp_type=tp_type, # PPTP Ethernet or VEIP UNI
- tp_pointer=self._uni_port.entity_id # Ethernet UNI ID
+ uni_port.entity_id, # Entity ID - This is read-only/set-by-create !!!
+ bridge_id_pointer=self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
+ port_num=uni_port.mac_bridge_port_num, # Port ID
+ tp_type=tp_type, # PPTP Ethernet or VEIP UNI
+ tp_pointer=uni_port.entity_id # Ethernet UNI ID
)
frame = msg.create()
self.log.debug('openomci-msg', omci_msg=msg)
@@ -378,216 +402,6 @@
returnValue(None)
@inlineCallbacks
- def perform_service_specific_steps(self):
- self.log.debug('function-entry')
-
- omci_cc = self._onu_device.omci_cc
- frame = None
-
- try:
- ################################################################################
- # TCONTS
- #
- # EntityID will be referenced by:
- # - GemPortNetworkCtp
- # References:
- # - ONU created TCONT (created on ONU startup)
-
- tcont_idents = self._onu_device.query_mib(Tcont.class_id)
- self.log.debug('tcont-idents', tcont_idents=tcont_idents)
-
- for tcont in self._handler.pon_port.tconts.itervalues():
- free_entity_id = None
- for k, v in tcont_idents.items():
- alloc_check = v.get('attributes', {}).get('alloc_id', 0)
- # Some onu report both to indicate an available tcont
- if alloc_check == 0xFF or alloc_check == 0xFFFF:
- free_entity_id = k
- break
- else:
- free_entity_id = None
-
- self.log.debug('tcont-loop', free_entity_id=free_entity_id)
-
- if free_entity_id is None:
- self.log.error('no-available-tconts')
- break
-
- # TODO: Need to restore on failure. Need to check status/results
- yield tcont.add_to_hardware(omci_cc, free_entity_id)
-
- ################################################################################
- # GEMS (GemPortNetworkCtp and GemInterworkingTp)
- #
- # For both of these MEs, the entity_id is the GEM Port ID. The entity id of the
- # GemInterworkingTp ME could be different since it has an attribute to specify
- # the GemPortNetworkCtp entity id.
- #
- # for the GemPortNetworkCtp ME
- #
- # GemPortNetworkCtp
- # EntityID will be referenced by:
- # - GemInterworkingTp
- # References:
- # - TCONT
- # - Hardcoded upstream TM Entity ID
- # - (Possibly in Future) Upstream Traffic descriptor profile pointer
- #
- # GemInterworkingTp
- # EntityID will be referenced by:
- # - Ieee8021pMapperServiceProfile
- # References:
- # - GemPortNetworkCtp
- # - Ieee8021pMapperServiceProfile
- # - GalEthernetProfile
- #
-
- for gem_port in self._handler.pon_port.gem_ports.itervalues():
- tcont = gem_port.tcont
- if tcont is None:
- self.log.error('unknown-tcont-reference', gem_id=gem_port.gem_id)
- continue
-
- # TODO: Need to restore on failure. Need to check status/results
- yield gem_port.add_to_hardware(omci_cc,
- tcont.entity_id,
- self._ieee_mapper_service_profile_entity_id,
- self._gal_enet_profile_entity_id)
-
- ################################################################################
- # Update the IEEE 802.1p Mapper Service Profile config
- #
- # EntityID was created prior to this call. This is a set
- #
- # References:
- # - Gem Interwork TPs are set here
- #
- # TODO: All p-bits currently go to the one and only GEMPORT ID for now
- gem_ports = self._handler.pon_port.gem_ports
- gem_entity_ids = [gem_port.entity_id for _, gem_port in gem_ports.items()] \
- if len(gem_ports) else [OmciNullPointer]
-
- msg = Ieee8021pMapperServiceProfileFrame(
- self._ieee_mapper_service_profile_entity_id, # 802.1p mapper Service Mapper Profile ID
- interwork_tp_pointers=gem_entity_ids # Interworking TP IDs
- )
- frame = msg.set()
- self.log.debug('openomci-msg', omci_msg=msg)
- results = yield omci_cc.send(frame)
- self.check_status_and_state(results, 'set-8021p-mapper-service-profile')
-
- ################################################################################
- # Create Extended VLAN Tagging Operation config (PON-side)
- #
- # EntityID relates to the VLAN TCIS
- # References:
- # - VLAN TCIS from previously created VLAN Tagging filter data
- # - PPTP Ethernet or VEIP UNI
- #
-
- # TODO: do this for all uni/ports...
- # TODO: magic. static variable for assoc_type
-
- # default to PPTP
- if self._uni_port.type is UniType.VEIP:
- association_type = 10
- elif self._uni_port.type is UniType.PPTP:
- association_type = 2
- else:
- association_type = 2
-
- attributes = dict(
- association_type=association_type, # Assoc Type, PPTP/VEIP Ethernet UNI
- associated_me_pointer=self._uni_port.entity_id, # Assoc ME, PPTP/VEIP Entity Id
-
- # See VOL-1311 - Need to set table during create to avoid exception
- # trying to read back table during post-create-read-missing-attributes
- # But, because this is a R/W attribute. Some ONU may not accept the
- # value during create. It is repeated again in a set below.
- input_tpid=self._input_tpid, # input TPID
- output_tpid=self._output_tpid, # output TPID
- )
-
- msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
- attributes=attributes
- )
-
- frame = msg.create()
- self.log.debug('openomci-msg', omci_msg=msg)
- results = yield omci_cc.send(frame)
- self.check_status_and_state(results, 'create-extended-vlan-tagging-operation-configuration-data')
-
- attributes = dict(
- # Specifies the TPIDs in use and that operations in the downstream direction are
- # inverse to the operations in the upstream direction
- input_tpid=self._input_tpid, # input TPID
- output_tpid=self._output_tpid, # output TPID
- downstream_mode=0, # inverse of upstream
- )
-
- msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
- attributes=attributes
- )
-
- frame = msg.set()
- self.log.debug('openomci-msg', msg=msg)
- results = yield omci_cc.send(frame)
- self.check_status_and_state(results, 'set-extended-vlan-tagging-operation-configuration-data')
-
- attributes = dict(
- # parameters: Entity Id ( 0x900), Filter Inner Vlan Id(0x1000-4096,do not filter on Inner vid,
- # Treatment Inner Vlan Id : 2
-
- # Update uni side extended vlan filter
- # filter for untagged
- # probably for eapol
- # TODO: lots of magic
- # TODO: magic 0x1000 / 4096?
- received_frame_vlan_tagging_operation_table=
- VlanTaggingOperation(
- filter_outer_priority=15, # This entry is not a double-tag rule
- filter_outer_vid=4096, # Do not filter on the outer VID value
- filter_outer_tpid_de=0, # Do not filter on the outer TPID field
-
- filter_inner_priority=15,
- filter_inner_vid=4096,
- filter_inner_tpid_de=0,
- filter_ether_type=0,
-
- treatment_tags_to_remove=0,
- treatment_outer_priority=15,
- treatment_outer_vid=0,
- treatment_outer_tpid_de=0,
-
- treatment_inner_priority=0,
- treatment_inner_vid=self._cvid,
- treatment_inner_tpid_de=4,
- )
- )
-
- msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
- attributes=attributes
- )
-
- frame = msg.set()
- self.log.debug('openomci-msg', omci_msg=msg)
- results = yield omci_cc.send(frame)
- self.check_status_and_state(results, 'set-extended-vlan-tagging-operation-configuration-data-table')
-
- except TimeoutError as e:
- self.log.warn('rx-timeout-2', e=e)
- raise
-
- except Exception as e:
- self.log.exception('omci-setup-2', e=e)
- raise
-
- returnValue(None)
-
- @inlineCallbacks
def enable_uni(self, uni_port, force_lock):
"""
Lock or unlock a single uni port
diff --git a/voltha/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py b/voltha/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
index 26f7c66..89d39e3 100644
--- a/voltha/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
+++ b/voltha/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
@@ -48,7 +48,7 @@
name = "Broadcom Tech-Profile Download Task"
- def __init__(self, omci_agent, handler):
+ def __init__(self, omci_agent, handler, uni_id):
"""
Class initialization
@@ -71,7 +71,7 @@
self._max_gem_payload = DEFAULT_GEM_PAYLOAD
# TODO: only using a single UNI/ethernet port
- self._uni_port = self._handler.uni_ports[0]
+ self._uni_port = self._handler.uni_ports[uni_id]
self._uni_port_num = self._uni_port.mac_bridge_port_num
self._ethernet_uni_entity_id = self._uni_port.entity_id
@@ -179,6 +179,7 @@
self.log.debug('tcont-idents', tcont_idents=tcont_idents)
for tcont in self._handler.pon_port.tconts.itervalues():
+ if tcont.uni_id is not None and tcont.uni_id != self._uni_port.uni_id: continue
free_entity_id = None
for k, v in tcont_idents.items():
alloc_check = v.get('attributes', {}).get('alloc_id', 0)
@@ -189,7 +190,7 @@
else:
free_entity_id = None
- self.log.debug('tcont-loop', free_entity_id=free_entity_id)
+ self.log.debug('tcont-loop', free_entity_id=free_entity_id, alloc_id=tcont.alloc_id)
if free_entity_id is None:
self.log.error('no-available-tconts')
@@ -258,19 +259,22 @@
self.tcont_me_to_queue_map[tcont_me].append(k)
else:
uni_port = (related_port & 0xffff0000) >> 16
- if uni_port not in self.uni_port_to_queue_map:
- self.log.debug("prior-q-related-port-and-uni-port-me",
- related_port=related_port,
- uni_port_me=uni_port)
- self.uni_port_to_queue_map[uni_port] = list()
+ if uni_port == self._uni_port.entity_id:
+ if uni_port not in self.uni_port_to_queue_map:
+ self.log.debug("prior-q-related-port-and-uni-port-me",
+ related_port=related_port,
+ uni_port_me=uni_port)
+ self.uni_port_to_queue_map[uni_port] = list()
- self.uni_port_to_queue_map[uni_port].append(k)
+ self.uni_port_to_queue_map[uni_port].append(k)
self.log.debug("ul-prior-q", ul_prior_q=self.tcont_me_to_queue_map)
self.log.debug("dl-prior-q", dl_prior_q=self.uni_port_to_queue_map)
for gem_port in self._handler.pon_port.gem_ports.itervalues():
+ if gem_port.uni_id is not None and gem_port.uni_id != self._uni_port.uni_id: continue
+
# TODO: Traffic descriptor will be available after meter bands are available
tcont = gem_port.tcont
if tcont is None:
@@ -309,7 +313,8 @@
# TODO: Need to restore on failure. Need to check status/results
results = yield gem_port.add_to_hardware(omci_cc,
tcont.entity_id,
- self._ieee_mapper_service_profile_entity_id,
+ self._ieee_mapper_service_profile_entity_id +
+ self._uni_port.mac_bridge_port_num,
self._gal_enet_profile_entity_id,
ul_prior_q_entity_id, dl_prior_q_entity_id)
self.check_status_and_state(results, 'create-gem-port')
@@ -329,6 +334,8 @@
gem_entity_ids = [OmciNullPointer] * 8
for gem_port in self._handler.pon_port.gem_ports.itervalues():
+ if gem_port.uni_id is not None and gem_port.uni_id != self._uni_port.uni_id: continue
+
if gem_port.direction == "upstream" or \
gem_port.direction == "bi-directional":
for i, p in enumerate(gem_port.pbit_map):
@@ -340,7 +347,7 @@
pass
msg = Ieee8021pMapperServiceProfileFrame(
- self._ieee_mapper_service_profile_entity_id, # 802.1p mapper Service Mapper Profile ID
+ self._ieee_mapper_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # 802.1p mapper Service Mapper Profile ID
interwork_tp_pointers=gem_entity_ids # Interworking TP IDs
)
frame = msg.set()
@@ -381,7 +388,7 @@
)
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
+ self._mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
attributes=attributes
)
@@ -399,7 +406,7 @@
)
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
+ self._mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
attributes=attributes
)
@@ -440,7 +447,7 @@
)
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- self._mac_bridge_service_profile_entity_id, # Bridge Entity ID
+ self._mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
attributes=attributes
)
diff --git a/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py b/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
index cf2e112..5413a8f 100644
--- a/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
+++ b/voltha/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
@@ -34,7 +34,7 @@
task_priority = 200
name = "Broadcom VLAN Filter Task"
- def __init__(self, omci_agent, device_id, set_vlan_id, priority=task_priority):
+ def __init__(self, omci_agent, device_id, uni_port, set_vlan_id, priority=task_priority):
"""
Class initialization
@@ -43,12 +43,16 @@
:param set_vlan_id: (int) VLAN to filter for and set
:param priority: (int) OpenOMCI Task priority (0..255) 255 is the highest
"""
+
+ self.log = structlog.get_logger(device_id=device_id, uni_port=uni_port.port_number)
+
super(BrcmVlanFilterTask, self).__init__(BrcmVlanFilterTask.name,
omci_agent,
device_id,
priority=priority,
exclusive=False)
self._device = omci_agent.get_device(device_id)
+ self._uni_port = uni_port
self._set_vlan_id = set_vlan_id
self._results = None
self._local_deferred = None
@@ -84,7 +88,7 @@
_mac_bridge_service_profile_entity_id = 0x201
_mac_bridge_port_ani_entity_id = 0x2102 # TODO: can we just use the entity id from the anis list?
# Delete bridge ani side vlan filter
- msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id)
+ msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num)
frame = msg.delete()
self.log.debug('openomci-msg', msg=msg)
self.strobe_watchdog()
@@ -93,7 +97,7 @@
# Re-Create bridge ani side vlan filter
msg = VlanTaggingFilterDataFrame(
- _mac_bridge_port_ani_entity_id, # Entity ID
+ _mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num, # Entity ID
vlan_tcis=[self._set_vlan_id], # VLAN IDs
forward_operation=0x10
)
@@ -132,7 +136,7 @@
)
)
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- _mac_bridge_service_profile_entity_id, # Bridge Entity ID
+ _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
attributes=attributes # See above
)
frame = msg.set()
@@ -168,7 +172,7 @@
)
)
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
- _mac_bridge_service_profile_entity_id, # Bridge Entity ID
+ _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
attributes=attributes # See above
)
frame = msg.set()
diff --git a/voltha/adapters/brcm_openomci_onu/onu_gem_port.py b/voltha/adapters/brcm_openomci_onu/onu_gem_port.py
index 571de78..b5e8f60 100644
--- a/voltha/adapters/brcm_openomci_onu/onu_gem_port.py
+++ b/voltha/adapters/brcm_openomci_onu/onu_gem_port.py
@@ -26,7 +26,7 @@
Broadcom ONU specific implementation
"""
- def __init__(self, gem_id, alloc_id, entity_id,
+ def __init__(self, gem_id, uni_id, alloc_id, entity_id,
direction="BIDIRECTIONAL",
encryption=False,
discard_config=None,
@@ -45,11 +45,12 @@
name=None,
handler=None):
- self.log = structlog.get_logger(device_id=handler.device_id, gem_id=gem_id)
+ self.log = structlog.get_logger(device_id=handler.device_id, uni_id=uni_id, gem_id=gem_id)
self.log.debug('function-entry')
self.name = name
self.gem_id = gem_id
+ self.uni_id = uni_id
self._alloc_id = alloc_id
self.tcont_ref = tcont_ref
self.intf_ref = intf_ref
@@ -255,6 +256,7 @@
log.debug('function-entry', gem_port=gem_port, entity_id=entity_id)
return OnuGemPort(gem_id=gem_port['gemport_id'],
+ uni_id=gem_port['uni_id'],
alloc_id=gem_port['alloc_id_ref'],
entity_id=entity_id,
direction=gem_port['direction'],
diff --git a/voltha/adapters/brcm_openomci_onu/onu_tcont.py b/voltha/adapters/brcm_openomci_onu/onu_tcont.py
index 91c3b36..1e22bdb 100644
--- a/voltha/adapters/brcm_openomci_onu/onu_tcont.py
+++ b/voltha/adapters/brcm_openomci_onu/onu_tcont.py
@@ -26,11 +26,12 @@
"""
Broadcom ONU specific implementation
"""
- def __init__(self, handler, alloc_id, q_sched_policy, traffic_descriptor):
+ def __init__(self, handler, uni_id, alloc_id, q_sched_policy, traffic_descriptor):
- self.log = structlog.get_logger(device_id=handler.device_id, alloc_id=alloc_id)
+ self.log = structlog.get_logger(device_id=handler.device_id, uni_id=uni_id, alloc_id=alloc_id)
self.log.debug('function-entry')
+ self.uni_id = uni_id
self.alloc_id = alloc_id
self._q_sched_policy = 0
self.q_sched_policy = q_sched_policy
@@ -64,6 +65,7 @@
log.debug('function-entry', tcont=tcont)
return OnuTCont(handler,
+ tcont['uni_id'],
tcont['alloc-id'],
tcont['q_sched_policy'],
td
diff --git a/voltha/adapters/brcm_openomci_onu/pon_port.py b/voltha/adapters/brcm_openomci_onu/pon_port.py
index 7fb6a9e..a5ee55d 100644
--- a/voltha/adapters/brcm_openomci_onu/pon_port.py
+++ b/voltha/adapters/brcm_openomci_onu/pon_port.py
@@ -149,12 +149,13 @@
"""
self.log.debug('function-entry')
- self._port = Port(port_no=self.port_number,
- label='PON port',
- type=Port.PON_ONU,
- admin_state=self._admin_state,
- oper_status=self._oper_status,
- peers=[])
+ if self._port is None:
+ self._port = Port(port_no=self.port_number,
+ label='PON port',
+ type=Port.PON_ONU,
+ admin_state=self._admin_state,
+ oper_status=self._oper_status,
+ peers=[])
return self._port
def _update_adapter_agent(self):
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)
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index 1afac68..0858005 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -213,12 +213,11 @@
device_info = self.stub.GetDeviceInfo(openolt_pb2.Empty())
self.log.info('Device connected', device_info=device_info)
- self.platform = self.platform_class(self.log, device_info)
self.resource_mgr = self.resource_mgr_class(self.device_id,
self.host_and_port,
self.extra_args,
device_info)
-
+ self.platform = self.platform_class(self.log, self.resource_mgr)
self.flow_mgr = self.flow_mgr_class(self.adapter_agent, self.log,
self.stub, self.device_id,
self.logical_device_id,
@@ -261,16 +260,12 @@
# Children ports
child_devices = self.adapter_agent.get_child_devices(self.device_id)
for onu_device in child_devices:
- uni_no = self.platform.mk_uni_port_num(
- onu_device.proxy_address.channel_id,
- onu_device.proxy_address.onu_id)
- uni_name = self.port_name(uni_no, Port.ETHERNET_UNI,
- serial_number=onu_device.serial_number)
onu_adapter_agent = \
registry('adapter_loader').get_agent(onu_device.adapter)
onu_adapter_agent.update_interface(onu_device,
{'oper_state': 'down'})
- self.onu_ports_down(onu_device, uni_no, uni_name, oper_state)
+ self.onu_ports_down(onu_device, oper_state)
+
# Children devices
self.adapter_agent.update_child_devices_state(
self.device_id, oper_status=oper_state,
@@ -521,13 +516,6 @@
expected_onu_id=onu_device.proxy_address.onu_id,
received_onu_id=onu_indication.onu_id)
- uni_no = self.platform.mk_uni_port_num(onu_indication.intf_id,
- onu_indication.onu_id)
- uni_name = self.port_name(uni_no, Port.ETHERNET_UNI,
- serial_number=onu_device.serial_number)
-
- self.log.debug('port-number-ready', uni_no=uni_no, uni_name=uni_name)
-
# Admin state
if onu_indication.admin_state == 'down':
if onu_indication.oper_state != 'down':
@@ -568,8 +556,7 @@
onu_device.oper_status = OperStatus.DISCOVERED
self.adapter_agent.update_device(onu_device)
# Set port oper state to Discovered
- self.onu_ports_down(onu_device, uni_no, uni_name,
- OperStatus.DISCOVERED)
+ self.onu_ports_down(onu_device, OperStatus.DISCOVERED)
onu_adapter_agent.update_interface(onu_device,
{'oper_state': 'down'})
@@ -598,42 +585,37 @@
self.log.warn('Not-implemented-or-invalid-value-of-oper-state',
oper_state=onu_indication.oper_state)
- def onu_ports_down(self, onu_device, uni_no, uni_name, oper_state):
+ def onu_ports_down(self, onu_device, oper_state):
# Set port oper state to Discovered
# add port will update port if it exists
- self.adapter_agent.add_port(
- self.device_id,
- Port(
- port_no=uni_no,
- label=uni_name,
- type=Port.ETHERNET_UNI,
- admin_state=onu_device.admin_state,
- oper_status=oper_state))
+ # self.adapter_agent.add_port(
+ # self.device_id,
+ # Port(
+ # port_no=uni_no,
+ # label=uni_name,
+ # type=Port.ETHERNET_UNI,
+ # admin_state=onu_device.admin_state,
+ # oper_status=oper_state))
+ # TODO this should be downning ports in onu adatper
# Disable logical port
onu_ports = self.proxy.get('devices/{}/ports'.format(onu_device.id))
- onu_port_id = None
for onu_port in onu_ports:
- if onu_port.port_no == uni_no:
- onu_port_id = onu_port.label
- if onu_port_id is None:
- self.log.error('matching-onu-port-label-not-found',
- onu_id=onu_device.id, olt_id=self.device_id,
- onu_ports=onu_ports)
- return
- try:
- onu_logical_port = self.adapter_agent.get_logical_port(
- logical_device_id=self.logical_device_id, port_id=onu_port_id)
- onu_logical_port.ofp_port.state = OFPPS_LINK_DOWN
- self.adapter_agent.update_logical_port(
- logical_device_id=self.logical_device_id,
- port=onu_logical_port)
- self.log.debug('cascading-oper-state-to-port-and-logical-port')
- except KeyError as e:
- self.log.error('matching-onu-port-label-invalid',
- onu_id=onu_device.id, olt_id=self.device_id,
- onu_ports=onu_ports, onu_port_id=onu_port_id,
- error=e)
+ self.log.debug('onu-ports-down', onu_port=onu_port)
+ onu_port_id = onu_port.label
+ try:
+ onu_logical_port = self.adapter_agent.get_logical_port(
+ logical_device_id=self.logical_device_id, port_id=onu_port_id)
+ onu_logical_port.ofp_port.state = OFPPS_LINK_DOWN
+ self.adapter_agent.update_logical_port(
+ logical_device_id=self.logical_device_id,
+ port=onu_logical_port)
+ self.log.debug('cascading-oper-state-to-port-and-logical-port')
+ except KeyError as e:
+ self.log.error('matching-onu-port-label-invalid',
+ onu_id=onu_device.id, olt_id=self.device_id,
+ onu_ports=onu_ports, onu_port_id=onu_port_id,
+ error=e)
def omci_indication(self, omci_indication):
@@ -653,22 +635,32 @@
self.log.debug("packet indication",
intf_type=pkt_indication.intf_type,
intf_id=pkt_indication.intf_id,
+ port_no=pkt_indication.port_no,
+ cookie=pkt_indication.cookie,
gemport_id=pkt_indication.gemport_id,
flow_id=pkt_indication.flow_id)
if pkt_indication.intf_type == "pon":
- pon_intf_gemport = (pkt_indication.intf_id, pkt_indication.gemport_id)
- try:
- onu_id = int(self.resource_mgr.kv_store[pon_intf_gemport])
- if onu_id is None:
- raise Exception("onu-id-none")
- except Exception as e:
- self.log.error("no-onu-reference-for-gem",
- gemport_id=pkt_indication.gemport_id, e=e)
- return
+ if pkt_indication.port_no:
+ logical_port_num = pkt_indication.port_no
+ else: # TODO Remove this else block after openolt device has been fully rolled out with cookie protobuf change
+ try:
+ onu_id_uni_id = self.resource_mgr.get_onu_uni_from_ponport_gemport(pkt_indication.intf_id,
+ pkt_indication.gemport_id)
+ onu_id = int(onu_id_uni_id[0])
+ uni_id = int(onu_id_uni_id[1])
+ self.log.debug("packet indication-kv", onu_id=onu_id, uni_id=uni_id)
+ if onu_id is None:
+ raise Exception("onu-id-none")
+ if uni_id is None:
+ raise Exception("uni-id-none")
+ logical_port_num = self.platform.mk_uni_port_num(pkt_indication.intf_id, onu_id, uni_id)
+ except Exception as e:
+ self.log.error("no-onu-reference-for-gem",
+ gemport_id=pkt_indication.gemport_id, e=e)
+ return
- logical_port_num = self.platform.mk_uni_port_num(pkt_indication.intf_id,
- onu_id)
+
elif pkt_indication.intf_type == "nni":
logical_port_num = self.platform.intf_id_to_port_no(
pkt_indication.intf_id,
@@ -693,7 +685,7 @@
packet=str(pkt).encode("HEX"))
# Find port type
- egress_port_type = self.port_type(egress_port)
+ egress_port_type = self.platform.intf_id_to_port_type_name(egress_port)
if egress_port_type == Port.ETHERNET_UNI:
if pkt.haslayer(Dot1Q):
@@ -715,11 +707,14 @@
'sending-packet-to-ONU', egress_port=egress_port,
intf_id=self.platform.intf_id_from_uni_port_num(egress_port),
onu_id=self.platform.onu_id_from_port_num(egress_port),
+ uni_id=self.platform.uni_id_from_port_num(egress_port),
+ port_no=egress_port,
packet=str(payload).encode("HEX"))
onu_pkt = openolt_pb2.OnuPacket(
intf_id=self.platform.intf_id_from_uni_port_num(egress_port),
onu_id=self.platform.onu_id_from_port_num(egress_port),
+ port_no=egress_port,
pkt=send_pkt)
self.stub.OnuPacketOut(onu_pkt)
@@ -774,7 +769,8 @@
parent_device_id=self.device_id, parent_port_no=port_no,
vendor_id=serial_number.vendor_id, proxy_address=proxy_address,
root=True, serial_number=serial_number_str,
- admin_state=AdminState.ENABLED)
+ admin_state=AdminState.ENABLED#, **{'vlan':4091} # magic still maps to brcm_openomci_onu.pon_port.BRDCM_DEFAULT_VLAN
+ )
def port_name(self, port_no, port_type, intf_id=None, serial_number=None):
if port_type is Port.ETHERNET_NNI:
@@ -782,17 +778,7 @@
elif port_type is Port.PON_OLT:
return "pon" + str(intf_id)
elif port_type is Port.ETHERNET_UNI:
- if serial_number is not None:
- return serial_number
- else:
- return "uni-{}".format(port_no)
-
- def port_type(self, port_no):
- ports = self.adapter_agent.get_ports(self.device_id)
- for port in ports:
- if port.port_no == port_no:
- return port.type
- return None
+ assert False, 'local UNI management not supported'
def add_logical_port(self, port_no, intf_id, oper_state):
self.log.info('adding-logical-port', port_no=port_no)
@@ -1018,8 +1004,12 @@
self.log.error('port delete error', error=e)
serial_number = self.destringify_serial_number(
child_device.serial_number)
+ # TODO FIXME - For each uni.
+ # TODO FIXME - Flows are not deleted
+ uni_id = 0 # FIXME
pon_intf_id_onu_id = (child_device.proxy_address.channel_id,
- child_device.proxy_address.onu_id)
+ child_device.proxy_address.onu_id,
+ uni_id)
alloc_id = self.resource_mgr.get_alloc_id(pon_intf_id_onu_id)
# Free any PON resources that were reserved for the ONU
self.resource_mgr.free_pon_resources_for_onu(pon_intf_id_onu_id)
diff --git a/voltha/adapters/openolt/openolt_flow_mgr.py b/voltha/adapters/openolt/openolt_flow_mgr.py
index 8669d32..1b996e7 100644
--- a/voltha/adapters/openolt/openolt_flow_mgr.py
+++ b/voltha/adapters/openolt/openolt_flow_mgr.py
@@ -194,10 +194,11 @@
if field.type == fd.VLAN_VID:
classifier_info[METADATA] = field.vlan_vid & 0xfff
- (intf_id, onu_id) = self.platform.extract_access_from_flow(
+ self.log.debug('flow-ports', classifier_inport=classifier_info[IN_PORT], action_output=action_info[OUTPUT])
+ (port_no, intf_id, onu_id, uni_id) = self.platform.extract_access_from_flow(
classifier_info[IN_PORT], action_info[OUTPUT])
- self.divide_and_add_flow(intf_id, onu_id, classifier_info,
+ self.divide_and_add_flow(intf_id, onu_id, uni_id, port_no, classifier_info,
action_info, flow)
def _is_uni_port(self, port_no):
@@ -251,14 +252,14 @@
child_device = self.adapter_agent.get_device(child_device_id)
pon_intf = child_device.proxy_address.channel_id
onu_id = child_device.proxy_address.onu_id
- flows = self.resource_mgr.get_flow_id_info(pon_intf, onu_id, flow_id)
+ uni_id = self.platform.uni_id_from_port_num(uni_port_no) if uni_port_no is not None else None
+ flows = self.resource_mgr.get_flow_id_info(pon_intf, onu_id, uni_id, flow_id)
assert (isinstance(flows, list))
self.log.debug("retrieved-flows", flows=flows)
for idx in range(len(flows)):
if flow_direction == flows[idx]['flow_type']:
flows.pop(idx)
- self.update_flow_info_to_kv_store(pon_intf, onu_id,
- flow_id, flows)
+ self.update_flow_info_to_kv_store(pon_intf, onu_id, uni_id, flow_id, flows)
if len(flows) > 0:
# There are still flows referencing the same flow_id.
# So the flow should not be freed yet.
@@ -266,7 +267,7 @@
# between DS and US.
return
- self.resource_mgr.free_flow_id(pon_intf, onu_id, flow_id)
+ self.resource_mgr.free_flow_id_for_uni(pon_intf, onu_id, uni_id, flow_id)
else:
self.log.error("invalid-info", uni_port_no=uni_port_no,
flow_category=flow_category,
@@ -318,28 +319,27 @@
self.log.debug('no device flow to remove for this flow (normal '
'for multi table flows)', flow=flow)
- def _get_ofp_port_name(self, intf_id, onu_id):
+ def _get_ofp_port_name(self, intf_id, onu_id, uni_id):
parent_port_no = self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT)
child_device = self.adapter_agent.get_child_device(self.device_id,
parent_port_no=parent_port_no, onu_id=onu_id)
if child_device is None:
self.log.error("could-not-find-child-device",
parent_port_no=intf_id, onu_id=onu_id)
- return None
- # FIXME: Assumes single UNI for a ONU device which is visible at ONOS
+ return (None, None)
ports = self.adapter_agent.get_ports(child_device.id, Port.ETHERNET_UNI)
logical_port = self.adapter_agent.get_logical_port(
- self.logical_device_id, ports[0].label)
- ofp_port_name = logical_port.ofp_port.name
+ self.logical_device_id, ports[uni_id].label)
+ ofp_port_name = (logical_port.ofp_port.name, logical_port.ofp_port.port_no)
return ofp_port_name
- def divide_and_add_flow(self, intf_id, onu_id, classifier,
+ def divide_and_add_flow(self, intf_id, onu_id, uni_id, port_no, classifier,
action, flow):
- self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id,
+ self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, port_no=port_no,
classifier=classifier, action=action)
- alloc_id, gem_ports = self.create_tcont_gemport(intf_id, onu_id,
+ alloc_id, gem_ports = self.create_tcont_gemport(intf_id, onu_id, uni_id,
flow.table_id)
if alloc_id is None or gem_ports is None:
self.log.error("alloc-id-gem-ports-unavailable", alloc_id=alloc_id,
@@ -355,7 +355,7 @@
if IP_PROTO in classifier:
if classifier[IP_PROTO] == 17:
self.log.debug('dhcp flow add')
- self.add_dhcp_trap(intf_id, onu_id, classifier,
+ self.add_dhcp_trap(intf_id, onu_id, uni_id, port_no, classifier,
action, flow, alloc_id, gemport_id)
elif classifier[IP_PROTO] == 2:
self.log.warn('igmp flow add ignored, not implemented yet')
@@ -366,19 +366,19 @@
elif ETH_TYPE in classifier:
if classifier[ETH_TYPE] == EAP_ETH_TYPE:
self.log.debug('eapol flow add')
- self.add_eapol_flow(intf_id, onu_id, flow, alloc_id,
+ self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, flow, alloc_id,
gemport_id)
vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow))
if vlan_id is not None:
self.add_eapol_flow(
- intf_id, onu_id, flow, alloc_id, gemport_id,
+ intf_id, onu_id, uni_id, port_no, flow, alloc_id, gemport_id,
eapol_flow_category=EAPOL_SECONDARY_FLOW,
vlan_id=vlan_id)
parent_port_no = self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT)
onu_device = self.adapter_agent.get_child_device(self.device_id,
onu_id=onu_id,
parent_port_no=parent_port_no)
- ofp_port_name = self._get_ofp_port_name(intf_id, onu_id)
+ (ofp_port_name, ofp_port_no) = self._get_ofp_port_name(intf_id, onu_id, uni_id)
if ofp_port_name is None:
self.log.error("port-name-not-found")
return
@@ -394,7 +394,7 @@
self.log.debug('Load-tech-profile-request-to-brcm-handler',
tp_path=tp_path)
- msg = {'proxy_address': onu_device.proxy_address,
+ msg = {'proxy_address': onu_device.proxy_address, 'uni_id': uni_id,
'event': 'download_tech_profile', 'event_data': tp_path}
# Send the event message to the ONU adapter
@@ -403,23 +403,23 @@
if classifier[ETH_TYPE] == LLDP_ETH_TYPE:
self.log.debug('lldp flow add')
- self.add_lldp_flow(flow)
+ self.add_lldp_flow(flow, port_no)
elif PUSH_VLAN in action:
- self.add_upstream_data_flow(intf_id, onu_id, classifier,
+ self.add_upstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier,
action, flow, alloc_id, gemport_id)
elif POP_VLAN in action:
- self.add_downstream_data_flow(intf_id, onu_id, classifier,
+ self.add_downstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier,
action, flow, alloc_id, gemport_id)
else:
self.log.debug('Invalid-flow-type-to-handle',
classifier=classifier,
action=action, flow=flow)
- def create_tcont_gemport(self, intf_id, onu_id, table_id):
+ def create_tcont_gemport(self, intf_id, onu_id, uni_id, table_id):
alloc_id, gem_port_ids = None, None
try:
- ofp_port_name = self._get_ofp_port_name(intf_id, onu_id)
+ (ofp_port_name, ofp_port_no) = self._get_ofp_port_name(intf_id, onu_id, uni_id)
if ofp_port_name is None:
self.log.error("port-name-not-found")
return alloc_id, gem_port_ids
@@ -452,6 +452,8 @@
self.stub.CreateTconts(openolt_pb2.Tconts(intf_id=intf_id,
onu_id=onu_id,
+ uni_id=uni_id,
+ port_no=ofp_port_no,
tconts=tconts))
else:
raise Exception('Tech-profile-instance-creation-failed')
@@ -471,8 +473,8 @@
except BaseException as e:
self.log.exception(exception=e)
- # Update the allocated alloc_id and gem_port_id for the ONU to KV store
- pon_intf_onu_id = (intf_id, onu_id)
+ # Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store
+ pon_intf_onu_id = (intf_id, onu_id, uni_id)
self.resource_mgr.resource_mgrs[intf_id].update_alloc_ids_for_onu(
pon_intf_onu_id,
list([alloc_id])
@@ -483,65 +485,67 @@
)
self.resource_mgr.update_gemports_ponport_to_onu_map_on_kv_store(
- gem_port_ids, intf_id, onu_id
+ gem_port_ids, intf_id, onu_id, uni_id
)
return alloc_id, gem_port_ids
- def add_upstream_data_flow(self, intf_id, onu_id, uplink_classifier,
+ def add_upstream_data_flow(self, intf_id, onu_id, uni_id, port_no, uplink_classifier,
uplink_action, logical_flow, alloc_id,
gemport_id):
uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG
- self.add_hsia_flow(intf_id, onu_id, uplink_classifier,
+ self.add_hsia_flow(intf_id, onu_id, uni_id, port_no, uplink_classifier,
uplink_action, UPSTREAM,
logical_flow, alloc_id, gemport_id)
# Secondary EAP on the subscriber vlan
- (eap_active, eap_logical_flow) = self.is_eap_enabled(intf_id, onu_id)
+ (eap_active, eap_logical_flow) = self.is_eap_enabled(intf_id, onu_id, uni_id)
if eap_active:
- self.add_eapol_flow(intf_id, onu_id, eap_logical_flow, alloc_id,
+ self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, eap_logical_flow, alloc_id,
gemport_id, eapol_flow_category=EAPOL_SECONDARY_FLOW,
vlan_id=uplink_classifier[VLAN_VID])
- def add_downstream_data_flow(self, intf_id, onu_id, downlink_classifier,
+ def add_downstream_data_flow(self, intf_id, onu_id, uni_id, port_no, downlink_classifier,
downlink_action, flow, alloc_id, gemport_id):
downlink_classifier[PACKET_TAG_TYPE] = DOUBLE_TAG
# Needed ???? It should be already there
downlink_action[POP_VLAN] = True
downlink_action[VLAN_VID] = downlink_classifier[VLAN_VID]
- self.add_hsia_flow(intf_id, onu_id, downlink_classifier,
+ self.add_hsia_flow(intf_id, onu_id, uni_id, port_no, downlink_classifier,
downlink_action, DOWNSTREAM,
flow, alloc_id, gemport_id)
- def add_hsia_flow(self, intf_id, onu_id, classifier, action,
+ def add_hsia_flow(self, intf_id, onu_id, uni_id, port_no, classifier, action,
direction, logical_flow, alloc_id, gemport_id):
- flow_id = self.resource_mgr.get_hsia_flow_for_onu(intf_id, onu_id, gemport_id)
+ flow_id = self.resource_mgr.get_hsia_flow_for_uni(intf_id, onu_id, uni_id, gemport_id)
if flow_id is None:
self.log.error("hsia-flow-unavailable")
return
flow = openolt_pb2.Flow(
- access_intf_id=intf_id, onu_id=onu_id, flow_id=flow_id,
+ access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=flow_id,
flow_type=direction, alloc_id=alloc_id, network_intf_id=0,
gemport_id=gemport_id,
classifier=self.mk_classifier(classifier),
action=self.mk_action(action),
- priority=logical_flow.priority)
+ priority=logical_flow.priority,
+ port_no=port_no,
+ cookie=logical_flow.cookie)
if self.add_flow_to_device(flow, logical_flow):
flow_info = self._get_flow_info_as_json_blob(flow, HSIA_FLOW)
- self.update_flow_info_to_kv_store(flow.access_intf_id, flow.onu_id,
+ self.update_flow_info_to_kv_store(flow.access_intf_id, flow.onu_id, flow.uni_id,
flow.flow_id, flow_info)
- def add_dhcp_trap(self, intf_id, onu_id, classifier, action, logical_flow,
+ def add_dhcp_trap(self, intf_id, onu_id, uni_id, port_no, classifier, action, logical_flow,
alloc_id, gemport_id):
self.log.debug('add dhcp upstream trap', classifier=classifier,
- intf_id=intf_id, onu_id=onu_id, action=action)
+ intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, action=action)
action.clear()
action[TRAP_TO_HOST] = True
@@ -550,25 +554,27 @@
classifier[PACKET_TAG_TYPE] = SINGLE_TAG
classifier.pop(VLAN_VID, None)
- pon_intf_onu_id = (intf_id, onu_id)
- flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id)
+ flow_id = self.resource_mgr.get_flow_id(intf_id, onu_id, uni_id)
dhcp_flow = openolt_pb2.Flow(
- onu_id=onu_id, flow_id=flow_id, flow_type=UPSTREAM,
+ onu_id=onu_id, uni_id=uni_id, flow_id=flow_id, flow_type=UPSTREAM,
access_intf_id=intf_id, gemport_id=gemport_id,
alloc_id=alloc_id, network_intf_id=0,
priority=logical_flow.priority,
classifier=self.mk_classifier(classifier),
- action=self.mk_action(action))
+ action=self.mk_action(action),
+ port_no=port_no,
+ cookie=logical_flow.cookie)
if self.add_flow_to_device(dhcp_flow, logical_flow):
flow_info = self._get_flow_info_as_json_blob(dhcp_flow, DHCP_FLOW)
self.update_flow_info_to_kv_store(dhcp_flow.access_intf_id,
dhcp_flow.onu_id,
+ dhcp_flow.uni_id,
dhcp_flow.flow_id,
flow_info)
- def add_eapol_flow(self, intf_id, onu_id, logical_flow, alloc_id,
+ def add_eapol_flow(self, intf_id, onu_id, uni_id, port_no, logical_flow, alloc_id,
gemport_id, eapol_flow_category=EAPOL_PRIMARY_FLOW,
vlan_id=DEFAULT_MGMT_VLAN):
@@ -580,20 +586,21 @@
uplink_action = dict()
uplink_action[TRAP_TO_HOST] = True
- pon_intf_onu_id = (intf_id, onu_id)
# Add Upstream EAPOL Flow.
if eapol_flow_category == EAPOL_PRIMARY_FLOW:
- uplink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id)
+ uplink_flow_id = self.resource_mgr.get_flow_id(intf_id, onu_id, uni_id)
else:
- uplink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id)
+ uplink_flow_id = self.resource_mgr.get_flow_id(intf_id, onu_id, uni_id)
upstream_flow = openolt_pb2.Flow(
- access_intf_id=intf_id, onu_id=onu_id, flow_id=uplink_flow_id,
+ access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=uplink_flow_id,
flow_type=UPSTREAM, alloc_id=alloc_id, network_intf_id=0,
gemport_id=gemport_id,
classifier=self.mk_classifier(uplink_classifier),
action=self.mk_action(uplink_action),
- priority=logical_flow.priority)
+ priority=logical_flow.priority,
+ port_no=port_no,
+ cookie=logical_flow.cookie)
logical_flow = copy.deepcopy(logical_flow)
logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid(
@@ -606,6 +613,7 @@
EAPOL_PRIMARY_FLOW)
self.update_flow_info_to_kv_store(upstream_flow.access_intf_id,
upstream_flow.onu_id,
+ upstream_flow.uni_id,
upstream_flow.flow_id,
flow_info)
else:
@@ -613,13 +621,16 @@
EAPOL_SECONDARY_FLOW)
self.update_flow_info_to_kv_store(upstream_flow.access_intf_id,
upstream_flow.onu_id,
+ upstream_flow.uni_id,
upstream_flow.flow_id,
flow_info)
if vlan_id == DEFAULT_MGMT_VLAN:
# Add Downstream EAPOL Flow, Only for first EAP flow (BAL
# requirement)
- special_vlan_downstream_flow = 4000 - onu_id
+ # FIXME this is actually not used. But, here to be consistent with the upstream tagging from ONU.
+ # It needs refactored to be completely removed
+ special_vlan_downstream_flow = 4091 # 4000 - onu_id
downlink_classifier = dict()
downlink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG
@@ -629,16 +640,17 @@
downlink_action[PUSH_VLAN] = True
downlink_action[VLAN_VID] = vlan_id
- pon_intf_onu_id = (intf_id, onu_id)
- downlink_flow_id = self.resource_mgr.get_flow_id(pon_intf_onu_id)
+ downlink_flow_id = self.resource_mgr.get_flow_id(intf_id, onu_id, uni_id)
downstream_flow = openolt_pb2.Flow(
- access_intf_id=intf_id, onu_id=onu_id, flow_id=downlink_flow_id,
+ access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=downlink_flow_id,
flow_type=DOWNSTREAM, alloc_id=alloc_id, network_intf_id=0,
gemport_id=gemport_id,
classifier=self.mk_classifier(downlink_classifier),
action=self.mk_action(downlink_action),
- priority=logical_flow.priority)
+ priority=logical_flow.priority,
+ port_no=port_no,
+ cookie=logical_flow.cookie)
downstream_logical_flow = ofp_flow_stats(
id=logical_flow.id, cookie=logical_flow.cookie,
@@ -652,13 +664,14 @@
downstream_logical_flow.instructions.extend(
fd.mk_instructions_from_actions([fd.output(
- self.platform.mk_uni_port_num(intf_id, onu_id))]))
+ self.platform.mk_uni_port_num(intf_id, onu_id, uni_id))]))
if self.add_flow_to_device(downstream_flow, downstream_logical_flow):
flow_info = self._get_flow_info_as_json_blob(downstream_flow,
EAPOL_PRIMARY_FLOW)
self.update_flow_info_to_kv_store(downstream_flow.access_intf_id,
downstream_flow.onu_id,
+ downstream_flow.uni_id,
downstream_flow.flow_id,
flow_info)
@@ -673,7 +686,7 @@
if logical_flow.id not in logical_flows_ids_provisioned:
self.add_flow(logical_flow)
except Exception as e:
- self.log.debug('Problem readding this flow', error=e)
+ self.log.exception('Problem reading this flow', e=e)
def reset_flows(self):
self.flows_proxy.update('/', Flows())
@@ -681,7 +694,7 @@
""" Add a downstream LLDP trap flow on the NNI interface
"""
- def add_lldp_flow(self, logical_flow, network_intf_id=0):
+ def add_lldp_flow(self, logical_flow, port_no, network_intf_id=0):
classifier = dict()
classifier[ETH_TYPE] = LLDP_ETH_TYPE
@@ -701,24 +714,27 @@
# we need to have a re-look at this.
# *********************************************
onu_id = -1
- intf_id_onu_id = (network_intf_id, onu_id)
- flow_id = self.resource_mgr.get_flow_id(intf_id_onu_id)
+ uni_id = -1
+ flow_id = self.resource_mgr.get_flow_id(network_intf_id, onu_id, uni_id)
downstream_flow = openolt_pb2.Flow(
access_intf_id=-1, # access_intf_id not required
- onu_id=onu_id, # onu_id not required
+ onu_id=onu_id, # onu_id not required
+ uni_id=uni_id, # uni_id not used
flow_id=flow_id,
flow_type=DOWNSTREAM,
network_intf_id=network_intf_id,
gemport_id=-1, # gemport_id not required
classifier=self.mk_classifier(classifier),
action=self.mk_action(action),
- priority=logical_flow.priority)
+ priority=logical_flow.priority,
+ port_no=port_no,
+ cookie=logical_flow.cookie)
self.log.debug('add lldp downstream trap', classifier=classifier,
- action=action, flow=downstream_flow)
+ action=action, flow=downstream_flow, port_no=port_no)
if self.add_flow_to_device(downstream_flow, logical_flow):
- self.update_flow_info_to_kv_store(network_intf_id, onu_id,
+ self.update_flow_info_to_kv_store(network_intf_id, onu_id, uni_id,
flow_id, downstream_flow)
def mk_classifier(self, classifier_info):
@@ -771,13 +787,14 @@
return
return action
- def is_eap_enabled(self, intf_id, onu_id):
+ def is_eap_enabled(self, intf_id, onu_id, uni_id):
flows = self.logical_flows_proxy.get('/').items
for flow in flows:
eap_flow = False
eap_intf_id = None
eap_onu_id = None
+ eap_uni_id = None
for field in fd.get_ofb_fields(flow):
if field.type == fd.ETH_TYPE:
if field.eth_type == EAP_ETH_TYPE:
@@ -786,12 +803,14 @@
eap_intf_id = self.platform.intf_id_from_uni_port_num(
field.port)
eap_onu_id = self.platform.onu_id_from_port_num(field.port)
+ eap_uni_id = self.platform.uni_id_from_port_num(field.port)
if eap_flow:
- self.log.debug('eap flow detected', onu_id=onu_id,
+ self.log.debug('eap flow detected', onu_id=onu_id, uni_id=uni_id,
intf_id=intf_id, eap_intf_id=eap_intf_id,
- eap_onu_id=eap_onu_id)
- if eap_flow and intf_id == eap_intf_id and onu_id == eap_onu_id:
+ eap_onu_id=eap_onu_id,
+ eap_uni_id=eap_uni_id)
+ if eap_flow and intf_id == eap_intf_id and onu_id == eap_onu_id and uni_id == eap_uni_id:
return True, flow
return False, None
@@ -832,9 +851,8 @@
self.register_flow(logical_flow, flow)
return True
- def update_flow_info_to_kv_store(self, intf_id, onu_id, flow_id, flow):
- pon_intf_onu_id = (intf_id, onu_id)
- self.resource_mgr.update_flow_id_info_for_onu(pon_intf_onu_id,
+ def update_flow_info_to_kv_store(self, intf_id, onu_id, uni_id, flow_id, flow):
+ self.resource_mgr.update_flow_id_info_for_uni(intf_id, onu_id, uni_id,
flow_id, flow)
def register_flow(self, logical_flow, device_flow):
@@ -894,8 +912,11 @@
def clear_flows_and_scheduler_for_logical_port(self, child_device, logical_port):
ofp_port_name = logical_port.ofp_port.name
+ port_no = logical_port.ofp_port.port_no
pon_port = child_device.proxy_address.channel_id
onu_id = child_device.proxy_address.onu_id
+ uni_id = self.platform.uni_id_from_port_num(logical_port)
+
# TODO: The DEFAULT_TECH_PROFILE_ID is assumed. Right way to do,
# is probably to maintain a list of Tech-profile table IDs associated
# with the UNI logical_port. This way, when the logical port is deleted,
@@ -905,13 +926,10 @@
get_tech_profile_instance(
DEFAULT_TECH_PROFILE_TABLE_ID,
ofp_port_name)
- flow_ids = self.resource_mgr.get_current_flow_ids_for_onu(pon_port,
- onu_id)
+ flow_ids = self.resource_mgr.get_current_flow_ids_for_uni(pon_port, onu_id, uni_id)
self.log.debug("outstanding-flows-to-be-cleared", flow_ids=flow_ids)
for flow_id in flow_ids:
- flow_infos = self.resource_mgr.get_flow_id_info(pon_port,
- onu_id,
- flow_id)
+ flow_infos = self.resource_mgr.get_flow_id_info(pon_port, onu_id, uni_id, flow_id)
for flow_info in flow_infos:
direction = flow_info['flow_type']
flow_to_remove = openolt_pb2.Flow(flow_id=flow_id,
@@ -926,12 +944,14 @@
else:
raise grpc_e
- self.resource_mgr.free_flow_id(pon_port, onu_id, flow_id)
+ self.resource_mgr.free_flow_id_for_uni(pon_port, onu_id, uni_id, flow_id)
try:
tconts = self.tech_profile[pon_port].get_tconts(tech_profile_instance)
self.stub.RemoveTconts(openolt_pb2.Tconts(intf_id=pon_port,
onu_id=onu_id,
+ uni_id=uni_id,
+ port_no=port_no,
tconts=tconts))
except grpc.RpcError as grpc_e:
self.log.error('error-removing-tcont-scheduler-queues',
@@ -970,7 +990,7 @@
self.log.debug("flow-info", json_blob=json_blob)
json_blob['flow_category'] = flow_category
flow_info = self.resource_mgr.get_flow_id_info(flow.access_intf_id,
- flow.onu_id, flow.flow_id)
+ flow.onu_id, flow.uni_id, flow.flow_id)
if flow_info is None:
flow_info = list()
diff --git a/voltha/adapters/openolt/openolt_platform.py b/voltha/adapters/openolt/openolt_platform.py
index c62bf8b..a44eafc 100644
--- a/voltha/adapters/openolt/openolt_platform.py
+++ b/voltha/adapters/openolt/openolt_platform.py
@@ -76,21 +76,27 @@
"""
-# MAX_ONUS_PER_PON = 112
-MAX_ONUS_PER_PON = 32
-
class OpenOltPlatform(object):
+ MAX_PONS_PER_OLT = 16
+ MAX_ONUS_PER_PON = 32
+ MAX_UNIS_PER_ONU = 16
- def __init__(self, log, device_info):
+ def __init__(self, log, resource_mgr):
self.log = log
- self.device_info = device_info
+ self.resource_mgr = resource_mgr
- def mk_uni_port_num(self, intf_id, onu_id):
- return intf_id << 11 | onu_id << 4
+ def mk_uni_port_num(self, intf_id, onu_id, uni_id):
+ assert intf_id < OpenOltPlatform.MAX_PONS_PER_OLT
+ assert onu_id < OpenOltPlatform.MAX_ONUS_PER_PON
+ assert uni_id < OpenOltPlatform.MAX_UNIS_PER_ONU
+ self.resource_mgr.assert_uni_id_limit(intf_id, onu_id, uni_id)
+ return intf_id << 11 | onu_id << 4 | uni_id
- def mk_flow_id(self, intf_id, onu_id, idx):
- return intf_id << 9 | onu_id << 4 | idx
+ #def mk_flow_id(self, intf_id, onu_id, idx):
+ # return intf_id << 9 | onu_id << 4 | idx
+ def uni_id_from_port_num(self, port_num):
+ return port_num & 0xF
def onu_id_from_port_num(self, port_num):
return (port_num >> 4) & 0x7F
@@ -123,7 +129,7 @@
elif intf_id & (0x1 << 16) == (0x1 << 16):
return Port.ETHERNET_NNI
else:
- return None
+ return Port.ETHERNET_UNI
def port_type_name_by_port_index(self, port_index):
try:
@@ -133,11 +139,15 @@
def extract_access_from_flow(self, in_port, out_port):
if self.is_upstream(out_port):
- return (self.intf_id_from_uni_port_num(in_port),
- self.onu_id_from_port_num(in_port))
+ return (in_port,
+ self.intf_id_from_uni_port_num(in_port),
+ self.onu_id_from_port_num(in_port),
+ self.uni_id_from_port_num(in_port))
else:
- return (self.intf_id_from_uni_port_num(out_port),
- self.onu_id_from_port_num(out_port))
+ return (out_port,
+ self.intf_id_from_uni_port_num(out_port),
+ self.onu_id_from_port_num(out_port),
+ self.uni_id_from_port_num(out_port))
def is_upstream(self, out_port):
@@ -149,6 +159,6 @@
return True
return False
-
- def max_onus_per_pon(self):
- return MAX_ONUS_PER_PON
+ #
+ #def max_onus_per_pon(self):
+ # return OpenOltPlatform.MAX_ONUS_PER_PON
diff --git a/voltha/adapters/openolt/openolt_resource_manager.py b/voltha/adapters/openolt/openolt_resource_manager.py
index 7e869d4..49b353d 100644
--- a/voltha/adapters/openolt/openolt_resource_manager.py
+++ b/voltha/adapters/openolt/openolt_resource_manager.py
@@ -23,6 +23,7 @@
from voltha.adapters.openolt.openolt_flow_mgr import *
from voltha.adapters.openolt.protos import openolt_pb2
+from voltha.adapters.openolt.openolt_platform import OpenOltPlatform
class OpenOltResourceMgr(object):
@@ -35,6 +36,7 @@
self.host_and_port = host_and_port
self.extra_args = extra_args
self.device_info = device_info
+ self.max_uni_id_per_onu = 0 #OpenOltPlatform.MAX_UNIS_PER_ONU, Uncomment or override to make default multi-uni
self.args = registry('main').get_args()
# KV store's IP Address and PORT
@@ -113,6 +115,17 @@
for key, resource_mgr in self.resource_mgrs.iteritems():
resource_mgr.clear_device_resource_pool()
+ def assert_pon_id_limit(self, pon_intf_id):
+ assert pon_intf_id in self.resource_mgrs
+
+ def assert_onu_id_limit(self, pon_intf_id, onu_id):
+ self.assert_pon_id_limit(pon_intf_id)
+ self.resource_mgrs[pon_intf_id].assert_resource_limits(onu_id, PONResourceManager.ONU_ID)
+
+ def assert_uni_id_limit(self, pon_intf_id, onu_id, uni_id):
+ self.assert_onu_id_limit(pon_intf_id, onu_id)
+ self.resource_mgrs[pon_intf_id].assert_resource_limits(uni_id, PONResourceManager.UNI_ID)
+
def get_onu_id(self, pon_intf_id):
onu_id = self.resource_mgrs[pon_intf_id].get_resource_id(
pon_intf_id, PONResourceManager.ONU_ID, 1)
@@ -124,36 +137,36 @@
return onu_id
- def get_flow_id(self, pon_intf_onu_id):
- pon_intf = pon_intf_onu_id[0]
- flow_id = self.resource_mgrs[pon_intf].get_resource_id(
- pon_intf_onu_id[0], PONResourceManager.FLOW_ID)
+ def get_flow_id(self, pon_intf_id, onu_id, uni_id):
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
+ flow_id = self.resource_mgrs[pon_intf_id].get_resource_id(
+ pon_intf_id, PONResourceManager.FLOW_ID)
if flow_id is not None:
- self.resource_mgrs[pon_intf].update_flow_id_for_onu(pon_intf_onu_id, flow_id)
+ self.resource_mgrs[pon_intf_id].update_flow_id_for_onu(pon_intf_onu_id, flow_id)
return flow_id
- def get_flow_id_info(self, pon_intf_id, onu_id, flow_id):
- pon_intf_onu_id = (pon_intf_id, onu_id)
+ def get_flow_id_info(self, pon_intf_id, onu_id, uni_id, flow_id):
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
return self.resource_mgrs[pon_intf_id].get_flow_id_info(pon_intf_onu_id, flow_id)
- def get_current_flow_ids_for_onu(self, pon_intf_id, onu_id):
- pon_intf_onu_id = (pon_intf_id, onu_id)
+ def get_current_flow_ids_for_uni(self, pon_intf_id, onu_id, uni_id):
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
return self.resource_mgrs[pon_intf_id].get_current_flow_ids_for_onu(pon_intf_onu_id)
- def update_flow_id_info_for_onu(self, pon_intf_onu_id, flow_id, flow_data):
- pon_intf_id = pon_intf_onu_id[0]
+ def update_flow_id_info_for_uni(self, pon_intf_id, onu_id, uni_id, flow_id, flow_data):
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
return self.resource_mgrs[pon_intf_id].update_flow_id_info_for_onu(
pon_intf_onu_id, flow_id, flow_data)
- def get_hsia_flow_for_onu(self, pon_intf_id, onu_id, gemport_id):
- pon_intf_onu_id = (pon_intf_id, onu_id)
+ def get_hsia_flow_for_uni(self, pon_intf_id, onu_id, uni_id, gemport_id):
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
try:
flow_ids = self.resource_mgrs[pon_intf_id]. \
get_current_flow_ids_for_onu(pon_intf_onu_id)
if flow_ids is not None:
for flow_id in flow_ids:
- flows = self.get_flow_id_info(pon_intf_id, onu_id, flow_id)
+ flows = self.get_flow_id_info(pon_intf_id, onu_id, uni_id, flow_id)
assert (isinstance(flows, list))
for flow in flows:
if flow['flow_category'] == HSIA_FLOW and \
@@ -162,7 +175,7 @@
except Exception as e:
self.log.error("error-retrieving-flow-info", e=e)
- return self.get_flow_id(pon_intf_onu_id)
+ return self.get_flow_id(pon_intf_id, onu_id, uni_id)
def get_alloc_id(self, pon_intf_onu_id):
# Derive the pon_intf from the pon_intf_onu_id tuple
@@ -194,20 +207,27 @@
def get_current_gemport_ids_for_onu(self, pon_intf_onu_id):
pon_intf_id = pon_intf_onu_id[0]
+ assert False, 'unused function'
return self.resource_mgrs[pon_intf_id].get_current_gemport_ids_for_onu(pon_intf_onu_id)
- def update_gemports_ponport_to_onu_map_on_kv_store(self, gemport_list, pon_port, onu_id):
+ def update_gemports_ponport_to_onu_map_on_kv_store(self, gemport_list, pon_port, onu_id, uni_id):
for gemport in gemport_list:
pon_intf_gemport = (pon_port, gemport)
# This information is used when packet_indication is received and
# we need to derive the ONU Id for which the packet arrived based
# on the pon_intf and gemport available in the packet_indication
- self.kv_store[str(pon_intf_gemport)] = str(onu_id)
+ self.kv_store[str(pon_intf_gemport)] = ' '.join(map(str, (onu_id, uni_id)))
+
+ def get_onu_uni_from_ponport_gemport(self, pon_port, gemport):
+ pon_intf_gemport = (pon_port, gemport)
+ return tuple(map(int, self.kv_store[str(pon_intf_gemport)].split(' ')))
def get_gemport_id(self, pon_intf_onu_id, num_of_id=1):
# Derive the pon_intf and onu_id from the pon_intf_onu_id tuple
pon_intf = pon_intf_onu_id[0]
onu_id = pon_intf_onu_id[1]
+ uni_id = pon_intf_onu_id[2]
+ assert False, 'unused function'
gemport_id_list = self.resource_mgrs[pon_intf].get_current_gemport_ids_for_onu(
pon_intf_onu_id)
@@ -230,7 +250,7 @@
gemport_id_list)
self.update_gemports_ponport_to_onu_map_on_kv_store(gemport_id_list,
- pon_intf, onu_id)
+ pon_intf, onu_id, uni_id)
return gemport_id_list
def free_onu_id(self, pon_intf_id, onu_id):
@@ -241,10 +261,10 @@
self.resource_mgrs[pon_intf_id].remove_resource_map(
pon_intf_onu_id)
- def free_flow_id(self, pon_intf_id, onu_id, flow_id):
+ def free_flow_id_for_uni(self, pon_intf_id, onu_id, uni_id, flow_id):
self.resource_mgrs[pon_intf_id].free_resource_id(
pon_intf_id, PONResourceManager.FLOW_ID, flow_id)
- pon_intf_onu_id = (pon_intf_id, onu_id)
+ pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
self.resource_mgrs[pon_intf_id].update_flow_id_for_onu(pon_intf_onu_id,
flow_id, False)
self.resource_mgrs[pon_intf_id].remove_flow_id_info(pon_intf_onu_id,
@@ -361,6 +381,7 @@
flow_id_start_idx=flow_id_start,
flow_id_end_idx=flow_id_end,
flow_id_shared_pool_id=flow_id_shared_pool_id,
+ uni_id_start_idx=0, uni_id_end_idx=self.max_uni_id_per_onu,
num_of_pon_ports=self.device_info.pon_ports,
intf_ids=arange.intf_ids
)
@@ -388,3 +409,6 @@
flow_id_end_idx=flow_id_end)
resource_mgr.update_ranges(flow_id_start_idx=flow_id_start, flow_id_end_idx=flow_id_end,
flow_id_shared_resource_mgr=global_resource_mgr)
+
+ # Make sure loaded range fits the platform bit encoding ranges
+ resource_mgr.update_ranges(uni_id_start_idx=0, uni_id_end_idx=OpenOltPlatform.MAX_UNIS_PER_ONU-1)
diff --git a/voltha/adapters/openolt/protos/openolt.proto b/voltha/adapters/openolt/protos/openolt.proto
index 8c35bba..0368bd8 100644
--- a/voltha/adapters/openolt/protos/openolt.proto
+++ b/voltha/adapters/openolt/protos/openolt.proto
@@ -217,6 +217,8 @@
fixed32 intf_id = 1;
fixed32 gemport_id = 2;
fixed32 flow_id = 3;
+ fixed32 port_no = 6;
+ fixed64 cookie = 7;
bytes pkt = 4;
}
@@ -244,6 +246,7 @@
message OnuPacket {
fixed32 intf_id = 1;
fixed32 onu_id = 2;
+ fixed32 port_no = 4;
bytes pkt = 3;
}
@@ -342,6 +345,7 @@
message Flow {
sfixed32 access_intf_id = 1;
sfixed32 onu_id = 2;
+ sfixed32 uni_id = 11;
fixed32 flow_id = 3;
string flow_type = 4; // upstream, downstream, broadcast, multicast
sfixed32 alloc_id = 10;
@@ -350,6 +354,8 @@
Classifier classifier = 7;
Action action = 8;
sfixed32 priority = 9;
+ fixed64 cookie = 12; // must be provided for any flow with trap_to_host action. Returned in PacketIndication
+ fixed32 port_no = 13; // must be provided for any flow with trap_to_host action. Returned in PacketIndication
}
message SerialNumber {
@@ -515,6 +521,8 @@
message Tconts {
fixed32 intf_id = 1;
fixed32 onu_id = 2;
+ fixed32 uni_id = 4;
+ fixed32 port_no = 5;
repeated Tcont tconts = 3;
}
diff --git a/voltha/core/logical_device_agent.py b/voltha/core/logical_device_agent.py
index f3a8417..70e26b6 100644
--- a/voltha/core/logical_device_agent.py
+++ b/voltha/core/logical_device_agent.py
@@ -786,42 +786,45 @@
if len(downstream_ports) == 0:
return None, None
# assert len(downstream_ports) == 1
- flows = OrderedDict((f.id, f) for f in [
- mk_flow_stat(
- priority=500,
- match_fields=[
- in_port(downstream_ports[0].port_no),
- vlan_vid(ofp.OFPVID_PRESENT | 0)
- ],
- actions=[
- set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)),
- output(upstream_ports[0].port_no)
- ]
- ),
- mk_flow_stat(
- priority=500,
- match_fields=[
- in_port(downstream_ports[0].port_no),
- vlan_vid(0)
- ],
- actions=[
- push_vlan(0x8100),
- set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)),
- output(upstream_ports[0].port_no)
- ]
- ),
- mk_flow_stat(
- priority=500,
- match_fields=[
- in_port(upstream_ports[0].port_no),
- vlan_vid(ofp.OFPVID_PRESENT | device.vlan)
- ],
- actions=[
- set_field(vlan_vid(ofp.OFPVID_PRESENT | 0)),
- output(downstream_ports[0].port_no)
- ]
- ),
- ])
+ upstream_port = upstream_ports[0]
+ flows = OrderedDict()
+ for downstream_port in downstream_ports:
+ flows.update(OrderedDict((f.id, f) for f in [
+ mk_flow_stat(
+ priority=500,
+ match_fields=[
+ in_port(downstream_port.port_no),
+ vlan_vid(ofp.OFPVID_PRESENT | 0)
+ ],
+ actions=[
+ set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)),
+ output(upstream_port.port_no)
+ ]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[
+ in_port(downstream_port.port_no),
+ vlan_vid(0)
+ ],
+ actions=[
+ push_vlan(0x8100),
+ set_field(vlan_vid(ofp.OFPVID_PRESENT | device.vlan)),
+ output(upstream_port.port_no)
+ ]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[
+ in_port(upstream_port.port_no),
+ vlan_vid(ofp.OFPVID_PRESENT | device.vlan)
+ ],
+ actions=[
+ set_field(vlan_vid(ofp.OFPVID_PRESENT | 0)),
+ output(downstream_port.port_no)
+ ]
+ ),
+ ]))
groups = OrderedDict()
return flows, groups
diff --git a/voltha/extensions/omci/omci_cc.py b/voltha/extensions/omci/omci_cc.py
index 6632d28..1d5c897 100644
--- a/voltha/extensions/omci/omci_cc.py
+++ b/voltha/extensions/omci/omci_cc.py
@@ -373,14 +373,18 @@
status = omci_getnext_msg.fields['success_code']
if status != ReasonCodes.Success.value:
- raise Exception('omci-status ' + status)
+ raise Exception('get-next-failure table=' + eca.field.name +
+ ' entity_id=' + str(entity_id) +
+ ' sqn=' + str(seq_no) + ' omci-status ' + str(status))
break
except Exception as e:
- self.log.exception('get-next-error ' + eca.field.name, e=e)
retries -= 1
if retries <= 0:
+ self.log.exception('get-next-error-abort', e=e)
raise e
+ else:
+ self.log.error('get-next-error-retry', e=e, retries_remaining=retries)
# Extract the data
num_octets = count - offset
diff --git a/voltha/extensions/omci/tasks/omci_get_request.py b/voltha/extensions/omci/tasks/omci_get_request.py
index 45c1db4..8b353c9 100644
--- a/voltha/extensions/omci/tasks/omci_get_request.py
+++ b/voltha/extensions/omci/tasks/omci_get_request.py
@@ -47,7 +47,7 @@
name = "ONU OMCI Get Task"
def __init__(self, omci_agent, device_id, entity_class, entity_id, attributes,
- exclusive=False, allow_failure=False):
+ exclusive=True, allow_failure=False):
"""
Class initialization
@@ -57,7 +57,7 @@
:param entity_id: (int) ME Class instance ID to retrieve
:param attributes: (list or set) Name of attributes to retrieve
:param exclusive: (bool) True if this GET request Task exclusively own the
- OMCI-CC while running. Default: False
+ OMCI-CC while running. Default: True
:param allow_failure: (bool) If true, attempt to get all valid attributes
if the original request receives an error
code of 9 (Attributes failed or unknown).