fix(route): insert route tracker entry only after AddRoute succeeds

Signed-off-by: Maximilian Rink <maximilian.rink@telekom.de>
This commit is contained in:
Maximilian Rink
2026-08-23 22:21:20 +02:00
parent 9d72f43f62
commit a8293f66e4
3 changed files with 34 additions and 3 deletions

View File

@@ -49,9 +49,6 @@ func (m *Manager) Add(object string, r route, precheck, update bool) error {
itm, exists := m.tracker[key]
if !exists {
m.tracker[key] = newItem(r)
itm = m.tracker[key]
added, err := r.AddRoute(precheck)
if err != nil {
if update && errors.Is(err, syscall.EEXIST) && update {
@@ -70,6 +67,9 @@ func (m *Manager) Add(object string, r route, precheck, update bool) error {
}
}
itm = newItem(r)
m.tracker[key] = itm
if added {
log.Debug("[RT] added route", "path", key, "object", object)
}

View File

@@ -0,0 +1,29 @@
package route
import (
"errors"
"testing"
)
var errTransientRouteAdd = errors.New("transient route add failure")
func TestManagerRetriesRouteAfterInitialAddFailure(t *testing.T) {
m := NewManager()
r := &mockRoute{hash: "retry", addErr: errTransientRouteAdd}
if err := m.Add("service", r, false, true); !errors.Is(err, errTransientRouteAdd) {
t.Fatalf("first add error = %v, want %v", err, errTransientRouteAdd)
}
// A transient netlink failure (for example while the link is being recreated)
// must not poison the in-memory tracker. The next reconciliation has to retry
// the kernel operation.
r.addErr = nil
r.added = true
if err := m.Add("service", r, false, true); err != nil {
t.Fatalf("retry add failed: %v", err)
}
if r.addCalls != 2 {
t.Fatalf("AddRoute called %d times, want 2", r.addCalls)
}
}

View File

@@ -186,6 +186,7 @@ func Test_MultipleRoutesAddDel(t *testing.T) {
type mockRoute struct {
added bool
addCalls int
addErr error
updated bool
updateErr error
@@ -195,6 +196,7 @@ type mockRoute struct {
}
func (mr *mockRoute) AddRoute(_ bool) (bool, error) {
mr.addCalls++
return mr.added, mr.addErr
}