Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login
    Introducing Netgate Nexus: Multi-Instance Management at Your Fingertips.

    HA + Track Interface + CARP RA source: BACKUP node still starts radvd and advertises ::/64

    Scheduled Pinned Locked Moved HA/CARP/VIPs
    2 Posts 1 Posters 128 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P Offline
      perrin
      last edited by perrin

      Environment

      pfSense Plus 26.07
      Two-node CARP HA pair
      PPPoE WAN with DHCPv6 Prefix Delegation
      LAN interfaces use IPv6 Configuration Type = Track Interface
      Router Advertisements use a link-local CARP VIP as RA source, e.g. fe80::9:1
      Additional ULA /64 is configured under RA Subnets

      Only the CARP MASTER establishes a PPPoE connection in my environment. On the BACKUP node PPPoE is intentionally disabled, so that node has no delegated IPv6 prefix. This is done through my custom package mentioned in this thread

      Expected behavior

      When the configured RA source CARP VIP is in BACKUP state, the node should not advertise itself as an IPv6 router on that interface.

      This appears to be the intended behavior of the CARP-aware RA handling: the MASTER should advertise using the shared CARP link-local address, while the BACKUP should remain silent.

      Actual behavior

      On the MASTER, the generated configuration is correct:

      interface vtnet0.9 {
          AdvSendAdvert on;
          AdvRASrcAddress {
              fe80::9:1;
          };
      
      
          prefix 2a11:....::/64 {
              ...
          };
      
      
          prefix fd6f:6e32:6465:8009::/64 {
              ...
          };
      };
      

      On the BACKUP node, since no DHCPv6-PD is available, pfSense generates a second/automatic Track Interface RA configuration instead:

      # Generated config for dhcp6 delegation from wan on lan
      interface vtnet0.9 {
          AdvSendAdvert on;
          ...
          prefix ::/64 {
              AdvOnLink on;
              AdvAutonomous on;
          };
      };
      

      radvd is running on the BACKUP node and actively sends RAs from the node's physical link-local address, not the CARP VIP:

      fe80::be24:11ff:fe1d:89fb > ff02::1:
      ICMP6, router advertisement
      

      Clients consequently learn two default routers:

      ::/0 via fe80::9:1                     # CARP / MASTER
      ::/0 via fe80::be24:11ff:fe1d:89fb    # physical address of BACKUP
      

      This causes intermittent IPv6 connectivity because the BACKUP node does not have an active WAN/PD.

      Stopping radvd manually on the BACKUP immediately fixes the problem and clients only use the CARP router.

      Possible cause

      Looking at the RA generation logic, there appear to be two relevant paths:

      normal/manual RA configuration, which respects the configured RA VIP/CARP state;
      automatic RA generation for IPv6 Track Interface interfaces.

      The second Track Interface path appears to recreate an RA interface even though the configured RA source VIP is currently CARP BACKUP.

      If the tracked IPv6 address does not exist, that path also appears to fall back to:

      prefix ::/64
      

      This effectively bypasses the CARP-aware RA suppression performed by the normal RA configuration path.

      Suggested fix

      The Track Interface RA generation path should apply the same RA-source/CARP-state check as the normal RA path.

      Conceptually, before generating automatic RA configuration for a tracked interface:

      $raconf = config_get_path("dhcpdv6/{$if}", []);
      
      
      if (!empty($raconf['rainterface']) &&
          str_starts_with($raconf['rainterface'], '_vip') &&
          get_carp_interface_status($raconf['rainterface']) != 'MASTER') {
          continue;
      }
      

      Exact function/config names may differ, but the intent would be:

      If an RA source VIP is configured and that VIP is not MASTER on this node, do not add the Track Interface to radvd.conf.

      If no other interface requires radvd, the daemon can then remain stopped on the BACKUP node.

      I would also question whether generating prefix ::/64 when a tracked interface currently has no delegated prefix is desirable at all. Skipping that prefix until PD becomes available seems safer.

      Reproduction

      Configure an HA pair.
      WAN uses PPPoE + DHCPv6-PD.
      LAN uses IPv6 Track Interface.
      Configure a link-local CARP VIP as the RA source.
      MASTER has active PPPoE/PD.
      BACKUP has no active PPPoE/PD.
      Inspect /var/etc/radvd.conf and capture RAs on the BACKUP LAN.

      The BACKUP generates prefix ::/64, starts radvd, and sends RAs using its physical link-local address.

      I can provide additional configuration snippets or packet captures if useful.

      P 1 Reply Last reply Reply Quote 0
      • P Offline
        perrin @perrin
        last edited by

        I created a patch to fix the issue. Testing the patch in my environment currently and so far it looks very promsing:

        radvd on backup node is stopped and started once in transitions to primary.

        here is the patch:

        --- a/etc/inc/services.inc
        +++ b/etc/inc/services.inc
        @@ -379,6 +379,21 @@
         			continue;
         		}
         
        +		/* Honor the RA Interface (CARP VIP) setting for tracked interfaces.
        +		 * Mirrors the check performed for manually configured RA interfaces
        +		 * above: when RAs are sourced from a CARP VIP, only the MASTER node
        +		 * may advertise. Without this a BACKUP node keeps sending RAs, often
        +		 * announcing a bogus "prefix ::/64" because no prefix is delegated.
        +		 * An empty status means the VIP could not be resolved; treat that as
        +		 * non-CARP and continue, matching the manual RA code path. */
        +		$ratrackif = config_get_path("dhcpdv6/{$if}/rainterface");
        +		if (!empty($ratrackif) && strstr($ratrackif, "_vip")) {
        +			$carpstatus = get_carp_interface_status($ratrackif);
        +			if (($carpstatus == "BACKUP") || ($carpstatus == "INIT")) {
        +				continue;
        +			}
        +		}
        +
         		$realif = get_real_interface($if, "inet6");
         
         		/* prevent duplicate entries, manual overrides */
        
        

        @stephenw10 would that be something which can make it into the main source code? currently i am running this patch via the system patches package.

        Thanks

        1 Reply Last reply Reply Quote 0
        • First post
          Last post
        Copyright 2026 Rubicon Communications LLC (Netgate). All rights reserved.
        Privacy Policy · Cookie Policy