diff --git a/net/bridge.go b/net/bridge.go index a5949b63..19931c82 100644 --- a/net/bridge.go +++ b/net/bridge.go @@ -8,6 +8,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/coreos/go-iptables/iptables" + "github.com/j-keck/arping" "github.com/pkg/errors" "github.com/vishvananda/netlink" @@ -442,3 +443,35 @@ func linkSetUpByName(linkName string) error { } return netlink.LinkSetUp(link) } + +func AddBridgeAddr(bridgeName string, addr *net.IPNet, removeDefaultRoute bool) error { + link, err := netlink.LinkByName(bridgeName) + if err != nil { + return errors.Wrapf(err, "AddBridgeAddr finding bridge %q", bridgeName) + } + newAddresses, err := AddAddresses(link, []*net.IPNet{addr}) + if err != nil { + return errors.Wrapf(err, "adding address %v to %q", addr, bridgeName) + } + for _, ipnet := range newAddresses { + arping.GratuitousArpOverIfaceByName(ipnet.IP, bridgeName) + } + if removeDefaultRoute { + routeFilter := &netlink.Route{ + LinkIndex: link.Attrs().Index, + Dst: &net.IPNet{IP: addr.IP.Mask(addr.Mask), Mask: addr.Mask}, + Protocol: 2, // RTPROT_KERNEL + } + filterMask := netlink.RT_FILTER_OIF | netlink.RT_FILTER_DST | netlink.RT_FILTER_PROTOCOL + routes, err := netlink.RouteListFiltered(netlink.FAMILY_V4, routeFilter, filterMask) + if err != nil { + return errors.Wrapf(err, "failed to get route list for bridge %q", bridgeName) + } + for _, r := range routes { + if err = netlink.RouteDel(&r); err != nil { + return errors.Wrapf(err, "failed to delete default route %+v", r) + } + } + } + return nil +} diff --git a/prog/weaver/main.go b/prog/weaver/main.go index ec4d04c3..5c2d8cb5 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -430,9 +430,25 @@ func main() { go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, !noDNS, enablePluginV2) } + if bridgeConfig.IsAWSVPC { + // Run this on its own goroutine because the allocator can block + // We remove the default route installed by the kernel, + // because awsvpc has installed it as well + go expose(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, bridgeConfig.IsAWSVPC) + } + signals.SignalHandlerLoop(common.Log, router) } +func expose(alloc *ipam.Allocator, subnet address.CIDR, bridgeName string, removeDefaultRoute bool) { + addr, err := alloc.Allocate("weave:expose", subnet, false, func() bool { return false }) + checkFatal(err) + cidr := address.MakeCIDR(subnet, addr) + err = weavenet.AddBridgeAddr(bridgeName, cidr.IPNet(), removeDefaultRoute) + checkFatal(err) + Log.Printf("Bridge %q exposed on address %v", bridgeName, cidr) +} + func options() map[string]string { options := make(map[string]string) mflag.Visit(func(f *mflag.Flag) { diff --git a/weave b/weave index 402b4db6..f483188d 100755 --- a/weave +++ b/weave @@ -474,12 +474,6 @@ expose_ip() { if ! ip addr show dev $BRIDGE | grep -qF $CIDR ; then ip addr add dev $BRIDGE $CIDR arp_update $BRIDGE $CIDR || true - # Remove a default route installed by the kernel, because awsvpc - # has installed it as well - if [ -n "$AWSVPC" ]; then - RCIDR=$(ip route list exact $CIDR proto kernel | head -n1 | cut -d' ' -f1) - [ -n "$RCIDR" ] && ip route del dev $BRIDGE proto kernel $RCIDR - fi fi [ -z "$FQDN" ] || when_weave_running put_dns_fqdn_no_check_alive weave:expose $FQDN $CIDR done @@ -1416,7 +1410,6 @@ launch_router() { --resolv-conf "/var/run/weave/etc/$RESOLV_CONF_BASE" \ "$@") wait_for_status $CONTAINER_NAME http_call $HTTP_ADDR - setup_awsvpc if [ -n "$ENABLE_PLUGIN" ]; then wait_for_status $CONTAINER_NAME http_call_unix $CONTAINER_NAME plugin-status.sock @@ -1424,12 +1417,6 @@ launch_router() { fi } -setup_awsvpc() { - if [ -n "$AWSVPC" ]; then - expose_ip - fi -} - # Recreate the parameter values that are set when the router is first launched fetch_router_args() { CONTAINER_ARGS=$(docker inspect -f '{{.Args}}' $CONTAINER_NAME) || return 1 @@ -1660,7 +1647,6 @@ EOF ! docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--awsvpc" || AWSVPC=1 fetch_router_args wait_for_status $CONTAINER_NAME http_call $HTTP_ADDR - setup_awsvpc ;; launch-proxy) deprecation_warnings "$@"