Add AWSVPC setup routines to the attach script
When running in the AWSVPC mode, we need to do the following: - Keep the HW TX offloading on. - Check that the allocated address belongs to the default subnet, because only one subnet is allowed and it should be the default one. If it is not possible to determine whether AWSVPC is on, we ignore all the steps, because the attachment routines have to work regardless whether the router is running and the AWSVPC detection is done by querying the /ipinfo/tracker endpoint served by the router.
This commit is contained in:
1 parent
de2a70861c
commit
7670fed72c
4 files changed
+51
-7
No files matched your search
+4
-4
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// create and attach a veth to the Weave bridge
|
||||
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
||||
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
||||
bridge, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
|
||||
@@ -42,7 +42,7 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, init func(p
|
||||
if err := netlink.LinkSetMasterByIndex(veth, bridge.Attrs().Index); err != nil {
|
||||
return cleanup(`unable to set master of %s: %s`, name, err)
|
||||
}
|
||||
if bridgeType == Bridge {
|
||||
if bridgeType == Bridge && !keepTXOn {
|
||||
if err := EthtoolTXOff(peerName); err != nil {
|
||||
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
||||
}
|
||||
@@ -111,14 +111,14 @@ func interfaceExistsInNamespace(ns netns.NsHandle, ifName string) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet) error {
|
||||
func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
|
||||
if !interfaceExistsInNamespace(ns, ifName) {
|
||||
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
|
||||
if len(id) > maxIDLen {
|
||||
id = id[:maxIDLen] // trim passed ID if too long
|
||||
}
|
||||
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
||||
_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, func(veth netlink.Link) error {
|
||||
_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
|
||||
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
||||
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
|
||||
id = fmt.Sprintf("%x", data)
|
||||
}
|
||||
|
||||
if err := weavenet.AttachContainer(ns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&result.IP4.IP}); err != nil {
|
||||
if err := weavenet.AttachContainer(ns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&result.IP4.IP}, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := weavenet.WithNetNSLink(ns, args.IfName, func(link netlink.Link) error {
|
||||
|
||||
@@ -134,8 +134,9 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
|
||||
if err != nil {
|
||||
return nil, driver.error("JoinEndpoint", "unable to find network info: %s", err)
|
||||
}
|
||||
|
||||
name, peerName := vethPair(j.EndpointID)
|
||||
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, nil); err != nil {
|
||||
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, nil); err != nil {
|
||||
return nil, driver.error("JoinEndpoint", "%s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,15 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/vishvananda/netns"
|
||||
|
||||
"github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
)
|
||||
|
||||
@@ -17,11 +20,26 @@ func attach(args []string) error {
|
||||
cmdUsage("attach-container", "[--no-multicast-route] <container-id> <bridge-name> <mtu> <cidr>...")
|
||||
}
|
||||
|
||||
client := api.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
|
||||
keepTXOn := false
|
||||
isAWSVPC := false
|
||||
// In a case of an error, we skip applying necessary steps for AWSVPC, because
|
||||
// "attach" should work without the weave router running.
|
||||
if t, err := client.LocalRangeTracker(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "unable to determine tracker: %s; skipping AWSVPC initialization\n", err)
|
||||
} else if t == "awsvpc" {
|
||||
isAWSVPC = true
|
||||
keepTXOn = true
|
||||
}
|
||||
|
||||
withMulticastRoute := true
|
||||
if args[0] == "--no-multicast-route" {
|
||||
withMulticastRoute = false
|
||||
args = args[1:]
|
||||
}
|
||||
if isAWSVPC {
|
||||
withMulticastRoute = false
|
||||
}
|
||||
|
||||
pid, nsContainer, err := containerPidAndNs(args[0])
|
||||
if err != nil {
|
||||
@@ -40,7 +58,22 @@ func attach(args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = weavenet.AttachContainer(nsContainer, fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs)
|
||||
|
||||
if isAWSVPC {
|
||||
// Currently, we allow only IP addresses from the default subnet
|
||||
if defaultSubnet, err := client.DefaultSubnet(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "unable to retrieve default subnet: %s; skipping AWSVPC checks\n", err)
|
||||
} else {
|
||||
for _, cidr := range cidrs {
|
||||
if !sameSubnet(cidr, defaultSubnet) {
|
||||
format := "AWSVPC constraints violation: %s does not belong to the default subnet %s"
|
||||
return fmt.Errorf(format, cidr, defaultSubnet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = weavenet.AttachContainer(nsContainer, fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn)
|
||||
// If we detected an error but the container has died, tell the user that instead.
|
||||
if err != nil && !processExists(pid) {
|
||||
err = fmt.Errorf("Container %s died", args[0])
|
||||
@@ -48,6 +81,16 @@ func attach(args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// sameSubnet checks whether ip belongs to network's subnet
|
||||
func sameSubnet(ip *net.IPNet, network *net.IPNet) bool {
|
||||
if network.Contains(ip.IP) {
|
||||
i1, i2 := ip.Mask.Size()
|
||||
n1, n2 := network.Mask.Size()
|
||||
return i1 == n1 && i2 == n2
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func containerPidAndNs(containerID string) (int, netns.NsHandle, error) {
|
||||
c, err := docker.NewVersionedClientFromEnv("1.18")
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user