diff --git a/net/arp.go b/net/arp.go index 8315db94..39322b9a 100644 --- a/net/arp.go +++ b/net/arp.go @@ -1,5 +1,6 @@ package net +import "path/filepath" import "fmt" import "io" import "os" @@ -7,21 +8,21 @@ import "os" // Configure the ARP cache parameters for the given interface. This // makes containers react more quickly to a change in the MAC address // associated with an IP address. -func ConfigureARPCache(name string) error { - if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil { +func ConfigureARPCache(procPath, name string) error { + if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil { return err } - if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil { + if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil { return err } - if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1"); err != nil { + if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1"); err != nil { return err } return nil } -func sysctl(variable, value string) error { - f, err := os.OpenFile(fmt.Sprintf("/proc/sys/%s", variable), os.O_WRONLY, 0) +func sysctl(procPath, variable, value string) error { + f, err := os.OpenFile(filepath.Join(procPath, "/sys/", variable), os.O_WRONLY, 0) if err != nil { return err } diff --git a/net/bridge.go b/net/bridge.go index c0514e50..a5949b63 100644 --- a/net/bridge.go +++ b/net/bridge.go @@ -4,6 +4,7 @@ import ( "fmt" "io/ioutil" "net" + "path/filepath" "github.com/Sirupsen/logrus" "github.com/coreos/go-iptables/iptables" @@ -71,7 +72,7 @@ func DetectBridgeType(weaveBridgeName, datapathName string) BridgeType { var ErrSetBridgeMac = errors.New("Setting $DOCKER_BRIDGE MAC (mitigate https://github.com/docker/docker/issues/14908)") func EnforceAddrAssignType(bridgeName string) error { - sysctlFilename := fmt.Sprintf("/sys/class/net/%s/addr_assign_type", bridgeName) + sysctlFilename := filepath.Join("/sys/class/net/", bridgeName, "/addr_assign_type") addrAssignType, err := ioutil.ReadFile(sysctlFilename) if err != nil { return errors.Wrapf(err, "reading %q", sysctlFilename) @@ -186,7 +187,7 @@ type BridgeConfig struct { Port int } -func CreateBridge(config *BridgeConfig) (BridgeType, error) { +func CreateBridge(procPath string, config *BridgeConfig) (BridgeType, error) { bridgeType := DetectBridgeType(config.WeaveBridgeName, config.DatapathName) if bridgeType == None { @@ -231,13 +232,13 @@ func CreateBridge(config *BridgeConfig) (BridgeType, error) { // Set proxy_arp on the bridge, so that it could accept packets destined // to containers within the same subnet but running on remote hosts. // Without it, exact routes on each container are required. - if err := sysctl("net/ipv4/conf/"+config.WeaveBridgeName+"/proxy_arp", "1"); err != nil { + if err := sysctl(procPath, "net/ipv4/conf/"+config.WeaveBridgeName+"/proxy_arp", "1"); err != nil { return bridgeType, errors.Wrap(err, "setting proxy_arp") } // Avoid delaying the first ARP request. Also, setting it to 0 avoids // placing the request into a bounded queue as it can be seen: // https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/net/ipv4/arp.c?id=refs/tags/v4.6.1#n819 - if err := sysctl("net/ipv4/neigh/"+config.WeaveBridgeName+"/proxy_delay", "0"); err != nil { + if err := sysctl(procPath, "net/ipv4/neigh/"+config.WeaveBridgeName+"/proxy_delay", "0"); err != nil { return bridgeType, errors.Wrap(err, "setting proxy_arp") } } @@ -252,7 +253,7 @@ func CreateBridge(config *BridgeConfig) (BridgeType, error) { return bridgeType, err } - if err := ConfigureARPCache(config.WeaveBridgeName); err != nil { + if err := ConfigureARPCache(procPath, config.WeaveBridgeName); err != nil { return bridgeType, errors.Wrapf(err, "configuring ARP cache on bridge %q", config.WeaveBridgeName) } diff --git a/plugin/net/watcher.go b/plugin/net/watcher.go index 736751d7..9a795611 100644 --- a/plugin/net/watcher.go +++ b/plugin/net/watcher.go @@ -53,7 +53,7 @@ func (w *watcher) ContainerStarted(id string) { rootDir = "/host" } netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid) - if _, err := weavenet.WithNetNS(netNSPath, "configure-arp", weavenet.VethName); err != nil { + if _, err := weavenet.WithNetNS(netNSPath, "configure-arp", weavenet.VethName, rootDir); err != nil { w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err) } } diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 773f6939..3da99359 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -147,6 +147,7 @@ func main() { trustedSubnetStr string dbPrefix string hostRoot string + procPath string discoveryEndpoint string token string advertiseAddress string @@ -197,6 +198,7 @@ func main() { mflag.BoolVar(&bridgeConfig.NoFastdp, []string{"-no-fastdp"}, false, "Disable Fast Datapath") mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation") mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data") + mflag.StringVar(&procPath, []string{"-proc-path"}, "/proc", "path to reach host /proc filesystem") mflag.BoolVar(&bridgeConfig.IsAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing") mflag.StringVar(&hostRoot, []string{"-host-root"}, "", "path to reach host filesystem") mflag.StringVar(&discoveryEndpoint, []string{"-peer-discovery-url"}, "https://cloud.weave.works/api/net", "url for peer discovery") @@ -256,7 +258,7 @@ func main() { name := peerName(routerName, bridgeConfig.WeaveBridgeName, dbPrefix, hostRoot) bridgeConfig.Mac = name.String() - bridgeType, err := weavenet.CreateBridge(&bridgeConfig) + bridgeType, err := weavenet.CreateBridge(procPath, &bridgeConfig) checkFatal(err) Log.Println("Bridge type is", bridgeType) diff --git a/prog/weaveutil/bridge.go b/prog/weaveutil/bridge.go index 0b63b336..9c38c815 100644 --- a/prog/weaveutil/bridge.go +++ b/prog/weaveutil/bridge.go @@ -17,8 +17,8 @@ func detectBridgeType(args []string) error { } func createBridge(args []string) error { - if len(args) != 9 { - cmdUsage("create-bridge", " ") + if len(args) != 10 { + cmdUsage("create-bridge", " ") } mtu, err := strconv.Atoi(args[3]) @@ -38,9 +38,10 @@ func createBridge(args []string) error { Mac: args[5], NoFastdp: args[6] != "", NoBridgedFastdp: args[7] != "", - ExpectNPC: args[8] == "--expect-npc", + ExpectNPC: args[9] == "--expect-npc", } - bridgeType, err := weavenet.CreateBridge(&config) + procPath := args[8] + bridgeType, err := weavenet.CreateBridge(procPath, &config) fmt.Println(bridgeType.String()) return err } diff --git a/prog/weaveutil/netdev.go b/prog/weaveutil/netdev.go index d35e395b..457e30e3 100644 --- a/prog/weaveutil/netdev.go +++ b/prog/weaveutil/netdev.go @@ -60,7 +60,8 @@ func setupIface(args []string) error { if err := netlink.LinkSetName(link, newIfName); err != nil { return err } - if err := weavenet.ConfigureARPCache(newIfName); err != nil { + // This is only called by AttachContainer which is only called in host pid namespace + if err := weavenet.ConfigureARPCache("/proc", newIfName); err != nil { return err } if err := ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil { @@ -71,10 +72,11 @@ func setupIface(args []string) error { } func configureARP(args []string) error { - if len(args) != 1 { - cmdUsage("configure-arp", "") + if len(args) != 2 { + cmdUsage("configure-arp", " ") } prefix := args[0] + rootPath := args[1] links, err := netlink.LinkList() if err != nil { @@ -83,7 +85,7 @@ func configureARP(args []string) error { for _, link := range links { ifName := link.Attrs().Name if strings.HasPrefix(ifName, prefix) { - weavenet.ConfigureARPCache(ifName) + weavenet.ConfigureARPCache(rootPath+"/proc", ifName) if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil { for _, addr := range addrs { arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName) diff --git a/weave b/weave index b79fe4e1..95d7673b 100755 --- a/weave +++ b/weave @@ -429,7 +429,7 @@ try_create_bridge() { WEAVEDB_DIR_PATH="$HOST_ROOT/$(docker inspect -f '{{with index .Mounts 0}}{{.Source}}{{end}}' $DB_CONTAINER_NAME 2>/dev/null)" fi MAC=$(util_op unique-id "$WEAVEDB_DIR_PATH/weave" "$HOST_ROOT") - BRIDGE_TYPE=$(util_op create-bridge "$DOCKER_BRIDGE" "$BRIDGE" "$DATAPATH" "$WEAVE_MTU" "$PORT" "$MAC" "$WEAVE_NO_FASTDP" "$WEAVE_NO_BRIDGED_FASTDP" "$1") + BRIDGE_TYPE=$(util_op create-bridge "$DOCKER_BRIDGE" "$BRIDGE" "$DATAPATH" "$WEAVE_MTU" "$PORT" "$MAC" "$WEAVE_NO_FASTDP" "$WEAVE_NO_BRIDGED_FASTDP" "$PROC_PATH" "$1") # Set some variables that are expected by code that comes later [ "$BRIDGE_TYPE" != "fastdp" ] || DATAPATH="$BRIDGE" MTU=${WEAVE_MTU:-$(cat /sys/class/net/$BRIDGE/mtu)}