Skip to content

Commit 9fa7bbf

Browse files
committed
network: preseed default-gateway neighbor
This change mirrors host networking into the guest as before, but now also includes the default gateway neighbor entry for each interface. Pods using overlay/synthetic gateways (e.g., 169.254.1.1) can hit a first-connect race while the guest performs the initial ARP. Preseeding the gateway neighbor removes that latency and makes early connections (e.g., to the API Service) deterministic. Signed-off-by: Saul Paredes <[email protected]>
1 parent 0c4c69a commit 9fa7bbf

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

src/runtime/virtcontainers/network.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,16 @@ func generateVCNetworkStructures(ctx context.Context, endpoints []Endpoint) ([]*
315315
routes = append(routes, &r)
316316
}
317317

318+
gatewaySet := gatewaySetFromRoutes(endpoint.Properties().Routes)
319+
318320
for _, neigh := range endpoint.Properties().Neighbors {
319-
var n pbTypes.ARPNeighbor
320321

321-
if !validGuestNeighbor(neigh) {
322+
if !validGuestNeighbor(neigh, gatewaySet) {
322323
continue
323324
}
324325

326+
var n pbTypes.ARPNeighbor
327+
325328
n.Device = endpoint.Name()
326329
n.State = int32(neigh.State)
327330
n.Flags = int32(neigh.Flags)

src/runtime/virtcontainers/network_linux.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,39 @@ func validGuestRoute(route netlink.Route) bool {
16141614
return route.Protocol != unix.RTPROT_KERNEL
16151615
}
16161616

1617-
func validGuestNeighbor(neigh netlink.Neigh) bool {
1618-
// We add only static ARP entries
1619-
return neigh.State == netlink.NUD_PERMANENT
1617+
// neighbor is valid if it is static or a default-gateway
1618+
func validGuestNeighbor(neigh netlink.Neigh, gatewaySet map[string]struct{}) bool {
1619+
// need a MAC for the guest
1620+
if neigh.HardwareAddr == nil {
1621+
return false
1622+
}
1623+
// Keep all static entries
1624+
if neigh.State == netlink.NUD_PERMANENT {
1625+
return true
1626+
}
1627+
// Gateway-only exception: allow the default-gateway IP:
1628+
// On some setups, the pod subnet gateway does not appear in the host ARP cache as a static entry.
1629+
// On these setups an ARP request storm happens when many Kata PODs are started at the same time and they all look for the gateway MAC address.
1630+
// This forces the gateway to churn a lot of ARP requests and render the ARP request full, hence dropping some ARP requests.
1631+
// Manually pre-populating the ARP entry in the UVM guest ARP cache for that gateway solves that problem.
1632+
_, isGw := gatewaySet[neigh.IP.String()]
1633+
return isGw
1634+
}
1635+
1636+
// helper: default routes => set of gateway IP strings
1637+
func gatewaySetFromRoutes(routes []netlink.Route) map[string]struct{} {
1638+
gatewaySet := make(map[string]struct{})
1639+
for _, route := range routes {
1640+
if route.Gw == nil {
1641+
continue
1642+
}
1643+
if route.Dst == nil {
1644+
gatewaySet[route.Gw.String()] = struct{}{}
1645+
continue
1646+
}
1647+
if ones, _ := route.Dst.Mask.Size(); ones == 0 { // 0.0.0.0/0 or ::/0
1648+
gatewaySet[route.Gw.String()] = struct{}{}
1649+
}
1650+
}
1651+
return gatewaySet
16201652
}

0 commit comments

Comments
 (0)