From 31bf46404a3d5f401507193869beed9c40c9612a Mon Sep 17 00:00:00 2001 From: Levalicious Date: Tue, 13 Oct 2026 16:01:59 -0400 Subject: [PATCH] lb: delete default routes as listed (RouteDel refuses a nil Dst) RouteList returns a default route without Dst, and netlink's RouteDel refuses a route with no Dst, Src or Gw. The egress unreachable table's "unreachable default" could not be removed once installed: every later pass failed there, before updating rules, so members stayed dropped after their EgressService got a holder again (fail closed, but stuck). S1's stale reply tables had the same latent fault. Both now delete through delRoute, which spells the default destination out; the unreachable route is compared by type alone, so it is not replaced on every pass. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UHXzGrsxfkGk8LmwrBbHNZ --- lb/datapath.go | 11 +++++++++-- lb/egress_datapath.go | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lb/datapath.go b/lb/datapath.go index 5dd6c751..4c9a7982 100644 --- a/lb/datapath.go +++ b/lb/datapath.go @@ -295,8 +295,7 @@ func (dp *Datapath) routes(holders []Holder) error { return err } for _, rt := range routes { - rt := rt - if err := netlink.RouteDel(&rt); err != nil { + if err := delRoute(rt); err != nil { return fmt.Errorf("removing stale route in table %d: %v", table, err) } } @@ -324,3 +323,11 @@ func (dp *Datapath) routes(holders []Holder) error { } return nil } + +// delRoute deletes a route as RouteList returned it: a default route lists without Dst, which RouteDel refuses. +func delRoute(rt netlink.Route) error { + if rt.Dst == nil { + rt.Dst = &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)} + } + return netlink.RouteDel(&rt) +} diff --git a/lb/egress_datapath.go b/lb/egress_datapath.go index baf6f92d..efdcfe70 100644 --- a/lb/egress_datapath.go +++ b/lb/egress_datapath.go @@ -213,11 +213,11 @@ func egressNet(e EgressDesired, self string, local Local) error { return err } for _, rt := range routes { - if want != nil && rt.Type == want.Type && rt.LinkIndex == want.LinkIndex && rt.Gw.Equal(want.Gw) { + if want != nil && rt.Type == want.Type && + (want.Type == unix.RTN_UNREACHABLE || rt.LinkIndex == want.LinkIndex && rt.Gw.Equal(want.Gw)) { continue } - rt := rt - if err := netlink.RouteDel(&rt); err != nil { + if err := delRoute(rt); err != nil { return fmt.Errorf("removing stale route in table %d: %v", table, err) } }