From 2525cb5e8876b72c3bb7765779dd04a05f529a15 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 30 Jul 2024 14:24:31 +0200 Subject: [PATCH] Announce fir IPv4 addresses (GARP) before IPv6 NA To announce IPv6 addresses, SendUnsolicitedNeighborAdvertisement() possibly needs to wait for tentative IPv6 addresses to become usable (DAD). This can take more than a second. Change the loop over all addresses, to iterate them twice, and on the first run announce IPv4 addresses. IPv4 addresses don't need to be affected by this waiting. Note that utils.AnnounceIPs() is called towards the end of whatever the command invocation is doing. This reordering, ensures that we potentially announce IPv4 addresses earlier. --- pkg/utils/packet.go | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/pkg/utils/packet.go b/pkg/utils/packet.go index e162e3be..b1e82f57 100644 --- a/pkg/utils/packet.go +++ b/pkg/utils/packet.go @@ -200,22 +200,34 @@ func AnnounceIPs(ifName string, ipConfigs []*current.IPConfig) error { } // For all the IP addresses assigned by IPAM, we will send either a GARP (IPv4) or Unsolicited NA (IPv6). - for _, ipc := range ipConfigs { - var err error - if IsIPv6(ipc.Address.IP) { - /* As per RFC 4861, sending unsolicited neighbor advertisements should be considered as a performance - * optimization. It does not reliably update caches in all nodes. The Neighbor Unreachability Detection - * algorithm is more reliable although it may take slightly longer to update. - */ - err = SendUnsolicitedNeighborAdvertisement(ipc.Address.IP, linkObj) - } else if IsIPv4(ipc.Address.IP) { - err = SendGratuitousArp(ipc.Address.IP, linkObj) - } else { - return fmt.Errorf("the IP %s on interface %q is neither IPv4 or IPv6", ipc.Address.IP.String(), ifName) - } + // + // Note that SendUnsolicitedNeighborAdvertisement() can wait for tentative + // IPv6 addresses. It is thus slower. We iterate over the addresses twice + // (i_af loop), and first announce IPv4 addresses. + for i_af := 0; i_af < 2; i_af++ { + for _, ipc := range ipConfigs { + var err error + if IsIPv6(ipc.Address.IP) { + /* As per RFC 4861, sending unsolicited neighbor advertisements should be considered as a performance + * optimization. It does not reliably update caches in all nodes. The Neighbor Unreachability Detection + * algorithm is more reliable although it may take slightly longer to update. + */ + if i_af == 0 { + continue + } + err = SendUnsolicitedNeighborAdvertisement(ipc.Address.IP, linkObj) + } else if IsIPv4(ipc.Address.IP) { + if i_af == 1 { + continue + } + err = SendGratuitousArp(ipc.Address.IP, linkObj) + } else { + return fmt.Errorf("the IP %s on interface %q is neither IPv4 or IPv6", ipc.Address.IP.String(), ifName) + } - if err != nil { - return fmt.Errorf("failed to send GARP/NA message for ip %s on interface %q: %v", ipc.Address.IP.String(), ifName, err) + if err != nil { + return fmt.Errorf("failed to send GARP/NA message for ip %s on interface %q: %v", ipc.Address.IP.String(), ifName, err) + } } } return nil