avd
avd copied to clipboard
Feat(eos_designs): Support for PTP configuration based on best practices
Change Summary
PTP
Arista best practices are utilised, simplifying configuration of several global and interface-specific PTP settings:
- PTP is enabled on a node_group or node-specific level and only then will the global PTP settings take effect:
-
PTP mode boundary is used by default.
-
You can apply one of three different PTP profiles globally as well as for connected endpoints:
-
AES67
-
SMPTE2059-2
-
AES67-R16-2016 (used by default)
The profile will apply PTP parameters for all relevant interfaces which are:
- All links between leaf and spine switches
- Individual PTP-enabled links for connected endpoints
-
-
By default all links between leaf and spine switches participates in the Best Master Clock Algorithm (BMCA).
-
By default all interfaces used for endpoints use
ptp role master
, unless you specify that they should also participate in the BMCA. -
PTP Priorities are automatically set based on the node_type and switch_id.
-
PTP Clock Identity is automatically set based on a prefix (00:00:00 by default) + PTP priority1 and PTP priority2.
-
Component(s) name
arista.avd.eos_designs
Proposed changes
Addition to avd/plugins/module_utils/eos_designs_facts.py:
@cached_property
def default_ptp_priority1(self):
"""
switch.default_ptp_priority1 set based on
node_type_keys.<node_type_key>.default_ptp_priority1
"""
return get(self._node_type_key_data, "default_ptp_priority1", default=127)
@cached_property
def ptp(self):
'''
Generates PTP config on node level as well as for interfaces, using various defaults.
- The following are set in roles/eos_designs/defaults/main/default-node-type-keys.yml
default_node_type_keys:
"l3ls-evpn":
spine:
default_ptp_priority1: 20
l3leaf:
default_ptp_priority1: 30
PTP priority2 is set in the code below, calculated based on the node id:
default_priority2 = self.id % 256
'''
# Set defaults
default_ptp_enabled = get(self._hostvars, "ptp.enabled")
default_ptp_domain = get(self._hostvars, "ptp.domain", default=127)
default_ptp_profile = get(self._hostvars, "ptp.profile", default="aes67-r16-2016")
ptp = {}
ptp["enabled"] = get(self._switch_data_combined, "ptp.enabled", default=default_ptp_enabled)
if ptp["enabled"] is True:
auto_clock_identity = get(self._switch_data_combined, "ptp.auto_clock_identity", default=True)
priority1 = get(self._switch_data_combined, "ptp.priority1", default=self.default_ptp_priority1)
default_priority2 = self.id % 256
priority2 = get(self._switch_data_combined, "ptp.priority2", default=default_priority2)
if auto_clock_identity is True:
clock_identity_prefix = get(self._switch_data_combined, "ptp.clock_identity_prefix", default="00:00:00")
default_clock_identity = f"{clock_identity_prefix}:{priority1:02x}:00:{priority2:02x}"
ptp["device_config"] = {
"mode": get(self._switch_data_combined, "ptp.mode", default="boundary"),
"forward_unicast": get(self._switch_data_combined, "ptp.forward_unicast"),
"auto_clock_identity": auto_clock_identity,
"clock_identity_prefix": clock_identity_prefix,
"clock_identity": get(self._switch_data_combined, "ptp.clock_identity", default=default_clock_identity),
"source": {
"ip": get(self._switch_data_combined, "ptp.source.ip")
},
"priority1": priority1,
"priority2": priority2,
"ttl": get(self._switch_data_combined, "ptp.ttl"),
"domain": get(self._switch_data_combined, "ptp.domain", default=default_ptp_domain),
"message_type": {
"general": {
"dscp": get(self._switch_data_combined, "ptp.dscp.general_messages"),
},
"event": {
"dscp": get(self._switch_data_combined, "ptp.dscp.event_messages"),
},
},
"monitor": {
"enabled": get(self._switch_data_combined, "ptp.monitor.enabled", default=True),
"threshold": {
"offset_from_master": get(self._switch_data_combined, "ptp.monitor.threshold.offset_from_master", default=250),
"mean_path_delay": get(self._switch_data_combined, "ptp.monitor.threshold.mean_path_delay", default=1500),
"drop": {
"offset_from_master": get(self._switch_data_combined, "ptp.monitor.threshold.drop.offset_from_master"),
"mean_path_delay": get(self._switch_data_combined, "ptp.monitor.threshold.drop.mean_path_delay"),
},
},
"missing_message": {
"intervals": {
"announce": get(self._switch_data_combined, "ptp.monitor.missing_message.intervals.announce"),
"follow_up": get(self._switch_data_combined, "ptp.monitor.missing_message.intervals.follow_up"),
"sync": get(self._switch_data_combined, "ptp.monitor.missing_message.intervals.sync"),
},
"sequence_ids": {
"enabled": get(self._switch_data_combined, "ptp.monitor.missing_message.sequence_ids.enabled", default=True),
"announce": get(self._switch_data_combined, "ptp.monitor.missing_message.sequence_ids.announce", default=3),
"delay_resp": get(self._switch_data_combined, "ptp.monitor.missing_message.sequence_ids.delay_resp", default=3),
"follow_up": get(self._switch_data_combined, "ptp.monitor.missing_message.sequence_ids.follow_up", default=3),
"sync": get(self._switch_data_combined, "ptp.monitor.missing_message.sequence_ids.sync", default=3),
},
},
},
}
ptp["profile"] = get(self._switch_data_combined, "ptp.profile", default_ptp_profile)
if ptp["profile"] == "aes67-r16-2016":
ptp["interface_config"] = {
"enable": True,
"announce": {
"interval": 0,
"timeout": 3,
},
"delay_req": -3,
"sync_message": {
"interval": -3,
},
"transport": "ipv4",
}
elif ptp["profile"] == "smpte2059-2":
ptp["interface_config"] = {
"enable": True,
"announce": {
"interval": -1,
"timeout": 3,
},
"delay_req": -4,
"sync_message": {
"interval": -4,
},
"transport": "ipv4",
}
elif ptp["profile"] == "aes67":
ptp["interface_config"] = {
"enable": True,
"announce": {
"interval": 2,
"timeout": 3,
},
"delay_req": 0,
"sync_message": {
"interval": 0,
},
"transport": "ipv4",
}
return ptp
return None
Addition to defaults/main/default-node-type-keys.yml, defining defaults based on node type:
default_node_type_keys:
"l3ls-evpn":
spine:
default_ptp_priority1: 20
l3leaf:
default_ptp_priority1: 30
Addition to eos_designs/doc/node-types.md (documentation of change described above)
Added eos_designs/doc/ptp.md (documentation of how to use all this)
Addition to avd/molecule/eos_designs_unit_tests/inventory/group_vars:
- PTP_TESTS.yml
- PTP_TESTS_SPINES.yml
- PTP_TESTS_LEAFS.yml
Addition to avd/molecule/eos_designs_unit_tests/inventory/hosts.yml:
PTP_TESTS:
children:
PTP_TESTS_SPINES:
hosts:
ptp-tests-spine1:
ptp-tests-spine2:
PTP_TESTS_LEAFS:
hosts:
ptp-tests-leaf1:
ptp-tests-leaf2:
How to test
molecule converge --scenario-name eos_designs_unit_tests --
Checklist
User Checklist
- N/A
Repository Checklist
- [x] My code has been rebased from devel before I start
- [x] I have read the CONTRIBUTING document.
- [x] My change requires a change to the documentation and documentation have been updated accordingly.
- [x] I have updated molecule CI testing accordingly. (check the box if not applicable)
Please add another commit, when someone comments or suggests. With only 1 commit, both the PR commit message and the actual commit message should be same.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.