// Do post-attach configuration of all veths we have created func ConfigureARPforVeths(processID int, prefix string) error { _, err := FindNetDevs(processID, func(link netlink.Link) bool { ifName := link.Attrs().Name if strings.HasPrefix(ifName, prefix) { weavenet.ConfigureARPCache(ifName) if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil { for _, addr := range addrs { arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName) } } } return false }) return err }
func main() { flag.Parse() if *helpFlag { printHelpAndExit() } if *verboseFlag { arping.EnableVerboseLog() } arping.SetTimeout(*timeoutFlag) if len(flag.Args()) != 1 { fmt.Println("Parameter <IP> missing!") printHelpAndExit() } dstIP := net.ParseIP(flag.Arg(0)) var hwAddr net.HardwareAddr var durationNanos time.Duration var err error if *gratuitousFlag { if len(*ifaceNameFlag) > 0 { err = arping.GratuitousArpOverIfaceByName(dstIP, *ifaceNameFlag) } else { err = arping.GratuitousArp(dstIP) } } else { if len(*ifaceNameFlag) > 0 { hwAddr, durationNanos, err = arping.PingOverIfaceByName(dstIP, *ifaceNameFlag) } else { hwAddr, durationNanos, err = arping.Ping(dstIP) } } // ping timeout if err == arping.ErrTimeout { fmt.Println(err) os.Exit(1) } // ping failed if err != nil { fmt.Println(err) os.Exit(2) } if *gratuitousFlag { os.Exit(0) } // ping success durationMicros := durationNanos / 1000 var durationString string if durationMicros > 1000 { durationString = fmt.Sprintf("%d,%03d", durationMicros/1000, durationMicros%1000) } else { durationString = fmt.Sprintf("%d", durationMicros) } fmt.Printf("%s (%s) %s usec\n", dstIP, hwAddr, durationString) os.Exit(0) }
func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error { ipt, err := iptables.New() if err != nil { return err } if !interfaceExistsInNamespace(ns, ifName) { maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl") if len(id) > maxIDLen { id = id[:maxIDLen] // trim passed ID if too long } name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id _, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error { if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil { return fmt.Errorf("failed to move veth to container netns: %s", err) } if err := WithNetNSUnsafe(ns, func() error { if err := netlink.LinkSetName(veth, ifName); err != nil { return err } if err := ConfigureARPCache(ifName); err != nil { return err } if err := ipt.Append("filter", "INPUT", "-i", ifName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil { return err } return nil }); err != nil { return fmt.Errorf("error setting up interface: %s", err) } return nil }) if err != nil { return err } } if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error { newAddresses, err := AddAddresses(veth, cidrs) if err != nil { return err } // Add multicast ACCEPT rules for new subnets for _, ipnet := range newAddresses { acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"} exists, err := ipt.Exists("filter", "INPUT", acceptRule...) if err != nil { return err } if !exists { if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil { return err } } } if err := netlink.LinkSetUp(veth); err != nil { return err } for _, ipnet := range newAddresses { // If we don't wait for a bit here, we see the arp fail to reach the bridge. time.Sleep(1 * time.Millisecond) arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName) } if withMulticastRoute { /* Route multicast packets across the weave network. This must come last in 'attach'. If you change this, change weavewait to match. TODO: Add the MTU lock to prevent PMTU discovery for multicast destinations. Without that, the kernel sets the DF flag on multicast packets. Since RFC1122 prohibits sending of ICMP errors for packets with multicast destinations, that causes packets larger than the PMTU to be dropped silently. */ _, multicast, _ := net.ParseCIDR("224.0.0.0/4") if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil { return err } } return nil }); err != nil { return err } return nil }