Skip to content

Commit aaefcd8

Browse files
Merge pull request #19926 from danwinship/egress-ip-duplicates
Fix a bug when a namespace has two egress IPs on same node
2 parents 032dcff + 9df9166 commit aaefcd8

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

pkg/network/node/egressip.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,11 @@ func (eip *egressIPWatcher) updateNamespaceEgress(vnid uint32, egressIPs []strin
271271
eip.deleteNamespace(ip, ns)
272272
}
273273

274-
// Make sure we update OVS even if nothing was added or removed; the order might
275-
// have changed
276-
eip.changedNamespaces = append(eip.changedNamespaces, ns)
274+
// Even IPs that weren't added/removed need to be considered "changed", to
275+
// ensure we correctly process reorderings, duplicates added/removed, etc.
276+
for _, ip := range newRequestedIPs.Intersection(oldRequestedIPs).UnsortedList() {
277+
eip.egressIPChanged(eip.egressIPs[ip])
278+
}
277279

278280
eip.syncEgressIPs()
279281
}
@@ -310,8 +312,8 @@ func (eip *egressIPWatcher) syncEgressIPs() {
310312
func (eip *egressIPWatcher) syncEgressNodeState(eg *egressIPInfo) {
311313
// The egressIPInfo should have an assigned node IP if and only if the
312314
// egress IP is active (ie, it is assigned to exactly 1 node and exactly
313-
// 1 namespace).
314-
egressIPActive := (len(eg.nodes) == 1 && len(eg.namespaces) == 1)
315+
// 1 namespace, and it's the first one for its namespace).
316+
egressIPActive := (len(eg.nodes) == 1 && len(eg.namespaces) == 1 && eg.ip == eg.namespaces[0].requestedIPs[0])
315317
if egressIPActive && eg.assignedNodeIP != eg.nodes[0].nodeIP {
316318
glog.V(4).Infof("Assigning egress IP %s to node %s", eg.ip, eg.nodes[0].nodeIP)
317319
eg.assignedNodeIP = eg.nodes[0].nodeIP

pkg/network/node/egressip_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
355355

356356
// Assigning that IP to a node should now make it work
357357
eip.updateNodeEgress("172.17.0.4", []string{"172.17.0.101"})
358+
err = assertNetlinkChange(eip, "claim 172.17.0.101")
359+
if err != nil {
360+
t.Fatalf("%v", err)
361+
}
358362
err = assertOVSChanges(eip, &flows,
359363
egressOVSChange{vnid: 42, egress: Local},
360364
)
@@ -364,6 +368,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
364368

365369
// Swapping the order in the NetNamespace should bring the original Egress IP back
366370
eip.updateNamespaceEgress(42, []string{"172.17.0.100", "172.17.0.101"})
371+
err = assertNetlinkChange(eip, "release 172.17.0.101")
372+
if err != nil {
373+
t.Fatalf("%v", err)
374+
}
367375
err = assertOVSChanges(eip, &flows,
368376
egressOVSChange{vnid: 42, egress: Remote, remote: "172.17.0.3"},
369377
)
@@ -373,6 +381,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
373381

374382
// Removing the inactive egress IP from its node should have no effect
375383
eip.updateNodeEgress("172.17.0.4", []string{"172.17.0.200"})
384+
err = assertNoNetlinkChanges(eip)
385+
if err != nil {
386+
t.Fatalf("%v", err)
387+
}
376388
err = assertOVSChanges(eip, &flows,
377389
egressOVSChange{vnid: 42, egress: Remote, remote: "172.17.0.3"},
378390
)
@@ -392,6 +404,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
392404
// Now add the egress IPs back...
393405
eip.updateNodeEgress("172.17.0.3", []string{"172.17.0.100"})
394406
eip.updateNodeEgress("172.17.0.4", []string{"172.17.0.101"})
407+
err = assertNoNetlinkChanges(eip)
408+
if err != nil {
409+
t.Fatalf("%v", err)
410+
}
395411
err = assertOVSChanges(eip, &flows,
396412
egressOVSChange{vnid: 42, egress: Remote, remote: "172.17.0.3"},
397413
)
@@ -402,6 +418,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
402418
// Assigning either the used or the unused Egress IP to another namespace should
403419
// break this namespace
404420
eip.updateNamespaceEgress(43, []string{"172.17.0.100"})
421+
err = assertNoNetlinkChanges(eip)
422+
if err != nil {
423+
t.Fatalf("%v", err)
424+
}
405425
err = assertOVSChanges(eip, &flows,
406426
egressOVSChange{vnid: 42, egress: Dropped},
407427
egressOVSChange{vnid: 43, egress: Dropped},
@@ -411,6 +431,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
411431
}
412432

413433
eip.deleteNamespaceEgress(43)
434+
err = assertNoNetlinkChanges(eip)
435+
if err != nil {
436+
t.Fatalf("%v", err)
437+
}
414438
err = assertOVSChanges(eip, &flows,
415439
egressOVSChange{vnid: 42, egress: Remote, remote: "172.17.0.3"},
416440
egressOVSChange{vnid: 43, egress: Normal},
@@ -420,6 +444,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
420444
}
421445

422446
eip.updateNamespaceEgress(44, []string{"172.17.0.101"})
447+
err = assertNoNetlinkChanges(eip)
448+
if err != nil {
449+
t.Fatalf("%v", err)
450+
}
423451
err = assertOVSChanges(eip, &flows,
424452
egressOVSChange{vnid: 42, egress: Dropped},
425453
egressOVSChange{vnid: 44, egress: Dropped},
@@ -429,6 +457,10 @@ func TestMultipleNamespaceEgressIPs(t *testing.T) {
429457
}
430458

431459
eip.deleteNamespaceEgress(44)
460+
err = assertNoNetlinkChanges(eip)
461+
if err != nil {
462+
t.Fatalf("%v", err)
463+
}
432464
err = assertOVSChanges(eip, &flows,
433465
egressOVSChange{vnid: 42, egress: Remote, remote: "172.17.0.3"},
434466
egressOVSChange{vnid: 44, egress: Normal},

0 commit comments

Comments
 (0)