// Wait for an interface to come up and have a route added to the multicast subnet. // This matches the behaviour in 'weave attach', which is the only context in which // we expect this to be called. If you change one, change the other to match. func EnsureInterfaceAndMcastRoute(ifaceName string) (*net.Interface, error) { iface, err := ensureInterface(ifaceName) if err != nil { return nil, err } ch := make(chan netlink.RouteUpdate) done := make(chan struct{}) defer close(done) if err := netlink.RouteSubscribe(ch, done); err != nil { return nil, err } dest := net.IPv4(224, 0, 0, 0) check := func(route netlink.Route) bool { return route.LinkIndex == iface.Index && route.Dst != nil && route.Dst.IP.Equal(dest) } // check for currently-existing route after subscribing, to avoid race routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) if err != nil { return nil, err } for _, route := range routes { if check(route) { return iface, nil } } for update := range ch { if check(update.Route) { return iface, nil } } // should never get here return iface, nil }
// Wait for an interface to come up and have a route added to the multicast subnet. // This matches the behaviour in 'weave attach', which is the only context in which // we expect this to be called. If you change one, change the other to match. func EnsureInterfaceAndMcastRoute(ifaceName string) (*net.Interface, error) { iface, err := ensureInterface(ifaceName) if err != nil { return nil, err } dest := net.IPv4(224, 0, 0, 0) if CheckRouteExists(ifaceName, dest) { return iface, err } ch := make(chan netlink.RouteUpdate) done := make(chan struct{}) defer close(done) if err := netlink.RouteSubscribe(ch, done); err != nil { return nil, err } for update := range ch { link, _ := netlink.LinkByIndex(update.Route.LinkIndex) if link.Attrs().Name == ifaceName && update.Route.Dst.IP.Equal(dest) { break } } return iface, nil }
// This function should be put into the main process or somewhere that can be // use to init the network namespace trap. func setupNetworkNsTrap(netNs2Containerd func(supervisor.NetlinkUpdate)) { // Subscribe for links change event chLink := make(chan netlink.LinkUpdate) doneLink := make(chan struct{}) defer close(doneLink) if err := netlink.LinkSubscribe(chLink, doneLink); err != nil { glog.Fatal(err) } // Subscribe for addresses change event chAddr := make(chan netlink.AddrUpdate) doneAddr := make(chan struct{}) defer close(doneAddr) if err := netlink.AddrSubscribe(chAddr, doneAddr); err != nil { glog.Fatal(err) } // Subscribe for route change event chRoute := make(chan netlink.RouteUpdate) doneRoute := make(chan struct{}) defer close(doneRoute) if err := netlink.RouteSubscribe(chRoute, doneRoute); err != nil { glog.Fatal(err) } for { select { case updateLink := <-chLink: handleLink(updateLink, netNs2Containerd) case updateAddr := <-chAddr: handleAddr(updateAddr, netNs2Containerd) case updateRoute := <-chRoute: handleRoute(updateRoute, netNs2Containerd) } } }