From 494cd07f722d6bf5f2e69a6d2d729848882e1971 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 19 Sep 2013 10:57:11 +0200 Subject: [PATCH] network: Stop shelling out to /sbin/ip We have our own netlink version of all the required calls now, so we can just skip the /sbin/ip dependency. --- network.go | 66 +++++++++++++++---------------------------------- network_test.go | 13 +++++----- 2 files changed, 27 insertions(+), 52 deletions(-) diff --git a/network.go b/network.go index c3f3253aee..5ea76daaff 100644 --- a/network.go +++ b/network.go @@ -6,12 +6,11 @@ import ( "fmt" "github.com/dotcloud/docker/iptables" "github.com/dotcloud/docker/proxy" + "github.com/dotcloud/docker/netlink" "github.com/dotcloud/docker/utils" "log" "net" - "os/exec" "strconv" - "strings" "sync" ) @@ -68,42 +67,10 @@ func networkSize(mask net.IPMask) int32 { return int32(binary.BigEndian.Uint32(m)) + 1 } -//Wrapper around the ip command -func ip(args ...string) (string, error) { - path, err := exec.LookPath("ip") - if err != nil { - return "", fmt.Errorf("command not found: ip") - } - output, err := exec.Command(path, args...).CombinedOutput() - if err != nil { - return "", fmt.Errorf("ip failed: ip %v", strings.Join(args, " ")) - } - return string(output), nil -} - -func checkRouteOverlaps(routes string, dockerNetwork *net.IPNet) error { - utils.Debugf("Routes:\n\n%s", routes) - for _, line := range strings.Split(routes, "\n") { - if strings.Trim(line, "\r\n\t ") == "" || strings.Contains(line, "default") { - continue - } - _, network, err := net.ParseCIDR(strings.Split(line, " ")[0]) - if err != nil { - // is this a mask-less IP address? - if ip := net.ParseIP(strings.Split(line, " ")[0]); ip == nil { - // fail only if it's neither a network nor a mask-less IP address - return fmt.Errorf("Unexpected ip route output: %s (%s)", err, line) - } else { - _, network, err = net.ParseCIDR(ip.String() + "/32") - if err != nil { - return err - } - } - } - if err == nil && network != nil { - if networkOverlaps(dockerNetwork, network) { - return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork, line) - } +func checkRouteOverlaps(networks []*net.IPNet, dockerNetwork *net.IPNet) error { + for _, network := range networks { + if networkOverlaps(dockerNetwork, network) { + return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork, network) } } return nil @@ -139,7 +106,7 @@ func CreateBridgeIface(config *DaemonConfig) error { if err != nil { return err } - routes, err := ip("route") + routes, err := netlink.NetworkGetRoutes() if err != nil { return err } @@ -155,15 +122,22 @@ func CreateBridgeIface(config *DaemonConfig) error { } utils.Debugf("Creating bridge %s with network %s", config.BridgeIface, ifaceAddr) - if output, err := ip("link", "add", config.BridgeIface, "type", "bridge"); err != nil { - return fmt.Errorf("Error creating bridge: %s (output: %s)", err, output) + if err := netlink.NetworkLinkAdd(config.BridgeIface, "bridge"); err != nil { + return fmt.Errorf("Error creating bridge: %s", err) } - - if output, err := ip("addr", "add", ifaceAddr, "dev", config.BridgeIface); err != nil { - return fmt.Errorf("Unable to add private network: %s (%s)", err, output) + iface, err := net.InterfaceByName(config.BridgeIface) + if err != nil { + return err } - if output, err := ip("link", "set", config.BridgeIface, "up"); err != nil { - return fmt.Errorf("Unable to start network bridge: %s (%s)", err, output) + ipAddr, ipNet, err := net.ParseCIDR(ifaceAddr) + if err != nil { + return err + } + if netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil { + return fmt.Errorf("Unable to add private network: %s", err) + } + if err := netlink.NetworkLinkUp(iface); err != nil { + return fmt.Errorf("Unable to start network bridge: %s", err) } if config.EnableIptables { diff --git a/network_test.go b/network_test.go index a0492b4907..7304e205a5 100644 --- a/network_test.go +++ b/network_test.go @@ -277,12 +277,13 @@ func TestNetworkOverlaps(t *testing.T) { } func TestCheckRouteOverlaps(t *testing.T) { - routes := `default via 10.0.2.2 dev eth0 -10.0.2.0 dev eth0 proto kernel scope link src 10.0.2.15 -10.0.3.0/24 dev lxcbr0 proto kernel scope link src 10.0.3.1 -10.0.42.0/24 dev testdockbr0 proto kernel scope link src 10.0.42.1 -172.16.42.0/24 dev docker0 proto kernel scope link src 172.16.42.1 -192.168.142.0/24 dev eth1 proto kernel scope link src 192.168.142.142` + routesData := []string{"10.0.2.0/32", "10.0.3.0/24", "10.0.42.0/24", "172.16.42.0/24", "192.168.142.0/24"} + + routes := []*net.IPNet{} + for _, addr := range routesData { + _, netX, _ := net.ParseCIDR(addr) + routes = append(routes, netX) + } _, netX, _ := net.ParseCIDR("172.16.0.1/24") if err := checkRouteOverlaps(routes, netX); err != nil {