From e621aca77e4f5b6f820b5bf2eba71cc7b3dde8f7 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 6 Jul 2015 18:05:13 +0100 Subject: [PATCH 1/2] Added --ignore-iface option to netcheck and use it to ignore weave bridge route --- net/route.go | 11 +++++++++-- prog/netcheck/netcheck.go | 17 ++++++++++++----- weave | 4 ++-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/net/route.go b/net/route.go index 6d1722ad..bff99e2d 100644 --- a/net/route.go +++ b/net/route.go @@ -9,13 +9,17 @@ 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 { +func CheckNetworkFree(subnet *net.IPNet, ignoreIfName string) error { routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) if err != nil { return err } for _, route := range routes { if route.Dst != nil && overlaps(route.Dst, subnet) { + if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { + continue + } + return fmt.Errorf("Network %s overlaps with existing route %s on host.", subnet, route.Dst) } } @@ -29,13 +33,16 @@ 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, ignoreIfName string) 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) { + if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { + continue + } return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) } } diff --git a/prog/netcheck/netcheck.go b/prog/netcheck/netcheck.go index 96a26ed4..78261a0e 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" ) @@ -15,19 +16,25 @@ func fatal(err error) { } func main() { - if len(os.Args) <= 1 { - os.Exit(0) + var ignoreIfaceName string + + mflag.StringVar(&ignoreIfaceName, []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, ignoreIfaceName) } else { - err = weavenet.CheckAddressOverlap(addr) + err = weavenet.CheckAddressOverlap(addr, ignoreIfaceName) } if err != nil { fatal(err) diff --git a/weave b/weave index 479ff2c5..9a10adb6 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 @@ -998,7 +998,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 From 6666fd14ac15866fc07c9bb27e620069f58dc3c6 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Tue, 7 Jul 2015 10:00:44 +0100 Subject: [PATCH 2/2] Allow multiple --ignore-iface arguments --- net/route.go | 35 +++++++++++++++++++---------------- prog/netcheck/netcheck.go | 21 ++++++++++++++++----- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/net/route.go b/net/route.go index bff99e2d..463f843b 100644 --- a/net/route.go +++ b/net/route.go @@ -9,21 +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, ignoreIfName string) 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) { - if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { - continue - } - 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. @@ -33,17 +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, ignoreIfName string) 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) { - if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { + if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil { + if _, found := ignoreIfaceNames[link.Attrs().Name]; found { continue } - return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) + } + if err := check(route); err != nil { + return err } } return nil diff --git a/prog/netcheck/netcheck.go b/prog/netcheck/netcheck.go index 78261a0e..fe822f2e 100644 --- a/prog/netcheck/netcheck.go +++ b/prog/netcheck/netcheck.go @@ -15,10 +15,21 @@ func fatal(err error) { os.Exit(1) } -func main() { - var ignoreIfaceName string +type stringList map[string]struct{} - mflag.StringVar(&ignoreIfaceName, []string{"-ignore-iface"}, "", "name of interface to ignore)") +func (ss *stringList) Set(value string) error { + (*ss)[value] = struct{}{} + return nil +} + +func (ss *stringList) String() string { + return fmt.Sprintf("%v", *ss) +} + +func main() { + ignoreIfaceNames := make(stringList) + + mflag.Var(&ignoreIfaceNames, []string{"-ignore-iface"}, "name of interface to ignore)") mflag.Parse() if len(mflag.Args()) < 1 { @@ -32,9 +43,9 @@ func main() { fatal(err) } if ipnet.IP.Equal(addr) { - err = weavenet.CheckNetworkFree(ipnet, ignoreIfaceName) + err = weavenet.CheckNetworkFree(ipnet, ignoreIfaceNames) } else { - err = weavenet.CheckAddressOverlap(addr, ignoreIfaceName) + err = weavenet.CheckAddressOverlap(addr, ignoreIfaceNames) } if err != nil { fatal(err)