In weavewait, wait for the multicast route to be added before calling container entrypoint.
We have moved the 'route add' command to the end of 'attach', so this indicates that all network interface set-up is complete.
This commit is contained in:
1 parent
3d25620d13
commit
2eed101a93
4 files changed
+90
-12
No files matched your search
@@ -15,11 +15,41 @@ func EnsureInterface(ifaceName string) (*net.Interface, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer s.Close()
|
||||
iface, err := ensureInterface(s, ifaceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iface, err
|
||||
}
|
||||
|
||||
func ensureInterface(s *nl.NetlinkSocket, ifaceName string) (*net.Interface, error) {
|
||||
if iface, err := findInterface(ifaceName); err == nil {
|
||||
return iface, nil
|
||||
}
|
||||
waitForIfUp(s, ifaceName)
|
||||
return findInterface(ifaceName)
|
||||
iface, err := findInterface(ifaceName)
|
||||
return iface, err
|
||||
}
|
||||
|
||||
// Wait for an interface to come up and have a route added to the multicast subnet.
|
||||
// This matches the behaviour in 'weave attach', which is the only context in which
|
||||
// we expect this to be called. If you change one, change the other to match.
|
||||
func EnsureInterfaceAndMcastRoute(ifaceName string) (*net.Interface, error) {
|
||||
s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK, syscall.RTNLGRP_IPV4_ROUTE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer s.Close()
|
||||
iface, err := ensureInterface(s, ifaceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dest := net.IPv4(224, 0, 0, 0)
|
||||
if CheckRouteExists(ifaceName, dest) {
|
||||
return iface, err
|
||||
}
|
||||
waitForRoute(s, ifaceName, dest)
|
||||
return iface, err
|
||||
}
|
||||
|
||||
func findInterface(ifaceName string) (iface *net.Interface, err error) {
|
||||
|
||||
+52
-5
@@ -3,14 +3,16 @@ package net
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
// 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, ignoreIfaceNames map[string]struct{}) error {
|
||||
return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error {
|
||||
return forEachRoute(ignoreIfaceNames, func(name string, 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)
|
||||
}
|
||||
@@ -26,7 +28,7 @@ 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, ignoreIfaceNames map[string]struct{}) error {
|
||||
return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error {
|
||||
return forEachRoute(ignoreIfaceNames, func(name string, 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)
|
||||
}
|
||||
@@ -34,20 +36,65 @@ func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) erro
|
||||
})
|
||||
}
|
||||
|
||||
func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(netlink.Route) error) error {
|
||||
func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(name string, r netlink.Route) error) error {
|
||||
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, route := range routes {
|
||||
if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil {
|
||||
link, err := netlink.LinkByIndex(route.LinkIndex)
|
||||
if err == nil {
|
||||
if _, found := ignoreIfaceNames[link.Attrs().Name]; found {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err := check(route); err != nil {
|
||||
if err := check(link.Attrs().Name, route); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckRouteExists(ifaceName string, dest net.IP) bool {
|
||||
found := false
|
||||
forEachRoute(map[string]struct{}{}, func(name string, route netlink.Route) error {
|
||||
if name == ifaceName && route.Dst.IP.Equal(dest) {
|
||||
found = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
func waitForRoute(s *nl.NetlinkSocket, ifaceName string, dest net.IP) error {
|
||||
native := nl.NativeEndian()
|
||||
for {
|
||||
msgs, err := s.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, m := range msgs {
|
||||
switch m.Header.Type {
|
||||
case syscall.RTM_NEWROUTE:
|
||||
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ip net.IP
|
||||
var link netlink.Link
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case syscall.RTA_DST:
|
||||
ip = attr.Value
|
||||
case syscall.RTA_OIF:
|
||||
index := int(native.Uint32(attr.Value[0:4]))
|
||||
link, _ = netlink.LinkByIndex(index)
|
||||
}
|
||||
}
|
||||
if link.Attrs().Name == ifaceName && ip.Equal(dest) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func main() {
|
||||
args = os.Args[1:]
|
||||
)
|
||||
|
||||
_, err := weavenet.EnsureInterface("ethwe")
|
||||
_, err := weavenet.EnsureInterfaceAndMcastRoute("ethwe")
|
||||
checkErr(err)
|
||||
|
||||
if len(args) == 0 {
|
||||
|
||||
@@ -528,14 +528,15 @@ attach() {
|
||||
|
||||
netnsenter ip link set $CONTAINER_IFNAME up || return 1
|
||||
|
||||
# Route multicast packets across the weave network.
|
||||
if ! netnsenter ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then
|
||||
netnsenter ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME
|
||||
fi
|
||||
|
||||
for ADDR in "$@" ; do
|
||||
arp_update $CONTAINER_IFNAME $ADDR "netnsenter"
|
||||
done
|
||||
|
||||
# Route multicast packets across the weave network.
|
||||
# This must come last in 'attach'. If you change this, change weavewait to match.
|
||||
if ! netnsenter ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then
|
||||
netnsenter ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME
|
||||
fi
|
||||
}
|
||||
|
||||
detach() {
|
||||
|
||||
Reference in new issue
Block a user