Merge branch '1.9'

This commit is contained in:
Bryan Boreham committed 2017-05-30 13:55:49 +00:00
commit 37526728e0
7 files changed
+82 -14

No files matched your search

+6 -2
View File
@@ -106,7 +106,7 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
// NB: This function can be used only by a process that terminates immediately // NB: This function can be used only by a process that terminates immediately
// after calling the function as it changes netns via WithNetNSLinkUnsafe. // after calling the function as it changes netns via WithNetNSLinkUnsafe.
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error { func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
ns, err := netns.GetFromPath(netNSPath) ns, err := netns.GetFromPath(netNSPath)
if err != nil { if err != nil {
return err return err
@@ -124,7 +124,7 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
id = id[:maxIDLen] // trim passed ID if too long id = id[:maxIDLen] // trim passed ID if too long
} }
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error { veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil { if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
return fmt.Errorf("failed to move veth to container netns: %s", err) return fmt.Errorf("failed to move veth to container netns: %s", err)
} }
@@ -136,6 +136,10 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
if err != nil { if err != nil {
return err return err
} }
if err = netlink.LinkSetHairpin(veth, hairpinMode); err != nil {
return fmt.Errorf("unable to set hairpin mode to %t for bridge side of veth %s: %s", hairpinMode, name, err)
}
} }
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error { if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
+8 -6
View File
@@ -34,7 +34,8 @@ func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin {
func loadNetConf(bytes []byte) (*NetConf, error) { func loadNetConf(bytes []byte) (*NetConf, error) {
n := &NetConf{ n := &NetConf{
BrName: weavenet.WeaveBridgeName, BrName: weavenet.WeaveBridgeName,
HairpinMode: true,
} }
if err := json.Unmarshal(bytes, n); err != nil { if err := json.Unmarshal(bytes, n); err != nil {
return nil, fmt.Errorf("failed to load netconf: %v", err) return nil, fmt.Errorf("failed to load netconf: %v", err)
@@ -128,7 +129,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
id = fmt.Sprintf("%x", data) id = fmt.Sprintf("%x", data)
} }
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false); err != nil { if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false, conf.HairpinMode); err != nil {
return err return err
} }
if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error { if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error {
@@ -218,8 +219,9 @@ func logOnStderr(err error) {
type NetConf struct { type NetConf struct {
types.NetConf types.NetConf
BrName string `json:"bridge"` BrName string `json:"bridge"`
IsGW bool `json:"isGateway"` IsGW bool `json:"isGateway"`
IPMasq bool `json:"ipMasq"` IPMasq bool `json:"ipMasq"`
MTU int `json:"mtu"` MTU int `json:"mtu"`
HairpinMode bool `json:"hairpinMode"`
} }
+6 -2
View File
@@ -17,11 +17,12 @@ import (
func attach(args []string) error { func attach(args []string) error {
if len(args) < 4 { if len(args) < 4 {
cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] <container-id> <bridge-name> <mtu> <cidr>...") cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] [--hairpin-mode=true|false] <container-id> <bridge-name> <mtu> <cidr>...")
} }
keepTXOn := false keepTXOn := false
withMulticastRoute := true withMulticastRoute := true
hairpinMode := true
for i := 0; i < len(args); { for i := 0; i < len(args); {
switch args[i] { switch args[i] {
case "--no-multicast-route": case "--no-multicast-route":
@@ -30,6 +31,9 @@ func attach(args []string) error {
case "--keep-tx-on": case "--keep-tx-on":
keepTXOn = true keepTXOn = true
args = append(args[:i], args[i+1:]...) args = append(args[:i], args[i+1:]...)
case "--hairpin-mode=false":
hairpinMode = false
args = append(args[:i], args[i+1:]...)
default: default:
i++ i++
} }
@@ -58,7 +62,7 @@ func attach(args []string) error {
return err return err
} }
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn) err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn, hairpinMode)
// If we detected an error but the container has died, tell the user that instead. // If we detected an error but the container has died, tell the user that instead.
if err != nil && !processExists(pid) { if err != nil && !processExists(pid) {
err = fmt.Errorf("Container %s died", args[0]) err = fmt.Errorf("Container %s died", args[0])
+1 -1
View File
@@ -515,7 +515,7 @@ func (proxy *Proxy) attach(containerID string) error {
pid := container.State.Pid pid := container.State.Pid
// Passing 0 for mtu means it will be taken from the bridge // Passing 0 for mtu means it will be taken from the bridge
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn) err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn, true)
if err != nil { if err != nil {
return err return err
} }
+4
View File
@@ -221,6 +221,10 @@ The list of variables you can set is:
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net * `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
versions (default is blank, i.e. check is enabled) versions (default is blank, i.e. check is enabled)
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
kernel is one of those that can panic if hairpin is enabled, then you can disable it
by setting `HAIRPIN_MODE=false`.
* `IPALLOC_RANGE` - the range of IP addresses used by Weave Net * `IPALLOC_RANGE` - the range of IP addresses used by Weave Net
and the subnet they are placed in (CIDR format; default `10.32.0.0/12`) and the subnet they are placed in (CIDR format; default `10.32.0.0/12`)
* `EXPECT_NPC` - set to 0 to disable Network Policy Controller (default is on) * `EXPECT_NPC` - set to 0 to disable Network Policy Controller (default is on)
+52 -1
View File
@@ -8,7 +8,7 @@ cni_connect() {
pid=$(container_pid $1 $2) pid=$(container_pid $1 $2)
id=$(docker_on $1 inspect -f '{{.Id}}' $2) id=$(docker_on $1 inspect -f '{{.Id}}' $2)
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \ run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
} }
run_on $HOST1 sudo mkdir -p /opt/cni/bin run_on $HOST1 sudo mkdir -p /opt/cni/bin
@@ -19,6 +19,11 @@ weave_on $HOST1 launch
C0=$(docker_on $HOST1 run --net=none --name=c0 -dt $SMALL_IMAGE /bin/sh) C0=$(docker_on $HOST1 run --net=none --name=c0 -dt $SMALL_IMAGE /bin/sh)
C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh) C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh)
C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh) C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)
CH0=$(docker_on $HOST1 run --net=none --name=ch0 -dt $SMALL_IMAGE /bin/sh)
CH1=$(docker_on $HOST1 run --net=none --name=ch1 -dt $SMALL_IMAGE /bin/sh)
CH2=$(docker_on $HOST1 run --net=none --name=ch2 -dt $SMALL_IMAGE /bin/sh)
# Enable unsolicited ARPs so that ping after the address reuse does not time out # Enable unsolicited ARPs so that ping after the address reuse does not time out
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1 exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
@@ -52,6 +57,29 @@ cni_connect $HOST1 c2 <<EOF
} }
EOF EOF
# examples to test hairpin
cni_connect $HOST1 ch0 <<EOF
{
"name": "weave",
"type": "weave-net",
"hairpinMode": true
}
EOF
cni_connect $HOST1 ch1 <<EOF
{
"name": "weave",
"type": "weave-net",
"hairpinMode": false
}
EOF
cni_connect $HOST1 ch2 <<EOF
{
"name": "weave",
"type": "weave-net"
}
EOF
C0IP=$(container_ip $HOST1 c0) C0IP=$(container_ip $HOST1 c0)
C1IP=$(container_ip $HOST1 c1) C1IP=$(container_ip $HOST1 c1)
C2IP=$(container_ip $HOST1 c2) C2IP=$(container_ip $HOST1 c2)
@@ -85,6 +113,29 @@ assert_raises "[ $C2IP != $C3IP ]"
assert_raises "[ $BRIP != $C3IP ]" assert_raises "[ $BRIP != $C3IP ]"
assert_raises "exec_on $HOST1 c1 $PING $C3IP" assert_raises "exec_on $HOST1 c1 $PING $C3IP"
#####
#
# Hairpin mode tests
#
# here we check that the bridge side of the veth is set to hairpin mode (true or false) correctly
# check for each of
# - ch0 explicitly true
# - ch1 explicitly false
# - ch2 unset, which should default to true
#
# we take advantage of the veth name being constructed from the container ID)
#
# should this reliance ever fail and we need to get it from the system, do the following for each:
# CH0_PEER_ID=$(exec_on $HOST1 ch0 cat /sys/class/net/eth0/iflink)
# CH0_PEER=$($SSH $HOST1 ip link show | awk "/^${CH0_PEER_ID}:/"' {print $2}' | sed 's/@.*$//g' )
# CH0_HAIRPIN=$($SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/$CH0_PEER/hairpin_mode)
# assert_raises "[ $CH0_HAIRPIN == 1 ]"
#
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH0:0:7}/hairpin_mode" "1"
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH1:0:7}/hairpin_mode" "0"
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH2:0:7}/hairpin_mode" "1"
# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548 # Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
stop_weave_on $HOST1 stop_weave_on $HOST1
+5 -2
View File
@@ -745,17 +745,20 @@ create_cni_config() {
cat >"$1" <<EOF cat >"$1" <<EOF
{ {
"name": "weave", "name": "weave",
"type": "weave-net" "type": "weave-net",
"hairpinMode": $2
} }
EOF EOF
} }
setup_cni() { setup_cni() {
# if env var HAIRPIN_MODE is not set, default it to true
HAIRPIN_MODE=${HAIRPIN_MODE:-true}
if install_cni_plugin $CNI_PLUGIN_DIR ; then if install_cni_plugin $CNI_PLUGIN_DIR ; then
upgrade_cni_plugin $CNI_PLUGIN_DIR upgrade_cni_plugin $CNI_PLUGIN_DIR
fi fi
if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf $HAIRPIN_MODE
fi fi
} }