[ 6322 ] Update the code to only accept a MAC address as a datapath id (DPID). If
one is provided and it is already assigned to a logical device then an exception
will be raised.
VOL-500 : Allow adapters to set the datapath id using the MAC address of the OLT device. The logical device id will use this datapath id as well
Change-Id: Ib6ae48861c3a449000360469f7fb7332ff39961a
diff --git a/common/utils/id_generation.py b/common/utils/id_generation.py
index 59535b8..bb2e144 100644
--- a/common/utils/id_generation.py
+++ b/common/utils/id_generation.py
@@ -35,16 +35,17 @@
def create_cluster_logical_device_ids(core_id, switch_id):
"""
Creates a logical device id and an OpenFlow datapath id that is unique
- across the Voltha cluster. Both ids represents a 64 bits integer where
- the lower 48 bits represents the switch id and the upper 16 bits
- represents the core id.
+ across the Voltha cluster.
+ The returned ids represents a 64 bits integer where the lower 48 bits is
+ the switch id and the upper 16 bits is the core id.
:param core_id: string
+ :param switch_id:int
:return: cluster logical device id and OpenFlow datapath id
"""
switch_id = format(switch_id, '012x')
- id = '{}{}'.format(format(int(core_id), '04x'), switch_id)
- hex_int = int(id, 16)
- return id, hex_int
+ core_in_hex=format(int(core_id, 16), '04x')
+ id = '{}{}'.format(core_in_hex[-4:], switch_id[-12:])
+ return id, int(id, 16)
def is_broadcast_core_id(id):
assert id and len(id) == 16
diff --git a/docker/config/netcfg.json b/docker/config/netcfg.json
index 245c263..244caec 100644
--- a/docker/config/netcfg.json
+++ b/docker/config/netcfg.json
@@ -31,7 +31,7 @@
}
},
"devices": {
- "of:0001000000000001": {
+ "of:0001aabbccddeeff": {
"basic": {
"driver": "pmc-olt"
},
diff --git a/voltha/adapters/ponsim_olt/ponsim_olt.py b/voltha/adapters/ponsim_olt/ponsim_olt.py
index d7a75eb..bb5b533 100644
--- a/voltha/adapters/ponsim_olt/ponsim_olt.py
+++ b/voltha/adapters/ponsim_olt/ponsim_olt.py
@@ -432,7 +432,8 @@
))
ld = LogicalDevice(
- # not setting id and datapth_id will let the adapter agent pick id
+ # not setting id and datapath_id. Adapter agent will pick the id
+ # and will pick the datapath_id is it is not provided
desc=ofp_desc(
mfr_desc='cord porject',
hw_desc='simualted pon',
@@ -452,7 +453,9 @@
),
root_device_id=device.id
)
- ld_initialized = self.adapter_agent.create_logical_device(ld)
+ mac_address = "AA:BB:CC:DD:EE:FF"
+ ld_initialized = self.adapter_agent.create_logical_device(ld,
+ dpid=mac_address)
cap = OFPPF_1GB_FD | OFPPF_FIBER
self.ofp_port_no = info.nni_port
self.adapter_agent.add_logical_port(ld_initialized.id, LogicalPort(
@@ -751,7 +754,9 @@
),
root_device_id=device.id
)
- ld_initialized = self.adapter_agent.create_logical_device(ld)
+ mac_address = "AA:BB:CC:DD:EE:FF"
+ ld_initialized = self.adapter_agent.create_logical_device(ld,
+ dpid=mac_address)
cap = OFPPF_1GB_FD | OFPPF_FIBER
self.adapter_agent.add_logical_port(ld_initialized.id, LogicalPort(
id='nni',
diff --git a/voltha/core/adapter_agent.py b/voltha/core/adapter_agent.py
index 2f73505..5c2327d 100644
--- a/voltha/core/adapter_agent.py
+++ b/voltha/core/adapter_agent.py
@@ -40,6 +40,12 @@
LogicalPort, AdminState, OperStatus, AlarmFilterRuleKey
from voltha.registry import registry
from common.utils.id_generation import create_cluster_device_id
+import re
+
+
+class MacAddressError(BaseException):
+ def __init__(self, error):
+ self.error = error
@implementer(IAdapterAgent)
class AdapterAgent(object):
@@ -496,17 +502,36 @@
self._make_up_to_date('/devices/{}/ports'.format(device_id),
port.port_no, port)
- def _find_first_available_id(self):
+ def _find_first_available_id(self, dpid=None):
+
+ def _is_valid_mac_address(dpid):
+ return re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$",
+ dpid)
+
+ # If a dpid is provided then validate whether it is a MAC address
+ switch_id = 1
+ if dpid:
+ dpid = dpid.lower()
+ if not _is_valid_mac_address(dpid):
+ raise MacAddressError('Invalid-mac-address-format')
+ switch_id = int(dpid.replace(':', ''), 16)
+
logical_devices = self.root_proxy.get('/logical_devices')
existing_ids = set(ld.id for ld in logical_devices)
existing_datapath_ids = set(ld.datapath_id for ld in logical_devices)
core_id = registry('core').core_store_id
- i = 1
+
while True:
- ld_id, dp_id = create_cluster_logical_device_ids(core_id, i)
- if dp_id not in existing_datapath_ids and ld_id not in existing_ids:
+ ld_id, dp_id = create_cluster_logical_device_ids(core_id, switch_id)
+ existing_ids = dp_id in existing_datapath_ids or ld_id in \
+ existing_ids
+ if not existing_ids:
return ld_id, dp_id
- i += 1
+ else:
+ if dpid:
+ raise MacAddressError('Already-registered-mac-address')
+ else:
+ switch_id += 1
def get_logical_device(self, logical_device_id):
return self.root_proxy.get('/logical_devices/{}'.format(
@@ -516,11 +541,18 @@
return self.root_proxy.get('/logical_devices/{}/ports/{}'.format(
logical_device_id, port_id))
- def create_logical_device(self, logical_device):
+ def create_logical_device(self, logical_device, dpid=None):
+ """
+ Allow the adapters to provide their own datapath id. This must
+ be the OLT MAC address.
+ :param logical_device:
+ :param dpid: OLT MAC address
+ :return: updated logical device
+ """
assert isinstance(logical_device, LogicalDevice)
if not logical_device.id:
- ld_id, dp_id = self._find_first_available_id()
+ ld_id, dp_id = self._find_first_available_id(dpid)
logical_device.id = ld_id
logical_device.datapath_id = dp_id