Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dbeee32
fix: address: purge all ips only if primary ipv4 changed
aderumier May 9, 2023
8edccd1
netlink: decode some IFLA_INET6_CONF attributes
christoph-heiss Aug 22, 2025
4e3ab5e
nlcache: add get_link_inet6_conf
aderumier Apr 26, 2023
af46590
nlcache: add Address.IFA_FLAGS and get_ip_addresses_flags() method
aderumier May 10, 2023
4dd3e46
add method auto support for inet6
aderumier Apr 11, 2025
2a4c6d9
add auto addons
aderumier Apr 11, 2025
17d08d2
address: handle auto
aderumier Apr 11, 2025
27e2f23
address: add support for accept_ra and autoconf
aderumier Apr 26, 2023
88eed5d
dhcp: remove accept_ra and autoconf
aderumier Apr 27, 2023
2995b3c
address: process addresses with static + slaac
aderumier Apr 26, 2023
991ce07
man: interfaces: add inet6 auto method
aderumier Apr 11, 2025
cc697c1
fix sysctl accept_ra/autoconf with dotted vlan interfaces
aderumier May 9, 2023
39c68bc
address: move sysctl accept_ra/autoconf code to _sysctl_config def
aderumier May 9, 2023
3a580af
address: add cache.get_link_inet6_accept_ra and autoconf
aderumier May 9, 2023
a0bb084
inet6 auto : default to accept_ra=2 like ifupdown1
aderumier May 9, 2023
059dcc2
address: skip purge dynamic ipv6 address for autoconf instead accept_ra
aderumier May 9, 2023
dc5a7d9
address: use default accept_ra|autoconf from net.ipv6.conf.all. sysctl
aderumier May 9, 2023
98ab450
update nlcache after sysctl_set accept_ra/autoconf
aderumier May 10, 2023
3d9c46d
address: fix accept_ra/autoconf sysctl on bridges
aderumier Apr 11, 2025
3fb1daf
addons: auto: drop unused imports
christoph-heiss Apr 11, 2025
ccff007
addons: {address,auto}: use f-strings where possible
christoph-heiss Apr 11, 2025
10500fd
addons: {address,auto}: Improve IPv6 auto-configuration help and doc
christoph-heiss Apr 11, 2025
b508063
make: add some more build artifacts to clean
christoph-heiss Apr 11, 2025
682ec54
gitignore: add some more build artifacts to ignore
christoph-heiss Apr 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ wheels/
.installed.cfg
*.egg
MANIFEST
.pybuild/
man/

# Debian packaging
debian/files
debian/.debhelper/
debian/*.debhelper
debian/*.substvars
debian/ifupdown2

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ clean-build: ## remove build artifacts
rm -fr build/
rm -fr dist/
rm -fr .eggs/
rm -fr .pybuild/
rm -fr man/
find . -name '*.egg-info' -exec rm -fr {} +
find . -name '*.egg' -exec rm -f {} +
rm -fr debian/files debian/.debhelper debian/ifupdown2 debian/ifupdown2.substvars
find debian -name '*.debhelper' -exec rm -f {} +

clean-pyc: ## remove Python file artifacts
find . -name '*.pyc' -exec rm -f {} +
Expand Down
2 changes: 2 additions & 0 deletions etc/network/ifupdown2/addons.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pre-up,mstpctl
pre-up,tunnel
pre-up,vrf
pre-up,ethtool
pre-up,auto
pre-up,address
up,dhcp
up,address
Expand All @@ -28,6 +29,7 @@ pre-down,usercmds
pre-down,vxrd
pre-down,dhcp
down,ppp
down,auto
down,addressvirtual
down,address
down,usercmds
Expand Down
111 changes: 98 additions & 13 deletions ifupdown2/addons/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,19 @@ class address(AddonWithIpBlackList, moduleBase):
"validvals": ['on', 'off', 'yes', 'no', '0', '1'],
"default": "no",
"aliases": ["disable-ip6"]
}
},
'accept-ra': {
'help': 'Accept IPv6 router advertisements',
'validvals': ['0', '1', '2'],
'default': '0',
'example': ['accept-ra 1']
},
'autoconf': {
'help': 'Enable IPv6 slaac autoconfiguration',
'validvals': ['0', '1'],
'default': '0',
'example': ['autoconf 1']
},
}
}

Expand Down Expand Up @@ -272,6 +284,15 @@ def __init__(self, *args, **kargs):

self.mac_regex = re.compile(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")

try:
self.default_accept_ra = str(self.sysctl_get('net.ipv6.conf.all.accept_ra'))
except Exception:
self.default_accept_ra = 1

try:
self.default_autoconf = str(self.sysctl_get('net.ipv6.conf.all.autoconf'))
except Exception:
self.default_autoconf = 1

def __policy_get_default_mtu(self):
default_mtu = policymanager.policymanager_api.get_attr_default(
Expand Down Expand Up @@ -682,21 +703,31 @@ def process_addresses(self, ifaceobj, ifaceobj_getfunc=None, force_reapply=False
if force_reapply:
self.__add_ip_addresses_with_attributes(ifaceobj, ifname, user_config_ip_addrs_list)
return

purge_dynamic_v6_addresses = True
running_autoconf = self.cache.get_link_inet6_autoconf(ifaceobj)
if running_autoconf == '1' and not squash_addr_config:
purge_dynamic_v6_addresses = False

try:
# if primary address is not same, there is no need to keep any, reset all addresses.
if ordered_user_configured_ips and running_ip_addrs and ordered_user_configured_ips[0] != running_ip_addrs[0]:
self.logger.info("%s: primary ip changed (from %s to %s) we need to purge all ip addresses and re-add them"
% (ifname, ordered_user_configured_ips[0], running_ip_addrs[0]))
skip_addrs = []
# if primary ipv4 address is not same, there is no need to keep any, reset all ipv4 addresses.
if user_ip4 and running_ip_addrs and running_ip_addrs[0].version == 4 and user_ip4[0] != running_ip_addrs[0]:
self.logger.info("%s: primary ipv4 changed (from %s to %s) we need to purge all ipv4 addresses and re-add them"
% (ifname, user_ip4[0], running_ip_addrs[0]))
skip_addrs = user_ip6
else:
skip_addrs = ordered_user_configured_ips

if anycast_ip:
skip_addrs.append(anycast_ip)

ip_flags = self.cache.get_ip_addresses_flags(ifname)
for addr in running_ip_addrs:
if addr in skip_addrs:
continue
# don't purge dynamic ipv6 ip if autoconf is enabled
if addr.version == 6 and not purge_dynamic_v6_addresses and addr in ip_flags and not ip_flags[addr] & 0x80:
continue
self.netlink.addr_del(ifname, addr)
except Exception as e:
self.log_warn(str(e))
Expand Down Expand Up @@ -923,14 +954,15 @@ def _process_mtu_config_mtu_none(self, ifaceobj, ifaceobj_getfunc):
self._propagate_mtu_to_upper_devs(ifaceobj, self.default_mtu, self.default_mtu_int, ifaceobj_getfunc)

def _set_bridge_forwarding(self, ifaceobj):
""" set ip forwarding to 0 if bridge interface does not have a
ip nor svi """
""" Disable IP forwarding if bridge interface does not have a IP nor SVI. """
ifname = ifaceobj.name

netconf_ipv4_forwarding = self.cache.get_netconf_forwarding(socket.AF_INET, ifname)
netconf_ipv6_forwarding = self.cache.get_netconf_forwarding(socket.AF_INET6, ifname)

if not ifaceobj.upperifaces and not ifaceobj.get_attr_value('address') and (ifaceobj.addr_method and "dhcp" not in ifaceobj.addr_method):
if ( not ifaceobj.upperifaces and not ifaceobj.get_attr_value('address') and
ifaceobj.addr_method and "dhcp" not in ifaceobj.addr_method and "auto" not in ifaceobj.addr_method):

if netconf_ipv4_forwarding:
self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 0)
if netconf_ipv6_forwarding:
Expand All @@ -944,6 +976,41 @@ def _set_bridge_forwarding(self, ifaceobj):
def sysctl_write_forwarding_value_to_proc(self, ifname, family, value):
self.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname), "%s\n" % value)

def _sysctl_slaac(self, ifaceobj):
addr_method = ifaceobj.addr_method
if addr_method not in ["auto"]:

try:
sysctl_ifname = '/'.join(ifaceobj.name.split("."))

running_accept_ra = self.cache.get_link_inet6_accept_ra(ifaceobj)
if running_accept_ra == '':
running_accept_ra = self.default_accept_ra
accept_ra = ifaceobj.get_attr_value_first('accept-ra')
if accept_ra is None:
accept_ra = self.default_accept_ra

if running_accept_ra != accept_ra:
self.sysctl_set(f'net.ipv6.conf.{sysctl_ifname}.accept_ra', accept_ra)
self.cache.update_link_inet6_accept_ra(ifaceobj.name, accept_ra)

running_autoconf = self.cache.get_link_inet6_autoconf(ifaceobj)
if running_autoconf == '':
running_autoconf = self.default_autoconf
autoconf = ifaceobj.get_attr_value_first('autoconf')
if autoconf is None:
autoconf = self.default_autoconf

if running_autoconf != autoconf:
self.sysctl_set(f'net.ipv6.conf.{sysctl_ifname}.autoconf', autoconf)
self.cache.update_link_inet6_autoconf(ifaceobj.name, autoconf)

except Exception as e:
if not setting_default_value:
ifaceobj.status = ifaceStatus.ERROR
self.logger.error('%s: %s' %(ifaceobj.name, str(e)))


def _sysctl_config(self, ifaceobj):
setting_default_value = False
mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
Expand All @@ -970,7 +1037,7 @@ def _sysctl_config(self, ifaceobj):

if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
self._set_bridge_forwarding(ifaceobj)

self._sysctl_slaac(ifaceobj)
if not self.syntax_check_sysctls(ifaceobj):
return
if not self.syntax_check_l3_svi_ip_forward(ifaceobj):
Expand Down Expand Up @@ -1037,6 +1104,8 @@ def _sysctl_config(self, ifaceobj):
ifaceobj.status = ifaceStatus.ERROR
self.logger.error('%s: %s' %(ifaceobj.name, str(e)))

self._sysctl_slaac(ifaceobj)

def process_mtu(self, ifaceobj, ifaceobj_getfunc):

if ifaceobj.link_privflags & ifaceLinkPrivFlags.OPENVSWITCH:
Expand Down Expand Up @@ -1074,7 +1143,7 @@ def up_ipv6_addrgen(self, ifaceobj):
# no need to go further during perfmode (boot)
return

if not user_configured_ipv6_addrgen and ifaceobj.addr_method in ["dhcp", "ppp"]:
if not user_configured_ipv6_addrgen and ifaceobj.addr_method in ["dhcp", "ppp", "auto"]:
return

if not user_configured_ipv6_addrgen:
Expand Down Expand Up @@ -1330,7 +1399,7 @@ def _down(self, ifaceobj, ifaceobj_getfunc=None):
if not self.cache.link_exists(ifaceobj.name):
return
addr_method = ifaceobj.addr_method
if addr_method not in ["dhcp", "ppp"]:
if addr_method not in ["dhcp", "ppp", "auto"]:
if ifaceobj.get_attr_value_first('address-purge')=='no':
addrlist = ifaceobj.get_attr_value('address')
for addr in addrlist or []:
Expand Down Expand Up @@ -1451,6 +1520,22 @@ def _query_sysctl(self, ifaceobj, ifaceobjcurr):
running_mpls_enable,
mpls_enable != running_mpls_enable)

accept_ra = ifaceobj.get_attr_value_first('accept-ra')
if accept_ra:
running_accept_ra = self.cache.get_link_inet6_accept_ra(ifaceobj)

ifaceobjcurr.update_config_with_status('accept_ra',
running_accept_ra,
accept_ra != running_accept_ra)

autoconf = ifaceobj.get_attr_value_first('autoconf')
if autoconf:
running_autoconf = self.cache.get_link_inet6_autoconf(ifaceobj)

ifaceobjcurr.update_config_with_status('autoconf',
running_autoconf,
autoconf != running_autoconf)

def query_check_ipv6_addrgen(self, ifaceobj, ifaceobjcurr):
ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')

Expand Down Expand Up @@ -1517,7 +1602,7 @@ def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):

def _query_check_address(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc):
""" ifquery-check: attribute: "address" """
if ifaceobj.addr_method in ["dhcp", "ppp"]:
if ifaceobj.addr_method in ["dhcp", "ppp", "auto"]:
return

if ifaceobj_getfunc:
Expand Down
Loading