diff --git a/net/route.go b/net/route.go index 6d1722ad..463f843b 100644 --- a/net/route.go +++ b/net/route.go @@ -9,17 +9,13 @@ import ( // A network is considered free if it does not overlap any existing // routes on this host. This is the same approach taken by Docker. -func CheckNetworkFree(subnet *net.IPNet) error { - routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) - if err != nil { - return err - } - for _, route := range routes { +func CheckNetworkFree(subnet *net.IPNet, ignoreIfaceNames map[string]struct{}) error { + return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error { if route.Dst != nil && overlaps(route.Dst, subnet) { return fmt.Errorf("Network %s overlaps with existing route %s on host.", subnet, route.Dst) } - } - return nil + return nil + }) } // Two networks overlap if the start-point of one is inside the other. @@ -29,14 +25,28 @@ func overlaps(n1, n2 *net.IPNet) bool { // For a specific address, we only care if it is actually *inside* an // existing route, because weave-local traffic never hits IP routing. -func CheckAddressOverlap(addr net.IP) error { +func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) error { + return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error { + if route.Dst != nil && route.Dst.Contains(addr) { + return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) + } + return nil + }) +} + +func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(netlink.Route) error) error { routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) if err != nil { return err } for _, route := range routes { - if route.Dst != nil && route.Dst.Contains(addr) { - return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) + if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil { + if _, found := ignoreIfaceNames[link.Attrs().Name]; found { + continue + } + } + if err := check(route); err != nil { + return err } } return nil diff --git a/prog/netcheck/netcheck.go b/prog/netcheck/netcheck.go index 96a26ed4..fe822f2e 100644 --- a/prog/netcheck/netcheck.go +++ b/prog/netcheck/netcheck.go @@ -6,6 +6,7 @@ import ( "net" "os" + "github.com/docker/docker/pkg/mflag" weavenet "github.com/weaveworks/weave/net" ) @@ -14,20 +15,37 @@ func fatal(err error) { os.Exit(1) } +type stringList map[string]struct{} + +func (ss *stringList) Set(value string) error { + (*ss)[value] = struct{}{} + return nil +} + +func (ss *stringList) String() string { + return fmt.Sprintf("%v", *ss) +} + func main() { - if len(os.Args) <= 1 { - os.Exit(0) + ignoreIfaceNames := make(stringList) + + mflag.Var(&ignoreIfaceNames, []string{"-ignore-iface"}, "name of interface to ignore)") + mflag.Parse() + + if len(mflag.Args()) < 1 { + fmt.Fprintln(os.Stderr, "usage: netcheck [--ignore-iface ] network-cidr") + os.Exit(1) } - cidrStr := os.Args[1] + cidrStr := mflag.Args()[0] addr, ipnet, err := net.ParseCIDR(cidrStr) if err != nil { fatal(err) } if ipnet.IP.Equal(addr) { - err = weavenet.CheckNetworkFree(ipnet) + err = weavenet.CheckNetworkFree(ipnet, ignoreIfaceNames) } else { - err = weavenet.CheckAddressOverlap(addr) + err = weavenet.CheckAddressOverlap(addr, ignoreIfaceNames) } if err != nil { fatal(err) diff --git a/weave b/weave index 9ad98158..50be4676 100755 --- a/weave +++ b/weave @@ -860,7 +860,7 @@ ipam_cidrs() { ALL_CIDRS="$ALL_CIDRS $CIDR" else # This is a plain IP address; warn if it clashes but carry on - command_exists netcheck && netcheck $1 || true + command_exists netcheck && netcheck --ignore-iface=$BRIDGE $1 || true ALL_CIDRS="$ALL_CIDRS $1" fi shift 1 @@ -1018,7 +1018,7 @@ launch_router() { eval "set -- $ARGS" if [ -z "$IPRANGE_SPECIFIED" ] ; then IPRANGE="10.32.0.0/12" - if command_exists netcheck && ! netcheck $IPRANGE ; then + if command_exists netcheck && ! netcheck --ignore-iface=$BRIDGE $IPRANGE ; then echo "Default --ipalloc-range $IPRANGE overlaps with existing route on host." >&2 echo "Please pick another range and set it on all hosts." >&2 exit 1