diff --git a/libnetwork/drivers/overlay/peerdb.go b/libnetwork/drivers/overlay/peerdb.go index 00af35d707..345f1c1aba 100644 --- a/libnetwork/drivers/overlay/peerdb.go +++ b/libnetwork/drivers/overlay/peerdb.go @@ -321,7 +321,7 @@ func (d *driver) peerAddOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask } // Add neighbor entry for the peer IP - if err := sbox.AddNeighbor(peerIP, peerMac, osl.WithLinkName(s.vxlanName)); err != nil { + if err := sbox.AddNeighbor(peerIP, peerMac, false, osl.WithLinkName(s.vxlanName)); err != nil { if _, ok := err.(osl.NeighborSearchError); ok && dbEntries > 1 { // We are in the transient case so only the first configuration is programmed into the kernel // Upon deletion if the active configuration is deleted the next one from the database will be restored @@ -332,7 +332,7 @@ func (d *driver) peerAddOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask } // Add fdb entry to the bridge for the peer mac - if err := sbox.AddNeighbor(vtep, peerMac, osl.WithLinkName(s.vxlanName), osl.WithFamily(syscall.AF_BRIDGE)); err != nil { + if err := sbox.AddNeighbor(vtep, peerMac, false, osl.WithLinkName(s.vxlanName), osl.WithFamily(syscall.AF_BRIDGE)); err != nil { return fmt.Errorf("could not add fdb entry for nid:%s eid:%s into the sandbox:%v", nid, eid, err) } diff --git a/libnetwork/osl/neigh_linux.go b/libnetwork/osl/neigh_linux.go index 46ecd47ec1..c5dab0b8a3 100644 --- a/libnetwork/osl/neigh_linux.go +++ b/libnetwork/osl/neigh_linux.go @@ -110,16 +110,22 @@ func (n *Namespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr) error } // AddNeighbor adds a neighbor entry into the sandbox. -func (n *Namespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, options ...NeighOption) error { +func (n *Namespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, options ...NeighOption) error { var ( - iface netlink.Link - err error + iface netlink.Link + err error + neighborAlreadyPresent bool ) + // If the namespace already has the neighbor entry but the AddNeighbor is called + // because of a miss notification (force flag) program the kernel anyway. nh := n.findNeighbor(dstIP, dstMac) if nh != nil { - log.G(context.TODO()).Warnf("Neighbor entry already present for IP %v, mac %v neighbor:%+v", dstIP, dstMac, nh) - return NeighborSearchError{dstIP, dstMac, true} + neighborAlreadyPresent = true + log.G(context.TODO()).Warnf("Neighbor entry already present for IP %v, mac %v neighbor:%+v forceUpdate:%t", dstIP, dstMac, nh, force) + if !force { + return NeighborSearchError{dstIP, dstMac, true} + } } nh = &neigh{ @@ -166,6 +172,10 @@ func (n *Namespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, options . return fmt.Errorf("could not add neighbor entry:%+v error:%v", nlnh, err) } + if neighborAlreadyPresent { + return nil + } + n.mu.Lock() n.neighbors = append(n.neighbors, nh) n.mu.Unlock()