Update VLAN support to match POC-3 requirements
Change-Id: I556edb4b55d8cbf7ce112f9d867641ec7eaeb489
diff --git a/voltha/adapters/adtran_olt/adtran_device_handler.py b/voltha/adapters/adtran_olt/adtran_device_handler.py
index 5422a07..e8c8af6 100644
--- a/voltha/adapters/adtran_olt/adtran_device_handler.py
+++ b/voltha/adapters/adtran_olt/adtran_device_handler.py
@@ -144,7 +144,7 @@
# registered (via xPON API/CLI) before they are activated.
self._autoactivate = False
- self.max_nni_ports = 1 # TODO: This is a VOLTHA imposed limit in 'low_decomposer.py
+ self.max_nni_ports = 1 # TODO: This is a VOLTHA imposed limit in 'flow_decomposer.py
# and logical_device_agent.py
# OMCI ZMQ Channel
self.zmq_port = DEFAULT_ZEROMQ_OMCI_TCP_PORT
@@ -152,7 +152,7 @@
# Heartbeat support
self.heartbeat_count = 0
self.heartbeat_miss = 0
- self.heartbeat_interval = 5 # TODO: Decrease before release or any scale testing
+ self.heartbeat_interval = 2 # TODO: Decrease before release or any scale testing
self.heartbeat_failed_limit = 3
self.heartbeat_timeout = 5
self.heartbeat = None
diff --git a/voltha/adapters/adtran_olt/adtran_olt.py b/voltha/adapters/adtran_olt/adtran_olt.py
index 23ba5eb..be75f2e 100644
--- a/voltha/adapters/adtran_olt/adtran_olt.py
+++ b/voltha/adapters/adtran_olt/adtran_olt.py
@@ -51,7 +51,7 @@
self.descriptor = Adapter(
id=self.name,
vendor='Adtran, Inc.',
- version='0.5',
+ version='0.7',
config=AdapterConfig(log_level=LogLevel.INFO)
)
log.debug('adtran_olt.__init__', adapter_agent=adapter_agent)
diff --git a/voltha/adapters/adtran_olt/adtran_olt_handler.py b/voltha/adapters/adtran_olt/adtran_olt_handler.py
index 524648b..4eb2a63 100644
--- a/voltha/adapters/adtran_olt/adtran_olt_handler.py
+++ b/voltha/adapters/adtran_olt/adtran_olt_handler.py
@@ -32,7 +32,7 @@
OntaniConfig, VOntaniConfig, VEnetConfig
FIXED_ONU = True # Enhanced ONU support
-
+ATT_NETWORK = True # Use AT&T cVlan scheme
class AdtranOltHandler(AdtranDeviceHandler):
"""
@@ -516,6 +516,11 @@
def get_channel_id(self, pon_id, onu_id):
from pon_port import PonPort
+ if ATT_NETWORK:
+ if FIXED_ONU:
+ return onu_id + 2
+ return 1 + onu_id + (pon_id * 120)
+
if FIXED_ONU:
return self._onu_offset(onu_id)
return self._onu_offset(onu_id) + (pon_id * PonPort.MAX_ONUS_SUPPORTED)
@@ -528,6 +533,11 @@
def _channel_id_to_pon_id(self, channel_id, onu_id):
from pon_port import PonPort
+ if ATT_NETWORK:
+ if FIXED_ONU:
+ return channel_id - onu_id - 2
+ return (channel_id - onu_id - 1) / 120
+
if FIXED_ONU:
return channel_id - self._onu_offset(onu_id)
return (channel_id - self._onu_offset(onu_id)) / PonPort.MAX_ONUS_SUPPORTED
@@ -627,27 +637,13 @@
return self._v_enets
return None
- def create_interface(self, data):
- """
- Create XPON interfaces
- :param data: (xpon config info)
- """
+ def _data_to_dict(self, data):
name = data.name
interface = data.interface
inst_data = data.data
- items = self._get_xpon_collection(data)
-
- if items is not None and name not in items:
- self._cached_xpon_pon_info = {} # Clear cached data
-
if isinstance(data, ChannelgroupConfig):
- self.log.debug('create_interface-channel-group', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("Channel group '{}' already exists".format(name))
-
- items[name] = {
+ return 'channel-group', {
'name': name,
'enabled': interface.enabled,
'system-id': inst_data.system_id,
@@ -655,23 +651,18 @@
}
elif isinstance(data, ChannelpartitionConfig):
- self.log.debug('create_interface-channel-partition', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("Channel partition '{}' already exists".format(name))
-
def _auth_method_enum_to_string(value):
from voltha.protos.bbf_fiber_types_pb2 import SERIAL_NUMBER, LOID, \
REGISTRATION_ID, OMCI, DOT1X
return {
SERIAL_NUMBER: 'serial-number',
LOID: 'loid',
- REGISTRATION_ID: 'registation-id',
+ REGISTRATION_ID: 'registration-id',
OMCI: 'omci',
- DOT1X: 'don1x'
+ DOT1X: 'dot1x'
}.get(value, 'unknown')
- items[name] = {
+ return 'channel-partition', {
'name': name,
'enabled': interface.enabled,
'authentication-method': _auth_method_enum_to_string(inst_data.authentication_method),
@@ -682,12 +673,7 @@
}
elif isinstance(data, ChannelpairConfig):
- self.log.debug('create_interface-channel-pair', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("Channel pair '{}' already exists".format(name))
-
- items[name] = {
+ return 'channel-pair', {
'name': name,
'enabled': interface.enabled,
'channel-group': inst_data.channelgroup_ref,
@@ -696,12 +682,7 @@
}
elif isinstance(data, ChannelterminationConfig):
- self.log.debug('create_interface-channel-termination', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("Channel termination '{}' already exists".format(name))
-
- items[name] = {
+ return 'channel-termination', {
'name': name,
'enabled': interface.enabled,
'xgs-ponid': inst_data.xgs_ponid,
@@ -709,15 +690,9 @@
'channel-pair': inst_data.channelpair_ref,
'ber-calc-period': inst_data.ber_calc_period
}
- self.on_channel_termination_config(name, 'create')
elif isinstance(data, OntaniConfig):
- self.log.debug('create_interface-ont-ani', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("ONT ANI '{}' already exists".format(name))
-
- items[name] = {
+ return 'ont-ani', {
'name': name,
'enabled': interface.enabled,
'upstream-fec': inst_data.upstream_fec_indicator,
@@ -725,12 +700,7 @@
}
elif isinstance(data, VOntaniConfig):
- self.log.debug('create_interface-v-ont-ani', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("vONT ANI '{}' already exists".format(name))
-
- items[name] = {
+ return 'vOnt-ani', {
'name': name,
'enabled': interface.enabled,
'onu-id': inst_data.onu_id,
@@ -741,12 +711,7 @@
}
elif isinstance(data, VEnetConfig):
- self.log.debug('create_interface-v-enet', interface=interface, data=inst_data)
-
- if name in items:
- raise KeyError("vENET '{}' already exists".format(name))
-
- items[name] = {
+ return 'vEnet', {
'name': name,
'enabled': interface.enabled,
'v-ont-ani': inst_data.v_ontani_ref
@@ -755,6 +720,33 @@
else:
raise NotImplementedError('Unknown data type')
+ def create_interface(self, data):
+ """
+ Create XPON interfaces
+ :param data: (xpon config info)
+ """
+ self.log.debug('create-interface', interface=data.interface, inst_data=data.data)
+
+ name = data.name
+ interface = data.interface
+ inst_data = data.data
+
+ items = self._get_xpon_collection(data)
+
+ if items is not None and name not in items:
+ self._cached_xpon_pon_info = {} # Clear cached data
+
+ item_type, new_item = self._data_to_dict(data)
+ self.log.debug('new-item', item_type=item_type, item=new_item)
+
+ if name in items:
+ raise KeyError("{} '{}' already exists".format(item_type, name))
+
+ items[name] = new_item
+
+ if isinstance(data, ChannelterminationConfig):
+ self._on_channel_termination_create(name)
+
def update_interface(self, data):
"""
Update XPON interfaces
@@ -769,10 +761,46 @@
if items is None:
raise ValueError('Unknown data type: {}'.format(type(data)))
- if name not in items:
+ existing_item = items.get(name)
+ if existing_item is None:
raise KeyError("'{}' not found. Type: {}".format(name, type(data)))
+ item_type, update_item = self._data_to_dict(data)
+ self.log.debug('update-item', item_type=item_type, item=update_item)
+
+ # TODO: Calculate the difference
+ diffs = {}
+
+ if len(diffs) == 0:
+ self.log.debug('update-item-no-diffs')
+
self._cached_xpon_pon_info = {} # Clear cached data
+
+ # Act on changed items
+ if isinstance(data, ChannelgroupConfig):
+ pass
+
+ elif isinstance(data, ChannelpartitionConfig):
+ pass
+
+ elif isinstance(data, ChannelpairConfig):
+ pass
+
+ elif isinstance(data, ChannelterminationConfig):
+ pass
+
+ elif isinstance(data, OntaniConfig):
+ pass
+
+ elif isinstance(data, VOntaniConfig):
+ pass
+
+ elif isinstance(data, VEnetConfig):
+ pass
+
+ else:
+ raise NotImplementedError('Unknown data type')
+
raise NotImplementedError('TODO: not yet supported')
def delete_interface(self, data):
@@ -781,23 +809,42 @@
:param data: (xpon config info)
"""
name = data.name
- interface = data.interface
- inst_data = data.data
- self._cached_xpon_pon_info = {} # Clear cached data
items = self._get_xpon_collection(data)
item = items.get(name)
+ self.log.debug('delete-interface', name=name, data=data)
- if item in items:
+ if item is not None:
+ self._cached_xpon_pon_info = {} # Clear cached data
del items[name]
- pass # TODO Do something....
+
+ if isinstance(data, ChannelgroupConfig):
+ pass
+
+ elif isinstance(data, ChannelpartitionConfig):
+ pass
+
+ elif isinstance(data, ChannelpairConfig):
+ pass
+
+ elif isinstance(data, ChannelterminationConfig):
+ self._on_channel_termination_delete(name)
+
+ elif isinstance(data, OntaniConfig):
+ pass
+
+ elif isinstance(data, VOntaniConfig):
+ pass
+
+ elif isinstance(data, VEnetConfig):
+ pass
+
+ else:
+ raise NotImplementedError('Unknown data type')
+
raise NotImplementedError('TODO: not yet supported')
- def on_channel_termination_config(self, name, operation, pon_type='xgs-ponid'):
- supported_operations = ['create']
-
- assert operation in supported_operations, \
- 'Unsupported channel-term operation: {}'.format(operation)
+ def _on_channel_termination_create(self, name, pon_type='xgs-ponid'):
assert name in self._channel_terminations, \
'{} is not a channel-termination'.format(name)
ct = self._channel_terminations[name]
@@ -833,15 +880,27 @@
# TODO support FEC, and MCAST AES settings
# TODO Support setting of line rate
- if operation == 'create':
- pon_port.xpon_name = name
- pon_port.discovery_tick = polling_period
- pon_port.authentication_method = authentication_method
- pon_port.deployment_range = deployment_range * 1000 # pon-agent uses meters
- pon_port.downstream_fec_enable = downstream_fec
- # TODO: pon_port.mcast_aes = mcast_aes
+ pon_port.xpon_name = name
+ pon_port.discovery_tick = polling_period
+ pon_port.authentication_method = authentication_method
+ pon_port.deployment_range = deployment_range * 1000 # pon-agent uses meters
+ pon_port.downstream_fec_enable = downstream_fec
+ # TODO: pon_port.mcast_aes = mcast_aes
- pon_port.admin_state = AdminState.ENABLED if enabled else AdminState.DISABLED
+ pon_port.admin_state = AdminState.ENABLED if enabled else AdminState.DISABLED
+
+ def _on_channel_termination_delete(self, name, pon_type='xgs-ponid'):
+ assert name in self._channel_terminations, \
+ '{} is not a channel-termination'.format(name)
+ ct = self._channel_terminations[name]
+
+ # Look up the southbound PON port
+ pon_id = ct[pon_type]
+ pon_port = self.southbound_ports.get(pon_id, None)
+ if pon_port is None:
+ raise ValueError('Unknown PON port. PON-ID: {}'.format(pon_id))
+
+ pon_port.enabled = False
def create_tcont(self, tcont_data, traffic_descriptor_data):
"""
diff --git a/voltha/adapters/adtran_olt/pon_port.py b/voltha/adapters/adtran_olt/pon_port.py
index 275236e..0505057 100644
--- a/voltha/adapters/adtran_olt/pon_port.py
+++ b/voltha/adapters/adtran_olt/pon_port.py
@@ -53,7 +53,7 @@
_SUPPORTED_ACTIVATION_METHODS = ['autodiscovery', 'autoactivate']
_SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
- def __init__(self, pon_index, port_no, parent, label=None):
+ def __init__(self, pon_index, port_no, parent):
# TODO: Weed out those properties supported by common 'Port' object (future)
self.log = structlog.get_logger(device_id=parent.device_id, pon_id=pon_index)
@@ -61,9 +61,9 @@
self._pon_id = pon_index
self._port_no = port_no
self._name = 'xpon 0/{}'.format(pon_index+1)
- self._label = label or 'PON-{}'.format(pon_index)
+ self._label = 'pon-{}'.format(pon_index)
self._port = None
- self._no_onu_discover_tick = 5.0 # TODO: Decrease to 1 or 2 later
+ self._no_onu_discover_tick = 5.0
self._discovery_tick = 20.0
self._discovered_onus = [] # List of serial numbers
self._sync_tick = 20.0
@@ -140,6 +140,7 @@
@xpon_name.setter
def xpon_name(self, value):
+ assert '/' not in value, "xPON names cannot have embedded forward slashes '/'"
self._xpon_name = value
@property
@@ -728,6 +729,9 @@
self._active_los_alarms.add(onu_id)
los_alarm(True, onu_id)
+ # TODO: A method to update the AdapterAgent's child device state (operStatus)
+ # would be useful here
+
def _process_status_onu_discovered_list(self, discovered_onus):
"""
Look for new ONUs
@@ -879,18 +883,24 @@
:param onu:
:return:
"""
- olt = self.olt
- adapter = self.adapter_agent
- channel_id = onu.onu_vid
+ # Only call older 'child_device_detected' if not using xPON to configure the system
- proxy = Device.ProxyAddress(device_id=olt.device_id, channel_id=channel_id)
+ if self.activation_method == "autoactivate":
+ olt = self.olt
+ adapter = self.adapter_agent
+ channel_id = onu.onu_vid
- adapter.child_device_detected(parent_device_id=olt.device_id,
- parent_port_no=self._port_no,
- child_device_type=onu.vendor_id,
- proxy_address=proxy,
- admin_state=AdminState.ENABLED,
- vlan=channel_id)
+ proxy = Device.ProxyAddress(device_id=olt.device_id,
+ channel_id=channel_id,
+ onu_id=onu.onu_id,
+ onu_session_id=onu.onu_id)
+
+ adapter.child_device_detected(parent_device_id=olt.device_id,
+ parent_port_no=self._port_no,
+ child_device_type=onu.vendor_id,
+ proxy_address=proxy,
+ admin_state=AdminState.ENABLED,
+ vlan=channel_id)
def get_next_onu_id(self):
used_ids = [onu.onu_id for onu in self._onus.itervalues()]