From e6666353c41de8ad675d4157cdbe848a42ba6385 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 21 Aug 2021 20:57:17 +0200 Subject: vyos.ifconfig: provide generic get_mac_synthetic() method WireGuard, Tunnel and also PPPoE all need a ways to calculate a synthetic MAC address used for the EUI64 link-local addresses. Instead of copying the code from Tunnel to WireGuard to PPPoE, use a generic implementation. (cherry picked from commit b7d30137b17da49ed5099d4d96659b363fc7bcc9) --- python/vyos/ifconfig/interface.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 9c02af68f..e815c0129 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -52,6 +52,10 @@ from vyos.ifconfig.vrrp import VRRP from vyos.ifconfig.operational import Operational from vyos.ifconfig import Section +from netaddr import EUI +from netaddr import mac_unix_expanded +from random import getrandbits + class Interface(Control): # This is the class which will be used to create # self.operational, it allows subclasses, such as @@ -367,6 +371,31 @@ class Interface(Control): """ return self.get_interface('mac') + def get_mac_synthetic(self): + """ + Get a synthetic MAC address. This is a common method which can be called + from derived classes to overwrite the get_mac() call in a generic way. + + NOTE: Tunnel interfaces have no "MAC" address by default. The content + of the 'address' file in /sys/class/net/device contains the + local-ip thus we generate a random MAC address instead + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('eth0').get_mac() + '00:50:ab:cd:ef:00' + """ + # we choose 40 random bytes for the MAC address, this gives + # us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A') + tmp = EUI(getrandbits(48)).value + # set locally administered bit in MAC address + tmp |= 0xf20000000000 + # convert integer to "real" MAC address representation + mac = EUI(hex(tmp).split('x')[-1]) + # change dialect to use : as delimiter instead of - + mac.dialect = mac_unix_expanded + return str(mac) + def set_mac(self, mac): """ Set interface MAC (Media Access Contrl) address to given value. -- cgit v1.2.3 From 0de23064b9d575ce0569839e3b4453a0c2e9dc1c Mon Sep 17 00:00:00 2001 From: Viacheslav Date: Sun, 29 Aug 2021 11:12:01 +0000 Subject: interfaces: T3777: Does not delete empty eui64 address Check eui64_old value before deleting It can be empty or not ipv6 address. --- python/vyos/ifconfig/interface.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index e815c0129..d47403488 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -38,6 +38,7 @@ from vyos.util import dict_search from vyos.util import read_file from vyos.util import get_interface_config from vyos.template import is_ipv4 +from vyos.template import is_ipv6 from vyos.validate import is_intf_addr_assigned from vyos.validate import is_ipv6_link_local from vyos.validate import assert_boolean @@ -588,9 +589,10 @@ class Interface(Control): Delete the address based on the interface's MAC-based EUI64 combined with the prefix address. """ - eui64 = mac2eui64(self.get_mac(), prefix) - prefixlen = prefix.split('/')[1] - self.del_addr(f'{eui64}/{prefixlen}') + if is_ipv6(prefix): + eui64 = mac2eui64(self.get_mac(), prefix) + prefixlen = prefix.split('/')[1] + self.del_addr(f'{eui64}/{prefixlen}') def set_ipv6_forwarding(self, forwarding): """ -- cgit v1.2.3 From 4281fb32ebba0f1e0c76bf1f21eea7defe65a1a9 Mon Sep 17 00:00:00 2001 From: Viacheslav Date: Tue, 31 Aug 2021 08:32:49 +0000 Subject: interface: T3782: Fix unexpected delete qdisc rule Some tc qdisc rules are generated by old perl code It prevent to unexpected override this code by python. --- python/vyos/ifconfig/interface.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index d47403488..c53bb964a 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1079,12 +1079,14 @@ class Interface(Control): source_if = next(iter(self._config['is_mirror_intf'])) config = self._config['is_mirror_intf'][source_if].get('mirror', None) - # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 - # Remove existing mirroring rules - delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' - delete_tc_cmd += f'tc qdisc del dev {source_if} handle 1: root prio 2> /dev/null;' - delete_tc_cmd += 'set $?=0' - self._popen(delete_tc_cmd) + # Check configuration stored by old perl code before delete T3782 + if not 'redirect' in self._config: + # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 + # Remove existing mirroring rules + delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' + delete_tc_cmd += f'tc qdisc del dev {source_if} handle 1: root prio 2> /dev/null;' + delete_tc_cmd += 'set $?=0' + self._popen(delete_tc_cmd) # Bail out early if nothing needs to be configured if not config: -- cgit v1.2.3 From 3efe74df68ea2d797155a1371cb0b321f5437f25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 19 Sep 2021 21:41:56 +0200 Subject: vyos.ifconfig: T2738: add delta check when changing interface parameters There is no need to alter interface parameters if they have not changed at all. (cherry picked from commit b4c58c5aefaca4fce817b58327b9c7c3e8145d6d) --- python/vyos/ifconfig/interface.py | 122 +++++++++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 9 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index c53bb964a..9a3419353 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -37,6 +37,7 @@ from vyos.util import mac2eui64 from vyos.util import dict_search from vyos.util import read_file from vyos.util import get_interface_config +from vyos.util import is_systemd_service_active from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.validate import is_intf_addr_assigned @@ -108,6 +109,10 @@ class Interface(Control): 'shellcmd': 'ip -json -detail link list dev {ifname}', 'format': lambda j: jmespath.search('[*].operstate | [0]', json.loads(j)), }, + 'vrf': { + 'shellcmd': 'ip -json -detail link list dev {ifname}', + 'format': lambda j: jmespath.search('[*].master | [0]', json.loads(j)), + }, } _command_set = { @@ -139,7 +144,6 @@ class Interface(Control): _sysfs_set = { 'arp_cache_tmo': { - 'convert': lambda tmo: (int(tmo) * 1000), 'location': '/proc/sys/net/ipv4/neigh/{ifname}/base_reachable_time_ms', }, 'arp_filter': { @@ -209,6 +213,51 @@ class Interface(Control): }, } + _sysfs_get = { + 'arp_cache_tmo': { + 'location': '/proc/sys/net/ipv4/neigh/{ifname}/base_reachable_time_ms', + }, + 'arp_filter': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/arp_filter', + }, + 'arp_accept': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/arp_accept', + }, + 'arp_announce': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/arp_announce', + }, + 'arp_ignore': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/arp_ignore', + }, + 'ipv4_forwarding': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/forwarding', + }, + 'rp_filter': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/rp_filter', + }, + 'ipv6_accept_ra': { + 'location': '/proc/sys/net/ipv6/conf/{ifname}/accept_ra', + }, + 'ipv6_autoconf': { + 'location': '/proc/sys/net/ipv6/conf/{ifname}/autoconf', + }, + 'ipv6_forwarding': { + 'location': '/proc/sys/net/ipv6/conf/{ifname}/forwarding', + }, + 'ipv6_dad_transmits': { + 'location': '/proc/sys/net/ipv6/conf/{ifname}/dad_transmits', + }, + 'proxy_arp': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/proxy_arp', + }, + 'proxy_arp_pvlan': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/proxy_arp_pvlan', + }, + 'link_detect': { + 'location': '/proc/sys/net/ipv4/conf/{ifname}/link_filter', + }, + } + @classmethod def exists(cls, ifname): return os.path.exists(f'/sys/class/net/{ifname}') @@ -359,6 +408,9 @@ class Interface(Control): >>> Interface('eth0').get_mtu() '1400' """ + tmp = self.get_interface('mtu') + if str(tmp) == mtu: + return None return self.set_interface('mtu', mtu) def get_mac(self): @@ -421,7 +473,7 @@ class Interface(Control): if prev_state == 'up': self.set_admin_state('up') - def set_vrf(self, vrf=''): + def set_vrf(self, vrf): """ Add/Remove interface from given VRF instance. @@ -430,6 +482,11 @@ class Interface(Control): >>> Interface('eth0').set_vrf('foo') >>> Interface('eth0').set_vrf() """ + + tmp = self.get_interface('vrf') + if tmp == vrf: + return None + self.set_interface('vrf', vrf) def set_arp_cache_tmo(self, tmo): @@ -441,6 +498,10 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_arp_cache_tmo(40) """ + tmo = str(int(tmo) * 1000) + tmp = self.get_interface('arp_cache_tmo') + if tmp == tmo: + return None return self.set_interface('arp_cache_tmo', tmo) def set_arp_filter(self, arp_filter): @@ -461,6 +522,9 @@ class Interface(Control): particular interfaces. Only for more complex setups like load- balancing, does this behaviour cause problems. """ + tmp = self.get_interface('arp_filter') + if tmp == arp_filter: + return None return self.set_interface('arp_filter', arp_filter) def set_arp_accept(self, arp_accept): @@ -477,6 +541,9 @@ class Interface(Control): gratuitous arp frame, the arp table will be updated regardless if this setting is on or off. """ + tmp = self.get_interface('arp_accept') + if tmp == arp_accept: + return None return self.set_interface('arp_accept', arp_accept) def set_arp_announce(self, arp_announce): @@ -498,6 +565,9 @@ class Interface(Control): receiving answer from the resolved target while decreasing the level announces more valid sender's information. """ + tmp = self.get_interface('arp_announce') + if tmp == arp_announce: + return None return self.set_interface('arp_announce', arp_announce) def set_arp_ignore(self, arp_ignore): @@ -510,12 +580,16 @@ class Interface(Control): 1 - reply only if the target IP address is local address configured on the incoming interface """ + tmp = self.get_interface('arp_ignore') + if tmp == arp_ignore: + return None return self.set_interface('arp_ignore', arp_ignore) def set_ipv4_forwarding(self, forwarding): - """ - Configure IPv4 forwarding. - """ + """ Configure IPv4 forwarding. """ + tmp = self.get_interface('ipv4_forwarding') + if tmp == forwarding: + return None return self.set_interface('ipv4_forwarding', forwarding) def set_ipv4_source_validation(self, value): @@ -544,6 +618,9 @@ class Interface(Control): print(f'WARNING: Global source-validation is set to "{global_setting}\n"' \ 'this overrides per interface setting!') + tmp = self.get_interface('rp_filter') + if int(tmp) == value: + return None return self.set_interface('rp_filter', value) def set_ipv6_accept_ra(self, accept_ra): @@ -559,6 +636,9 @@ class Interface(Control): 2 - Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled. """ + tmp = self.get_interface('ipv6_accept_ra') + if tmp == accept_ra: + return None return self.set_interface('ipv6_accept_ra', accept_ra) def set_ipv6_autoconf(self, autoconf): @@ -566,6 +646,9 @@ class Interface(Control): Autoconfigure addresses using Prefix Information in Router Advertisements. """ + tmp = self.get_interface('ipv6_autoconf') + if tmp == autoconf: + return None return self.set_interface('ipv6_autoconf', autoconf) def add_ipv6_eui64_address(self, prefix): @@ -619,6 +702,9 @@ class Interface(Control): 3. Router Advertisements are ignored unless accept_ra is 2. 4. Redirects are ignored. """ + tmp = self.get_interface('ipv6_forwarding') + if tmp == forwarding: + return None return self.set_interface('ipv6_forwarding', forwarding) def set_ipv6_dad_messages(self, dad): @@ -626,6 +712,9 @@ class Interface(Control): The amount of Duplicate Address Detection probes to send. Default: 1 """ + tmp = self.get_interface('ipv6_dad_transmits') + if tmp == dad: + return None return self.set_interface('ipv6_dad_transmits', dad) def set_link_detect(self, link_filter): @@ -648,6 +737,9 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_link_detect(1) """ + tmp = self.get_interface('link_detect') + if tmp == link_filter: + return None return self.set_interface('link_detect', link_filter) def get_alias(self): @@ -672,6 +764,9 @@ class Interface(Control): >>> Interface('eth0').set_ifalias('') """ + tmp = self.get_interface('alias') + if tmp == ifalias: + return None self.set_interface('alias', ifalias) def get_admin_state(self): @@ -747,6 +842,9 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_proxy_arp(1) """ + tmp = self.get_interface('proxy_arp') + if tmp == enable: + return None self.set_interface('proxy_arp', enable) def set_proxy_arp_pvlan(self, enable): @@ -773,6 +871,9 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_proxy_arp_pvlan(1) """ + tmp = self.get_interface('proxy_arp_pvlan') + if tmp == enable: + return None self.set_interface('proxy_arp_pvlan', enable) def get_addr_v4(self): @@ -1015,7 +1116,9 @@ class Interface(Control): lease_file = f'{config_base}_{ifname}.leases' # Stop client with old config files to get the right IF_METRIC. - self._cmd(f'systemctl stop dhclient@{ifname}.service') + systemd_service = f'dhclient@{ifname}.service' + if is_systemd_service_active(systemd_service): + self._cmd(f'systemctl stop {systemd_service}') if enable and 'disable' not in self._config: if dict_search('dhcp_options.host_name', self._config) == None: @@ -1061,8 +1164,9 @@ class Interface(Control): # for interfaces which are yet not up and running. return self._popen(f'systemctl restart dhcp6c@{ifname}.service') else: - self._popen(f'systemctl stop dhcp6c@{ifname}.service') - + systemd_service = f'dhcp6c@{ifname}.service' + if is_systemd_service_active(systemd_service): + self._cmd(f'systemctl stop {systemd_service}') if os.path.isfile(config_file): os.remove(config_file) @@ -1183,7 +1287,7 @@ class Interface(Control): # unbinding will call 'ip link set dev eth0 nomaster' which will # also drop the interface out of a bridge or bond - thus this is # checked before - self.set_vrf(config.get('vrf', '')) + self.set_vrf(config.get('vrf', None)) # Configure ARP cache timeout in milliseconds - has default value tmp = dict_search('ip.arp_cache_timeout', config) -- cgit v1.2.3 From e8c6595fc477573887efcdb55ba6a286587b214b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 19 Sep 2021 22:06:02 +0200 Subject: vyos.ifconfig: T2738: do not remove OS assigned IP addresses from interface When using VRRP on any given interface and performing an action against that interface - be it even only changing the alias - will trigger a removal of the VRRP IP address. The issue is caused by: # determine IP addresses which are assigned to the interface and build a # list of addresses which are no longer in the dict so they can be removed cur_addr = self.get_addr() for addr in list_diff(cur_addr, new_addr): When the script calls into the library - we will drop all IP addresses set on the adapter but not available in the config dict. We should only remove the IP addresses marked by the CLI to be deleted! (cherry picked from commit e80d0aebd691f1a707ab534b4d1340fa0b793e01) --- python/vyos/configdict.py | 3 +++ python/vyos/ifconfig/interface.py | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 06e5faf46..73986e9af 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -375,6 +375,9 @@ def get_interface_dict(config, base, ifname=''): # XXX: T2665: blend in proper DHCPv6-PD default values dict = T2665_set_dhcpv6pd_defaults(dict) + address = leaf_node_changed(config, ['address']) + if address: dict.update({'address_old' : address}) + # Check if we are a member of a bridge device bridge = is_member(config, ifname, 'bridge') if bridge: dict.update({'is_bridge_member' : bridge}) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 9a3419353..2629729f8 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1010,6 +1010,8 @@ class Interface(Control): >>> j.get_addr() ['2001:db8::ffff/64'] """ + if not addr: + raise ValueError() # remove from interface if addr == 'dhcp': @@ -1261,16 +1263,16 @@ class Interface(Control): # determine IP addresses which are assigned to the interface and build a # list of addresses which are no longer in the dict so they can be removed - cur_addr = self.get_addr() - for addr in list_diff(cur_addr, new_addr): - # we will delete all interface specific IP addresses if they are not - # explicitly configured on the CLI - if is_ipv6_link_local(addr): - eui64 = mac2eui64(self.get_mac(), 'fe80::/64') - if addr != f'{eui64}/64': + if 'address_old' in config: + for addr in list_diff(config['address_old'], new_addr): + # we will delete all interface specific IP addresses if they are not + # explicitly configured on the CLI + if is_ipv6_link_local(addr): + eui64 = mac2eui64(self.get_mac(), 'fe80::/64') + if addr != f'{eui64}/64': + self.del_addr(addr) + else: self.del_addr(addr) - else: - self.del_addr(addr) for addr in new_addr: self.add_addr(addr) -- cgit v1.2.3 From c330504ceda582daca8c4982e0cf8adfb556f15d Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 20 Sep 2021 21:50:56 +0200 Subject: vyos.ifconfig: get_mac_synthetic() must generate a stable "MAC" Commit b7d30137b1 ("vyos.ifconfig: provide generic get_mac_synthetic() method") provided a common helper to generate MAC addresses used by EUI64 addresses for interfaces not having a layer2 interface (WireGuard or ip tunnel). The problem is that every call to the helper always yielded a new MAC address. This becomes problematic when IPv6 link-local addresses are generated and modified on the interface as multiple link-local (fe80::/64) addresses can easily be added to the interface leaving ... a mess. This commit changes the way how the "synthetic" MAC is generated, we generate a UUID which is stable as it is based on the interface name. We take out the last 48 bits of the UUID and form the "MAC" address. (cherry picked from commit 081e23996feb60ad903caf8b0a4587f5dacc69bf) --- python/vyos/ifconfig/interface.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 2629729f8..de46d3d66 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -27,6 +27,8 @@ from netifaces import ifaddresses # this is not the same as socket.AF_INET/INET6 from netifaces import AF_INET from netifaces import AF_INET6 +from uuid import uuid3 +from uuid import NAMESPACE_DNS from vyos import ConfigError from vyos.configdict import list_diff @@ -56,7 +58,6 @@ from vyos.ifconfig import Section from netaddr import EUI from netaddr import mac_unix_expanded -from random import getrandbits class Interface(Control): # This is the class which will be used to create @@ -438,9 +439,14 @@ class Interface(Control): >>> Interface('eth0').get_mac() '00:50:ab:cd:ef:00' """ - # we choose 40 random bytes for the MAC address, this gives - # us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A') - tmp = EUI(getrandbits(48)).value + # calculate a UUID based on the interface name - this is as predictable + # as an interface MAC address and thus can be used in the same way + tmp = uuid3(NAMESPACE_DNS, self.ifname) + # take the last 48 bits from the UUID string + tmp = str(tmp).split('-')[-1] + # Convert pseudo random string into EUI format which now represents a + # MAC address + tmp = EUI(tmp).value # set locally administered bit in MAC address tmp |= 0xf20000000000 # convert integer to "real" MAC address representation -- cgit v1.2.3 From a6c5874445eba0eae5cb89a95358f4c6c74b7f79 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 20 Sep 2021 21:55:43 +0200 Subject: ifconfig: T2104: cleanup IPv6 EUI-64 handling in update() (cherry picked from commit 3f6ae12908f54222f2f79a87bed51f71e2fbac87) --- python/vyos/ifconfig/interface.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index de46d3d66..89a562cf6 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1369,16 +1369,11 @@ class Interface(Control): self.set_mtu(config.get('mtu')) # Delete old IPv6 EUI64 addresses before changing MAC - tmp = dict_search('ipv6.address.eui64_old', config) - if tmp: - for addr in tmp: - self.del_ipv6_eui64_address(addr) + for addr in (dict_search('ipv6.address.eui64_old', config) or []): + self.del_ipv6_eui64_address(addr) # Manage IPv6 link-local addresses - tmp = dict_search('ipv6.address.no_default_link_local', config) - # we must check explicitly for None type as if the key is set we will - # get an empty dict () - if isinstance(tmp, dict): + if dict_search('ipv6.address.no_default_link_local', config) != None: self.del_ipv6_eui64_address('fe80::/64') else: self.add_ipv6_eui64_address('fe80::/64') -- cgit v1.2.3 From 823b03417aa6ac717e785b741541e251c0d4125f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Sep 2021 08:55:36 +0200 Subject: vyos.ifconfig: dhcp: T3300: always re-start dhcp client instead of start Commit dd2eb5e5686655 ("dhcp: T3300: add DHCP default route distance") changed the logic on how the DHCP process is going to be started. The systemd unit was always "started" even if it was already running. It should rather be re-started to track changes in e.g. the DHCP hostname setting. (cherry picked from commit 8ba8f0e097527e3aaaf8b395bfc07cce47e2c788) --- python/vyos/ifconfig/interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 89a562cf6..1098df7fd 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1146,7 +1146,7 @@ class Interface(Control): # 'up' check is mandatory b/c even if the interface is A/D, as soon as # the DHCP client is started the interface will be placed in u/u state. # This is not what we intended to do when disabling an interface. - return self._cmd(f'systemctl start dhclient@{ifname}.service') + return self._cmd(f'systemctl restart {systemd_service}') else: # cleanup old config files for file in [config_file, options_file, pid_file, lease_file]: -- cgit v1.2.3 From b34b8a8fe3bc4a4a706c22af4a7ef4ea8a75e14b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Sep 2021 08:55:50 +0200 Subject: vyos.ifconfig: dhcpv6: re-use systemd_service definition variable (cherry picked from commit d1c58addd881e06b389799a9c14d8ebf5d03c567) --- python/vyos/ifconfig/interface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 1098df7fd..76f1e158a 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1163,16 +1163,16 @@ class Interface(Control): ifname = self.ifname config_file = f'/run/dhcp6c/dhcp6c.{ifname}.conf' + systemd_service = f'dhcp6c@{ifname}.service' if enable and 'disable' not in self._config: render(config_file, 'dhcp-client/ipv6.tmpl', self._config) - # We must ignore any return codes. This is required to enable DHCPv6-PD - # for interfaces which are yet not up and running. - return self._popen(f'systemctl restart dhcp6c@{ifname}.service') + # We must ignore any return codes. This is required to enable + # DHCPv6-PD for interfaces which are yet not up and running. + return self._popen(f'systemctl restart {systemd_service}') else: - systemd_service = f'dhcp6c@{ifname}.service' if is_systemd_service_active(systemd_service): self._cmd(f'systemctl stop {systemd_service}') if os.path.isfile(config_file): -- cgit v1.2.3 From e4812d266ea841f8baf5ad6c7cfae1c7eba664b6 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 26 Sep 2021 12:28:37 +0200 Subject: vyos.ifconfig: T3860: bugfix in get_mac_synthetic() Commit 081e23996f (vyos.ifconfig: get_mac_synthetic() must generate a stable "MAC") calculated a "stable" synthetic MAC address per the interface based on UUID and the interface name. The problem is that this calculation is too stable when run on multiple instances of VyOS on different hosts/hypervisors. Having R1 and R2 setup a connection both via "tun10" interface will become the same "synthetic" MAC address manifesting in the same link-local IPv6 address. This e.g. breaks OSPFv3 badly as both neighbors communicate using the same link-local address. As workaround one can: set interfaces tunnel tun1337 address 'fe80::1:1337/64' set interfaces tunnel tun1337 ipv6 address no-default-link-local This commit changes the way in how the synthetic MAC address is generated. It's based on the first 48 bits of a sha256 sum build from a CPU ID retrieved via DMI, the MAC address of eth0 and the interface name as used before. This should add enough entropy to get a stable pseudo MAC address. (cherry picked from commit 8d6861290f39298701b0a89bd358545763cee14b) --- python/vyos/ifconfig/interface.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 76f1e158a..709c70b65 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -27,8 +27,6 @@ from netifaces import ifaddresses # this is not the same as socket.AF_INET/INET6 from netifaces import AF_INET from netifaces import AF_INET6 -from uuid import uuid3 -from uuid import NAMESPACE_DNS from vyos import ConfigError from vyos.configdict import list_diff @@ -439,11 +437,22 @@ class Interface(Control): >>> Interface('eth0').get_mac() '00:50:ab:cd:ef:00' """ - # calculate a UUID based on the interface name - this is as predictable - # as an interface MAC address and thus can be used in the same way - tmp = uuid3(NAMESPACE_DNS, self.ifname) - # take the last 48 bits from the UUID string - tmp = str(tmp).split('-')[-1] + from hashlib import sha256 + + # Get processor ID number + cpu_id = self._cmd('sudo dmidecode -t 4 | grep ID | head -n1 | sed "s/.*ID://;s/ //g"') + # Get system eth0 base MAC address - every system has eth0 + eth0_mac = Interface('eth0').get_mac() + + sha = sha256() + # Calculate SHA256 sum based on the CPU ID number, eth0 mac address and + # this interface identifier - this is as predictable as an interface + # MAC address and thus can be used in the same way + sha.update(cpu_id.encode()) + sha.update(eth0_mac.encode()) + sha.update(self.ifname.encode()) + # take the most significant 48 bits from the SHA256 string + tmp = sha.hexdigest()[:12] # Convert pseudo random string into EUI format which now represents a # MAC address tmp = EUI(tmp).value -- cgit v1.2.3 From e687502b1cf4a3e15c562a3662afcbe0776b1fe7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 2 Oct 2021 18:50:38 +0200 Subject: vyos.ifconfig: T3883: bugfix VRF deletion We can not pass None as VRF name, this raises an exception. OSError: [Errno 255] failed to run command: ip link set dev eth2 master None --- python/vyos/ifconfig/interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 709c70b65..7f712d98f 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1304,7 +1304,7 @@ class Interface(Control): # unbinding will call 'ip link set dev eth0 nomaster' which will # also drop the interface out of a bridge or bond - thus this is # checked before - self.set_vrf(config.get('vrf', None)) + self.set_vrf(config.get('vrf', '')) # Configure ARP cache timeout in milliseconds - has default value tmp = dict_search('ip.arp_cache_timeout', config) -- cgit v1.2.3 From 1786246655c36e932be649a29d70cca6c9a29773 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 9 Oct 2021 08:38:06 +0200 Subject: tunnel: T3894: fix design when building synthetic MAC addresses It seems not all systems have eth0 - get a list of all available Ethernet interfaces on the system (without VLAN subinterfaces) and then take the first one. (cherry picked from commit f19c92f255011149eeb7626a2e158456abe4c9b8) --- python/vyos/ifconfig/interface.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'python/vyos/ifconfig/interface.py') diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 7f712d98f..036ca1413 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -441,15 +441,19 @@ class Interface(Control): # Get processor ID number cpu_id = self._cmd('sudo dmidecode -t 4 | grep ID | head -n1 | sed "s/.*ID://;s/ //g"') - # Get system eth0 base MAC address - every system has eth0 - eth0_mac = Interface('eth0').get_mac() + + # XXX: T3894 - it seems not all systems have eth0 - get a list of all + # available Ethernet interfaces on the system (without VLAN subinterfaces) + # and then take the first one. + all_eth_ifs = [x for x in Section.interfaces('ethernet') if '.' not in x] + first_mac = Interface(all_eth_ifs[0]).get_mac() sha = sha256() # Calculate SHA256 sum based on the CPU ID number, eth0 mac address and # this interface identifier - this is as predictable as an interface # MAC address and thus can be used in the same way sha.update(cpu_id.encode()) - sha.update(eth0_mac.encode()) + sha.update(first_mac.encode()) sha.update(self.ifname.encode()) # take the most significant 48 bits from the SHA256 string tmp = sha.hexdigest()[:12] -- cgit v1.2.3