Skip to content

Commit 03f4406

Browse files
committed
Ensure purging neighbor cache for stale deletes
When stale delete notifications are received, we still need to make sure to purge sandbox neighbor cache because these stale deletes are most typically out of order delete notifications and if an add for the peermac was received before the delete of the old peermac,vtep pair then we process that and replace the kernel state but the old neighbor state in the sandbox cache remains. That needs to be purged when we finally get the out of order delete notification. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
1 parent 2be973e commit 03f4406

File tree

3 files changed

+52
-38
lines changed

3 files changed

+52
-38
lines changed

drivers/overlay/peerdb.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,14 @@ func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask
168168
}
169169

170170
func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
171-
peerMac net.HardwareAddr, vtep net.IP) bool {
171+
peerMac net.HardwareAddr, vtep net.IP) peerEntry {
172172
peerDbWg.Wait()
173173

174174
d.peerDb.Lock()
175175
pMap, ok := d.peerDb.mp[nid]
176176
if !ok {
177177
d.peerDb.Unlock()
178-
return false
178+
return peerEntry{}
179179
}
180180
d.peerDb.Unlock()
181181

@@ -186,19 +186,20 @@ func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPM
186186

187187
pMap.Lock()
188188

189-
if pEntry, ok := pMap.mp[pKey.String()]; ok {
189+
pEntry, ok := pMap.mp[pKey.String()]
190+
if ok {
190191
// Mismatched endpoint ID(possibly outdated). Do not
191192
// delete peerdb
192193
if pEntry.eid != eid {
193194
pMap.Unlock()
194-
return false
195+
return pEntry
195196
}
196197
}
197198

198199
delete(pMap.mp, pKey.String())
199200
pMap.Unlock()
200201

201-
return true
202+
return pEntry
202203
}
203204

204205
func (d *driver) peerDbUpdateSandbox(nid string) {
@@ -312,10 +313,9 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas
312313
return err
313314
}
314315

316+
var pEntry peerEntry
315317
if updateDb {
316-
if !d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep) {
317-
return nil
318-
}
318+
pEntry = d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep)
319319
}
320320

321321
n := d.network(nid)
@@ -328,14 +328,24 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas
328328
return nil
329329
}
330330

331-
// Delete fdb entry to the bridge for the peer mac
332-
if err := sbox.DeleteNeighbor(vtep, peerMac); err != nil {
333-
return fmt.Errorf("could not delete fdb entry into the sandbox: %v", err)
331+
// Delete fdb entry to the bridge for the peer mac only if the
332+
// entry existed in local peerdb. If it is a stale delete
333+
// request, still call DeleteNeighbor but only to cleanup any
334+
// leftover sandbox neighbor cache and not actually delete the
335+
// kernel state.
336+
if (eid == pEntry.eid && vtep.Equal(pEntry.vtep)) ||
337+
(eid != pEntry.eid && !vtep.Equal(pEntry.vtep)) {
338+
if err := sbox.DeleteNeighbor(vtep, peerMac,
339+
eid == pEntry.eid && vtep.Equal(pEntry.vtep)); err != nil {
340+
return fmt.Errorf("could not delete fdb entry into the sandbox: %v", err)
341+
}
334342
}
335343

336344
// Delete neighbor entry for the peer IP
337-
if err := sbox.DeleteNeighbor(peerIP, peerMac); err != nil {
338-
return fmt.Errorf("could not delete neighbor entry into the sandbox: %v", err)
345+
if eid == pEntry.eid {
346+
if err := sbox.DeleteNeighbor(peerIP, peerMac, true); err != nil {
347+
return fmt.Errorf("could not delete neighbor entry into the sandbox: %v", err)
348+
}
339349
}
340350

341351
if err := d.checkEncryption(nid, vtep, 0, false, false); err != nil {

osl/neigh_linux.go

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *
3232
return nil
3333
}
3434

35-
func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr) error {
35+
func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
3636
var (
3737
iface netlink.Link
3838
err error
@@ -43,42 +43,46 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr)
4343
return fmt.Errorf("could not find the neighbor entry to delete")
4444
}
4545

46-
n.Lock()
47-
nlh := n.nlHandle
48-
n.Unlock()
46+
if osDelete {
47+
n.Lock()
48+
nlh := n.nlHandle
49+
n.Unlock()
4950

50-
if nh.linkDst != "" {
51-
iface, err = nlh.LinkByName(nh.linkDst)
52-
if err != nil {
53-
return fmt.Errorf("could not find interface with destination name %s: %v",
54-
nh.linkDst, err)
51+
if nh.linkDst != "" {
52+
iface, err = nlh.LinkByName(nh.linkDst)
53+
if err != nil {
54+
return fmt.Errorf("could not find interface with destination name %s: %v",
55+
nh.linkDst, err)
56+
}
5557
}
56-
}
5758

58-
nlnh := &netlink.Neigh{
59-
IP: dstIP,
60-
State: netlink.NUD_PERMANENT,
61-
Family: nh.family,
62-
}
59+
nlnh := &netlink.Neigh{
60+
IP: dstIP,
61+
State: netlink.NUD_PERMANENT,
62+
Family: nh.family,
63+
}
6364

64-
if nlnh.Family > 0 {
65-
nlnh.HardwareAddr = dstMac
66-
nlnh.Flags = netlink.NTF_SELF
67-
}
65+
if nlnh.Family > 0 {
66+
nlnh.HardwareAddr = dstMac
67+
nlnh.Flags = netlink.NTF_SELF
68+
}
6869

69-
if nh.linkDst != "" {
70-
nlnh.LinkIndex = iface.Attrs().Index
71-
}
70+
if nh.linkDst != "" {
71+
nlnh.LinkIndex = iface.Attrs().Index
72+
}
7273

73-
if err := nlh.NeighDel(nlnh); err != nil {
74-
return fmt.Errorf("could not delete neighbor entry: %v", err)
74+
if err := nlh.NeighDel(nlnh); err != nil {
75+
return fmt.Errorf("could not delete neighbor entry: %v", err)
76+
}
7577
}
7678

79+
n.Lock()
7780
for i, nh := range n.neighbors {
7881
if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
7982
n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
8083
}
8184
}
85+
n.Unlock()
8286

8387
return nil
8488
}

osl/sandbox.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ type Sandbox interface {
4242
AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, option ...NeighOption) error
4343

4444
// DeleteNeighbor deletes neighbor entry from the sandbox.
45-
DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr) error
45+
DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error
4646

4747
// Returns an interface with methods to set neighbor options.
4848
NeighborOptions() NeighborOptionSetter

0 commit comments

Comments
 (0)