func (n *network) initSandbox() error { n.Lock() n.initEpoch++ n.Unlock() sbox, err := osl.NewSandbox( osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), true) if err != nil { return fmt.Errorf("could not create network sandbox: %v", err) } n.setSandbox(sbox) n.driver.peerDbUpdateSandbox(n.id) var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) go n.watchMiss(nlSock) return nil }
// LinkSubscribe takes a chan down which notifications will be sent // when links change. Close the 'done' chan to stop subscription. func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) if err != nil { return err } if done != nil { go func() { <-done s.Close() }() } go func() { defer close(ch) for { msgs, err := s.Receive() if err != nil { return } for _, m := range msgs { ifmsg := nl.DeserializeIfInfomsg(m.Data) link, err := linkDeserialize(m.Data) if err != nil { return } ch <- LinkUpdate{IfInfomsg: *ifmsg, Link: link} } } }() return nil }
// RouteSubscribe takes a chan down which notifications will be sent // when routes are added or deleted. Close the 'done' chan to stop subscription. func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE) if err != nil { return err } if done != nil { go func() { <-done s.Close() }() } go func() { defer close(ch) for { msgs, err := s.Receive() if err != nil { return } for _, m := range msgs { route, err := deserializeRoute(m.Data) if err != nil { return } ch <- RouteUpdate{Type: m.Header.Type, Route: route} } } }() return nil }
func (n *network) initSandbox() error { n.Lock() n.initEpoch++ n.Unlock() sbox, err := osl.NewSandbox( osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), true) if err != nil { return fmt.Errorf("could not create network sandbox: %v", err) } // Add a bridge inside the namespace if err := sbox.AddInterface("bridge1", "br", sbox.InterfaceOptions().Address(bridgeIP), sbox.InterfaceOptions().Bridge(true)); err != nil { return fmt.Errorf("could not create bridge inside the network sandbox: %v", err) } n.setSandbox(sbox) var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) go n.watchMiss(nlSock) return n.initVxlan() }
func (n *network) initSandbox(restore bool) error { n.Lock() n.initEpoch++ n.Unlock() networkOnce.Do(networkOnceInit) if !restore { if hostMode { if err := addNetworkChain(n.id[:12]); err != nil { return err } } // If there are any stale sandboxes related to this network // from previous daemon life clean it up here n.cleanupStaleSandboxes() } // In the restore case network sandbox already exist; but we don't know // what epoch number it was created with. It has to be retrieved by // searching the net namespaces. key := "" if restore { key = osl.GenerateKey("-" + n.id) } else { key = osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch) + n.id) } sbox, err := osl.NewSandbox(key, !hostMode, restore) if err != nil { return fmt.Errorf("could not get network sandbox (oper %t): %v", restore, err) } n.setSandbox(sbox) if !restore { n.driver.peerDbUpdateSandbox(n.id) } var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) if nlSock != nil { go n.watchMiss(nlSock) } return nil }
// Wait for an interface to come up. func EnsureInterface(ifaceName string) (*net.Interface, error) { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) if err != nil { return nil, err } defer s.Close() iface, err := ensureInterface(s, ifaceName) if err != nil { return nil, err } return iface, err }
func (n *network) initSandbox() error { n.Lock() n.initEpoch++ n.Unlock() sbox, err := sandbox.NewSandbox( sandbox.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+string(n.id)), true) if err != nil { return fmt.Errorf("could not create network sandbox: %v", err) } // Add a bridge inside the namespace if err := sbox.AddInterface("bridge1", "br", sbox.InterfaceOptions().Address(bridgeIP), sbox.InterfaceOptions().Bridge(true)); err != nil { return fmt.Errorf("could not create bridge inside the network sandbox: %v", err) } vxlanName, err := createVxlan(n.vxlanID()) if err != nil { return err } if err := sbox.AddInterface(vxlanName, "vxlan", sbox.InterfaceOptions().Master("bridge1")); err != nil { return fmt.Errorf("could not add vxlan interface inside the network sandbox: %v", err) } n.vxlanName = vxlanName n.setSandbox(sbox) n.driver.peerDbUpdateSandbox(n.id) var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) go n.watchMiss(nlSock) return 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) { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_ROUTE) if err != nil { return nil, err } defer s.Close() iface, err := ensureInterface(s, ifaceName) if err != nil { return nil, err } dest := net.IPv4(224, 0, 0, 0) if CheckRouteExists(ifaceName, dest) { return iface, err } netlinkReceiveUntil(s, matchRoute(ifaceName, dest)) return iface, err }
func (n *network) initSandbox() error { n.Lock() n.initEpoch++ n.Unlock() networkOnce.Do(networkOnceInit) if hostMode { if err := addNetworkChain(n.id[:12]); err != nil { return err } } // If there are any stale sandboxes related to this network // from previous daemon life clean it up here n.cleanupStaleSandboxes() sbox, err := osl.NewSandbox( osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), !hostMode) if err != nil { return fmt.Errorf("could not create network sandbox: %v", err) } n.setSandbox(sbox) n.driver.peerDbUpdateSandbox(n.id) var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) if nlSock != nil { go n.watchMiss(nlSock) } return nil }
func (dev *vxlanDevice) MonitorMisses(misses chan *netlink.Neigh) { nlsock, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { log.Error("Failed to subscribe to netlink RTNLGRP_NEIGH messages") return } for { msgs, err := nlsock.Receive() if err != nil { log.Errorf("Failed to receive from netlink: %v ", err) time.Sleep(1 * time.Second) continue } for _, msg := range msgs { dev.processNeighMsg(msg, misses) } } }
// AddrSubscribe takes a chan down which notifications will be sent // when addresses change. Close the 'done' chan to stop subscription. func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR) if err != nil { return err } if done != nil { go func() { <-done s.Close() }() } go func() { defer close(ch) for { msgs, err := s.Receive() if err != nil { log.Printf("netlink.AddrSubscribe: Receive() error: %v", err) return } for _, m := range msgs { msgType := m.Header.Type if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR { log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType) continue } addr, _, ifindex, err := parseAddr(m.Data) if err != nil { log.Printf("netlink.AddrSubscribe: could not parse address: %v", err) continue } ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: ifindex, NewAddr: msgType == syscall.RTM_NEWADDR} } } }() return nil }
func (*nl) Subscribe(protocol int, groups ...uint) (NLSocket, error) { return vish_nl.Subscribe(protocol, groups...) }
func (u *NetLinkProbe) start() { s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK) if err != nil { logging.GetLogger().Errorf("Failed to subscribe to netlink RTNLGRP_LINK messages: %s", err.Error()) return } u.nlSocket = s defer u.nlSocket.Close() fd := u.nlSocket.GetFd() err = syscall.SetNonblock(fd, true) if err != nil { logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error()) return } epfd, e := syscall.EpollCreate1(0) if e != nil { logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error()) return } defer syscall.Close(epfd) u.initialize() event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)} if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil { logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error()) return } events := make([]syscall.EpollEvent, maxEpollEvents) for u.running.Load() == true { n, err := syscall.EpollWait(epfd, events[:], 1000) if err != nil { errno, ok := err.(syscall.Errno) if ok && errno != syscall.EINTR { logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error()) } continue } if n == 0 { continue } msgs, err := s.Receive() if err != nil { logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error()) time.Sleep(1 * time.Second) continue } for _, msg := range msgs { switch msg.Header.Type { case syscall.RTM_NEWLINK: ifmsg := nl.DeserializeIfInfomsg(msg.Data) u.onLinkAdded(int(ifmsg.Index)) case syscall.RTM_DELLINK: ifmsg := nl.DeserializeIfInfomsg(msg.Data) u.onLinkDeleted(int(ifmsg.Index)) } } } }
func (u *NetLinkProbe) start(nsPath string) { var context *common.NetNSContext var err error // Enter the network namespace if necessary if nsPath != "" { context, err = common.NewNetNsContext(nsPath) if err != nil { logging.GetLogger().Errorf("Failed to switch namespace: %s", err.Error()) return } } // Both NewHandle and Subscribe need to done in the network namespace. h, err := netlink.NewHandle(syscall.NETLINK_ROUTE) if err != nil { logging.GetLogger().Errorf("Failed to create netlink handle: %s", err.Error()) context.Close() return } defer h.Delete() s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR) if err != nil { logging.GetLogger().Errorf("Failed to subscribe to netlink messages: %s", err.Error()) context.Close() return } defer s.Close() u.ethtool, err = ethtool.NewEthtool() if err != nil { logging.GetLogger().Errorf("Failed to create ethtool object: %s", err.Error()) context.Close() return } defer u.ethtool.Close() epfd, e := syscall.EpollCreate1(0) if e != nil { logging.GetLogger().Errorf("Failed to create epoll: %s", err.Error()) return } defer syscall.Close(epfd) // Leave the network namespace context.Close() u.wg.Add(1) defer u.wg.Done() atomic.StoreInt64(&u.state, common.RunningState) defer atomic.StoreInt64(&u.state, common.StoppedState) u.netlink = h u.initialize() fd := s.GetFd() err = syscall.SetNonblock(fd, true) if err != nil { logging.GetLogger().Errorf("Failed to set the netlink fd as non-blocking: %s", err.Error()) return } event := syscall.EpollEvent{Events: syscall.EPOLLIN, Fd: int32(fd)} if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil { logging.GetLogger().Errorf("Failed to control epoll: %s", err.Error()) return } events := make([]syscall.EpollEvent, maxEpollEvents) for atomic.LoadInt64(&u.state) == common.RunningState { n, err := syscall.EpollWait(epfd, events[:], 1000) if err != nil { errno, ok := err.(syscall.Errno) if ok && errno != syscall.EINTR { logging.GetLogger().Errorf("Failed to receive from events from netlink: %s", err.Error()) } continue } if n == 0 { continue } msgs, err := s.Receive() if err != nil { if errno, ok := err.(syscall.Errno); !ok || !errno.Temporary() { logging.GetLogger().Errorf("Failed to receive from netlink messages: %s", err.Error()) return } time.Sleep(1 * time.Second) continue } for _, msg := range msgs { switch msg.Header.Type { case syscall.RTM_NEWLINK: link, err := netlink.LinkDeserialize(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error()) continue } u.onLinkAdded(link) case syscall.RTM_DELLINK: link, err := netlink.LinkDeserialize(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to deserialize netlink message: %s", err.Error()) continue } u.onLinkDeleted(link) case syscall.RTM_NEWADDR: addr, family, ifindex, err := parseAddr(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error()) continue } u.onAddressAdded(addr, family, ifindex) case syscall.RTM_DELADDR: addr, family, ifindex, err := parseAddr(msg.Data) if err != nil { logging.GetLogger().Warningf("Failed to parse newlink message: %s", err.Error()) continue } u.onAddressDeleted(addr, family, ifindex) } } } }