diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-04-23 20:44:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-23 20:44:44 +0200 |
commit | a18d92b2205bd647691c39fde925d05d8d83fa1e (patch) | |
tree | 94a358538b8985e9a30ed138c789aac171d7dbb5 /python/vyos | |
parent | af9f033fd19c0c927a2c1555347811bee1a8a964 (diff) | |
parent | 2d1dddd1b381676743dc602a321f2fd3146adc08 (diff) | |
download | vyos-1x-a18d92b2205bd647691c39fde925d05d8d83fa1e.tar.gz vyos-1x-a18d92b2205bd647691c39fde925d05d8d83fa1e.zip |
Merge pull request #371 from jjakob/ipv6-link-local-fix
interfaces: T2362: IPv6 link-local and EUI64 address fixes
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/configdict.py | 21 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 41 | ||||
-rw-r--r-- | python/vyos/ifconfig_vlan.py | 8 |
3 files changed, 44 insertions, 26 deletions
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 24fe174d2..2ce8a795f 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -125,6 +125,8 @@ def vlan_to_dict(conf): 'ip_enable_arp_ignore': 0, 'ip_proxy_arp': 0, 'ipv6_autoconf': 0, + 'ipv6_eui64_prefix': [], + 'ipv6_eui64_prefix_remove': [], 'ipv6_forwarding': 1, 'ipv6_dup_addr_detect': 1, 'ingress_qos': '', @@ -199,6 +201,22 @@ def vlan_to_dict(conf): if conf.exists('ipv6 address autoconf'): vlan['ipv6_autoconf'] = 1 + # Get prefixes for IPv6 addressing based on MAC address (EUI-64) + if conf.exists('ipv6 address eui64'): + vlan['ipv6_eui64_prefix'] = conf.return_values('ipv6 address eui64') + + # Determine currently effective EUI64 addresses - to determine which + # address is no longer valid and needs to be removed + eff_addr = conf.return_effective_values('ipv6 address eui64') + vlan['ipv6_eui64_prefix_remove'] = list_diff(eff_addr, vlan['ipv6_eui64_prefix']) + + # Remove the default link-local address if set. + if conf.exists('ipv6 address no-default-link-local'): + vlan['ipv6_eui64_prefix_remove'].append('fe80::/64') + else: + # add the link-local by default to make IPv6 work + vlan['ipv6_eui64_prefix'].append('fe80::/64') + # Disable IPv6 forwarding on this interface if conf.exists('ipv6 disable-forwarding'): vlan['ipv6_forwarding'] = 0 @@ -210,6 +228,9 @@ def vlan_to_dict(conf): # Media Access Control (MAC) address if conf.exists('mac'): vlan['mac'] = conf.return_value('mac') + # always recreate EUI64 addresses if mac is set + # I'm not sure how to check if a vlan interface exists or how to get its current mac. + vlan['ipv6_eui64_prefix_remove'] += vlan['ipv6_eui64_prefix'] # Maximum Transmission Unit (MTU) if conf.exists('mtu'): diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 62c30dbf7..a156eddd9 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1,4 +1,4 @@ -# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -419,39 +419,28 @@ class Interface(Control): """ return self.set_interface('ipv6_autoconf', autoconf) - def set_ipv6_eui64_address(self, prefix): + def add_ipv6_eui64_address(self, prefix): """ Extended Unique Identifier (EUI), as per RFC2373, allows a host to - assign iteslf a unique IPv6 address based on a given IPv6 prefix. + assign itself a unique IPv6 address based on a given IPv6 prefix. - If prefix is passed address is assigned, if prefix is '' address is - removed from interface. + Calculate the EUI64 from the interface's MAC, then assign it + with the given prefix to the interface. """ - # if prefix is an empty string convert it to None so mac2eui64 works - # as expected - if not prefix: - prefix = None eui64 = mac2eui64(self.get_mac(), prefix) + prefixlen = prefix.split('/')[1] + self.add_addr(f'{eui64}/{prefixlen}') - if not prefix: - # if prefix is empty - thus removed - we need to walk through all - # interface IPv6 addresses and find the one with the calculated - # EUI-64 identifier. The address is then removed - for addr in self.get_addr(): - addr_wo_prefix = addr.split('/')[0] - if is_ipv6(addr_wo_prefix): - if eui64 in IPv6Address(addr_wo_prefix).exploded: - self.del_addr(addr) - - return None + def del_ipv6_eui64_address(self, prefix): + """ + 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}') - # calculate and add EUI-64 IPv6 address - if IPv6Network(prefix): - # we also need to take the subnet length into account - prefix = prefix.split('/')[1] - eui64 = f'{eui64}/{prefix}' - self.add_addr(eui64 ) def set_ipv6_forwarding(self, forwarding): """ diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index 899fd17da..ee009f7f9 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -66,10 +66,18 @@ def apply_vlan_config(vlan, config): # assign/remove VRF vlan.set_vrf(config['vrf']) + # Delete old IPv6 EUI64 addresses before changing MAC + for addr in config['ipv6_eui64_prefix_remove']: + vlan.del_ipv6_eui64_address(addr) + # Change VLAN interface MAC address if config['mac']: vlan.set_mac(config['mac']) + # Add IPv6 EUI-based addresses + for addr in config['ipv6_eui64_prefix']: + vlan.add_ipv6_eui64_address(addr) + # enable/disable VLAN interface if config['disable']: vlan.set_admin_state('down') |