summaryrefslogtreecommitdiff
path: root/python/vyos
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-04-23 20:44:44 +0200
committerGitHub <noreply@github.com>2020-04-23 20:44:44 +0200
commita18d92b2205bd647691c39fde925d05d8d83fa1e (patch)
tree94a358538b8985e9a30ed138c789aac171d7dbb5 /python/vyos
parentaf9f033fd19c0c927a2c1555347811bee1a8a964 (diff)
parent2d1dddd1b381676743dc602a321f2fd3146adc08 (diff)
downloadvyos-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.py21
-rw-r--r--python/vyos/ifconfig/interface.py41
-rw-r--r--python/vyos/ifconfig_vlan.py8
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')