Compare commits

..

2 Commits

Author SHA1 Message Date
Scott Yeager
0618b41ae2 Ensure unique veth name and myc ip per container 2025-06-20 19:57:47 -07:00
Scott Yeager
9bdaf13797 Fix namespacing 2025-06-20 19:51:10 -07:00

62
main.go
View File

@ -1,6 +1,8 @@
package main package main
import ( import (
"crypto/sha256"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
@ -46,8 +48,8 @@ func cmdAdd(args *skel.CmdArgs) error {
return fmt.Errorf("failed to get Mycelium IP: %v", err) return fmt.Errorf("failed to get Mycelium IP: %v", err)
} }
// Create veth pair // Create veth pair with unique naming
hostVethName := fmt.Sprintf("veth-%s", args.ContainerID[:8]) hostVethName := generateVethName(args.ContainerID)
containerVethName := "eth0" containerVethName := "eth0"
hostVeth, containerVeth, err := createVethPair(hostVethName, containerVethName) hostVeth, containerVeth, err := createVethPair(hostVethName, containerVethName)
@ -101,7 +103,7 @@ func cmdCheck(args *skel.CmdArgs) error {
func cmdDel(args *skel.CmdArgs) error { func cmdDel(args *skel.CmdArgs) error {
// Clean up veth pair (host side will be automatically removed) // Clean up veth pair (host side will be automatically removed)
hostVethName := fmt.Sprintf("veth-%s", args.ContainerID[:8]) hostVethName := generateVethName(args.ContainerID)
link, err := netlink.LinkByName(hostVethName) link, err := netlink.LinkByName(hostVethName)
if err != nil { if err != nil {
@ -146,14 +148,25 @@ func getMyceliumIP(interfaceName string) (net.IP, error) {
} }
func generateContainerIP(myceliumPrefix net.IP, containerID string) net.IP { func generateContainerIP(myceliumPrefix net.IP, containerID string) net.IP {
// Generate a container IP within the /64 prefix // Generate a unique container IP within the /64 prefix using container ID hash
// Using simple approach: prefix + ::1 (could be made more sophisticated) hash := sha256.Sum256([]byte(containerID))
containerIP := make(net.IP, len(myceliumPrefix)) containerIP := make(net.IP, len(myceliumPrefix))
copy(containerIP, myceliumPrefix) copy(containerIP, myceliumPrefix)
containerIP[15] = 1 // Set last byte to 1
// Use first 8 bytes of hash for the host part (last 64 bits)
copy(containerIP[8:], hash[:8])
return containerIP return containerIP
} }
func generateVethName(containerID string) string {
// Generate unique but short veth name using hash of container ID
hash := sha256.Sum256([]byte(containerID))
shortHash := hex.EncodeToString(hash[:4]) // Use first 4 bytes for 8-char hex
return fmt.Sprintf("veth-%s", shortHash)
}
func createVethPair(hostName, containerName string) (netlink.Link, netlink.Link, error) { func createVethPair(hostName, containerName string) (netlink.Link, netlink.Link, error) {
veth := &netlink.Veth{ veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{Name: hostName}, LinkAttrs: netlink.LinkAttrs{Name: hostName},
@ -216,26 +229,47 @@ func configureContainerInterface(containerNS netns.NsHandle, ifName string, cont
return err return err
} }
// Get host veth link-local address for routing // Switch to main namespace to get host veth address
if err := netns.Set(originalNS); err != nil {
return err
}
// Get host veth link-local address
hostVeth, err := netlink.LinkByName(hostVethName) hostVeth, err := netlink.LinkByName(hostVethName)
if err == nil { if err != nil {
return err
}
hostAddrs, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6) hostAddrs, err := netlink.AddrList(hostVeth, netlink.FAMILY_V6)
if err == nil { if err != nil {
return err
}
var hostLLAddr net.IP
for _, addr := range hostAddrs { for _, addr := range hostAddrs {
if addr.IP.IsLinkLocalUnicast() { if addr.IP.IsLinkLocalUnicast() {
hostLLAddr = addr.IP
break
}
}
// Switch back to container namespace to add route
if err := netns.Set(containerNS); err != nil {
return err
}
if hostLLAddr != nil {
// Add route to Mycelium network via host veth // Add route to Mycelium network via host veth
route := &netlink.Route{ route := &netlink.Route{
Dst: &net.IPNet{ Dst: &net.IPNet{
IP: net.ParseIP("400::"), IP: net.ParseIP("400::"),
Mask: net.CIDRMask(7, 128), Mask: net.CIDRMask(7, 128),
}, },
Gw: addr.IP, Gw: hostLLAddr,
LinkIndex: link.Attrs().Index, LinkIndex: link.Attrs().Index,
} }
netlink.RouteAdd(route) if err := netlink.RouteAdd(route); err != nil {
break return err
}
}
} }
} }