Page MenuHomeVyOS Platform

dhcp6c fails to restart after interface down & up when using only PD
Closed, ResolvedPublicBUG

Description

When an interface is configured only with IPv6 PD and not with DHCPv6 for its own address, the dhcp6c service will not be restarted after the link goes down and comes back up.

Example config:

interfaces {
    ethernet eth0 {
        address dhcp                       <-- No dhcpv6 here!
        dhcpv6-options {
            pd 0 {                         <-- Using PD
                interface br0.1 {
                    address 1
                    sla-id 1
                }
                length 56
            }
        }
        ipv6 {
            address {
                autoconf                   <-- Using autoconf for own address
            }
        }
    }
}

The problem comes from the /etc/netplug/vyos-netplug-dhcp-client file (https://github.com/vyos/vyos-1x/blob/current/src/etc/netplug/vyos-netplug-dhcp-client), which correctly stops the dhcp6c client but then never restarts it as the logic used for restart is different for the logic used for stopping and is incorrect:

if in_out == 'out':
    # Interface moved state to down
    if is_systemd_service_active(systemdV4_service):
        cmd(f'systemctl stop {systemdV4_service}')
    if is_systemd_service_active(systemdV6_service):
        cmd(f'systemctl stop {systemdV6_service}')
elif in_out == 'in':
    if config.exists_effective(interface_path + ['address']):
        tmp = config.return_effective_values(interface_path + ['address'])
        # Always (re-)start the DHCP(v6) client service. If the DHCP(v6) client
        # is already running - which could happen if the interface is re-
        # configured in operational down state, it will have a backoff
        # time increasing while not receiving a DHCP(v6) reply.
        #
        # To make the interface instantly available, and as for a DHCP(v6) lease
        # we will re-start the service and thus cancel the backoff time.
        if 'dhcp' in tmp:
            cmd(f'systemctl restart {systemdV4_service}')
        if 'dhcpv6' in tmp:
            cmd(f'systemctl restart {systemdV6_service}')

As you can see above, is_systemd_service_active(systemdV6_service) will return true and the dhcp6c client will be stopped as expected. However, tmp in this case will only be ['dhcp'], as we are using PD only and not DHCPv6 for own address assignment. As such, the if 'dhcpv6' in tmp returns false and dhcp6c is never restarted and hence IPv6 connectivity is lost any time an ethernet interface is disconnected and reconnected.

This was introduced in this commit: https://github.com/vyos/vyos-1x/commit/588f2e02028bc3e0d1203c750c3cba56fb8291f2

The fix should be to change the v6 check to also check if the ['interfaces', 'ethernet', 'eth0', 'dhcpv6-options', 'pd'] exists as well as checking if 'dhcpv6' exists in address. Either of these conditions should be sufficient to require a restart of the service

Details

Version
1.4.3 (also in rolling)
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)

Event Timeline

Relevant section of interface.py: https://github.com/vyos/vyos-1x/blob/5845c4b1c50bc0335284cfb3306e0a91de3efd40/python/vyos/ifconfig/interface.py#L1822-L1824

The above shows PD is permitted to be running in isolation (i.e without dhcpv6 in address block), so the config example appears to be well-formed and this previously worked fine (until the commit linked above). The check in interface.py is for the presence of dhcpv6_options.pd, as suggested above as a fix: dhcpv6pd = dict_search('dhcpv6_options.pd', config)

Sorry, another followup, rather than duplicating the control logic in both interface.py and in vyos-netplug-dhcp-client (and leaving yourself open to another logic divergence in future), you could consider just checking for presence of the config file /var/run/dhcp6c.eth0.conf in vyos-netplug-dhcp-client when determining if the service should restart. That file only exists if dhcp6c is required on that specific interface, and that means the logic for dhcp6c presence is determined only by interface.py and vyos-netplug-dhcp-client just follows its lead.

dmbaturin changed Is it a breaking change? from Unspecified (possibly destroys the router) to Perfectly compatible.

To work around this at present I am setting the following additional configuration to prevent losing IPv6 connectivity frequently:

interfaces {
    ethernet eth0 {
        address dhcpv6            <-- Ensures dhcp6c is restarted but would cause a DHCPv6 address to be allocated to router, which is not desired
        dhcpv6-options {
            temporary             <-- Prevents a DHCPv6 address being requested, but allows PD request
            ... etc
        }
        ... etc
    }
}

Based on the template here this is almost the same as not having address dhcpv6 set, but will keep dhcp6c running on an interface re-up. This behaviour may differ between upstream DHCPv6 servers though...

sarthurdev changed the task status from Open to Needs testing.Oct 12 2025, 1:33 PM
sarthurdev claimed this task.
sarthurdev moved this task from Need Triage to Backport Candidates on the VyOS Rolling board.
sarthurdev subscribed.