From 098a6ff9c1e7512d43de93c4b64c0f41f264ee59 Mon Sep 17 00:00:00 2001 From: Scott Yeager Date: Fri, 20 Jun 2025 18:23:37 -0700 Subject: [PATCH] update route handling --- main.go | 70 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/main.go b/main.go index 61fc0f2..2b5cbcf 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net" + "time" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" @@ -60,9 +61,15 @@ func cmdAdd(args *skel.CmdArgs) error { return fmt.Errorf("failed to move veth to container netns: %v", err) } + // Get host veth link-local address with retry + hostLinkLocal, err := getHostVethLinkLocalWithRetry(hostVeth) + if err != nil { + return fmt.Errorf("failed to get host veth link-local address: %v", err) + } + // Configure container interface containerIP := generateContainerIP(myceliumIP, args.ContainerID) - if err := configureContainerInterface(containerNS, containerVethName, containerIP, hostVethName); err != nil { + if err := configureContainerInterface(containerNS, containerVethName, containerIP, hostLinkLocal); err != nil { return fmt.Errorf("failed to configure container interface: %v", err) } @@ -182,7 +189,7 @@ func createVethPair(hostName, containerName string) (netlink.Link, netlink.Link, return hostVeth, containerVeth, nil } -func configureContainerInterface(containerNS netns.NsHandle, ifName string, containerIP net.IP, hostVethName string) error { +func configureContainerInterface(containerNS netns.NsHandle, ifName string, containerIP net.IP, hostLinkLocal net.IP) error { // Switch to container namespace originalNS, err := netns.Get() if err != nil { @@ -216,27 +223,17 @@ func configureContainerInterface(containerNS netns.NsHandle, ifName string, cont return err } - // Get host veth link-local address for routing - hostVeth, err := netlink.LinkByName(hostVethName) - if err == nil { - hostAddrs, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6) - if err == nil { - for _, addr := range hostAddrs { - if addr.IP.IsLinkLocalUnicast() { - // Add route to Mycelium network via host veth - route := &netlink.Route{ - Dst: &net.IPNet{ - IP: net.ParseIP("400::"), - Mask: net.CIDRMask(7, 128), - }, - Gw: addr.IP, - LinkIndex: link.Attrs().Index, - } - netlink.RouteAdd(route) - break - } - } - } + // Add route to Mycelium network via host veth link-local address + route := &netlink.Route{ + Dst: &net.IPNet{ + IP: net.ParseIP("400::"), + Mask: net.CIDRMask(7, 128), + }, + Gw: hostLinkLocal, + LinkIndex: link.Attrs().Index, + } + if err := netlink.RouteAdd(route); err != nil { + return fmt.Errorf("failed to add route to 400::/7: %v", err) } return nil @@ -254,3 +251,30 @@ func configureHostInterface(hostVeth netlink.Link, containerIP net.IP) error { return netlink.RouteAdd(route) } + +func getHostVethLinkLocal(hostVeth netlink.Link) (net.IP, error) { + addrs, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6) + if err != nil { + return nil, fmt.Errorf("failed to get addresses for host veth: %v", err) + } + + for _, addr := range addrs { + if addr.IP.IsLinkLocalUnicast() { + return addr.IP, nil + } + } + + return nil, fmt.Errorf("no link-local address found on host veth") +} + +func getHostVethLinkLocalWithRetry(hostVeth netlink.Link) (net.IP, error) { + // Retry for up to 5 seconds, checking every 100ms + for i := 0; i < 50; i++ { + ip, err := getHostVethLinkLocal(hostVeth) + if err == nil { + return ip, nil + } + time.Sleep(100 * time.Millisecond) + } + return nil, fmt.Errorf("timeout waiting for host veth link-local address") +}