瀏覽代碼

Vendor libnetwork and github.com/vishvananda/netlink

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Aaron Lehmann 9 年之前
父節點
當前提交
24d2d53f5d
共有 33 個文件被更改,包括 351 次插入111 次删除
  1. 2 2
      hack/vendor.sh
  2. 14 22
      vendor/src/github.com/docker/libnetwork/agent.go
  3. 2 1
      vendor/src/github.com/docker/libnetwork/cluster/provider.go
  4. 8 0
      vendor/src/github.com/docker/libnetwork/config/config.go
  5. 4 0
      vendor/src/github.com/docker/libnetwork/controller.go
  6. 3 2
      vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go
  7. 2 2
      vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go
  8. 1 1
      vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_endpoint.go
  9. 2 2
      vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_store.go
  10. 2 2
      vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_store.go
  11. 40 16
      vendor/src/github.com/docker/libnetwork/drivers/overlay/encryption.go
  12. 7 5
      vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go
  13. 1 1
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go
  14. 36 26
      vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go
  15. 10 1
      vendor/src/github.com/docker/libnetwork/endpoint_cnt.go
  16. 5 1
      vendor/src/github.com/docker/libnetwork/network.go
  17. 1 1
      vendor/src/github.com/docker/libnetwork/networkdb/cluster.go
  18. 2 2
      vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go
  19. 1 0
      vendor/src/github.com/docker/libnetwork/osl/interface_linux.go
  20. 15 4
      vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go
  21. 4 0
      vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go
  22. 4 0
      vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go
  23. 4 0
      vendor/src/github.com/docker/libnetwork/osl/sandbox_freebsd.go
  24. 17 3
      vendor/src/github.com/docker/libnetwork/sandbox.go
  25. 1 1
      vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go
  26. 12 1
      vendor/src/github.com/vishvananda/netlink/addr_linux.go
  27. 2 2
      vendor/src/github.com/vishvananda/netlink/filter_linux.go
  28. 14 3
      vendor/src/github.com/vishvananda/netlink/link_linux.go
  29. 57 6
      vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go
  30. 30 0
      vendor/src/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
  31. 12 1
      vendor/src/github.com/vishvananda/netlink/route_linux.go
  32. 12 3
      vendor/src/github.com/vishvananda/netlink/xfrm_state.go
  33. 24 0
      vendor/src/github.com/vishvananda/netlink/xfrm_state_linux.go

+ 2 - 2
hack/vendor.sh

@@ -65,7 +65,7 @@ clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
 clone git github.com/imdario/mergo 0.2.1
 clone git github.com/imdario/mergo 0.2.1
 
 
 #get libnetwork packages
 #get libnetwork packages
-clone git github.com/docker/libnetwork 905d374c096ca1f3a9b75529e52518b7540179f3
+clone git github.com/docker/libnetwork 83ab4deaa2da3deb32cb5e64ceec43801dc17370
 clone git github.com/docker/go-events afb2b9f2c23f33ada1a22b03651775fdc65a5089
 clone git github.com/docker/go-events afb2b9f2c23f33ada1a22b03651775fdc65a5089
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
@@ -75,7 +75,7 @@ clone git github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa07
 clone git github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
 clone git github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
 clone git github.com/docker/libkv v0.2.1
 clone git github.com/docker/libkv v0.2.1
 clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
 clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
-clone git github.com/vishvananda/netlink 734d02c3e202f682c74b71314b2c61eec0170fd4
+clone git github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6c
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
 clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d

+ 14 - 22
vendor/src/github.com/docker/libnetwork/agent.go

@@ -35,6 +35,7 @@ func (b ByTime) Less(i, j int) bool { return b[i].LamportTime < b[j].LamportTime
 type agent struct {
 type agent struct {
 	networkDB         *networkdb.NetworkDB
 	networkDB         *networkdb.NetworkDB
 	bindAddr          string
 	bindAddr          string
+	advertiseAddr     string
 	epTblCancel       func()
 	epTblCancel       func()
 	driverCancelFuncs map[string][]func()
 	driverCancelFuncs map[string][]func()
 }
 }
@@ -236,25 +237,14 @@ func (c *controller) handleKeyChangeV1(keys []*types.EncryptionKey) error {
 func (c *controller) agentSetup() error {
 func (c *controller) agentSetup() error {
 	clusterProvider := c.cfg.Daemon.ClusterProvider
 	clusterProvider := c.cfg.Daemon.ClusterProvider
 
 
-	bindAddr, _, _ := net.SplitHostPort(clusterProvider.GetListenAddress())
+	bindAddr := clusterProvider.GetLocalAddress()
+	advAddr := clusterProvider.GetAdvertiseAddress()
 	remote := clusterProvider.GetRemoteAddress()
 	remote := clusterProvider.GetRemoteAddress()
 	remoteAddr, _, _ := net.SplitHostPort(remote)
 	remoteAddr, _, _ := net.SplitHostPort(remote)
 
 
-	// Determine the BindAddress from RemoteAddress or through best-effort routing
-	if !isValidClusteringIP(bindAddr) {
-		if !isValidClusteringIP(remoteAddr) {
-			remote = "8.8.8.8:53"
-		}
-		conn, err := net.Dial("udp", remote)
-		if err == nil {
-			bindHostPort := conn.LocalAddr().String()
-			bindAddr, _, _ = net.SplitHostPort(bindHostPort)
-			conn.Close()
-		}
-	}
-
-	if bindAddr != "" && c.agent == nil {
-		if err := c.agentInit(bindAddr); err != nil {
+	logrus.Infof("Initializing Libnetwork Agent Local-addr=%s Adv-addr=%s Remote-addr =%s", bindAddr, advAddr, remoteAddr)
+	if advAddr != "" && c.agent == nil {
+		if err := c.agentInit(bindAddr, advAddr); err != nil {
 			logrus.Errorf("Error in agentInit : %v", err)
 			logrus.Errorf("Error in agentInit : %v", err)
 		} else {
 		} else {
 			c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
 			c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
@@ -312,7 +302,7 @@ func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64) {
 	return keys[1].Key, keys[1].LamportTime
 	return keys[1].Key, keys[1].LamportTime
 }
 }
 
 
-func (c *controller) agentInit(bindAddrOrInterface string) error {
+func (c *controller) agentInit(bindAddrOrInterface, advertiseAddr string) error {
 	if !c.isAgent() {
 	if !c.isAgent() {
 		return nil
 		return nil
 	}
 	}
@@ -325,9 +315,9 @@ func (c *controller) agentInit(bindAddrOrInterface string) error {
 	keys, tags := c.getKeys(subsysGossip)
 	keys, tags := c.getKeys(subsysGossip)
 	hostname, _ := os.Hostname()
 	hostname, _ := os.Hostname()
 	nDB, err := networkdb.New(&networkdb.Config{
 	nDB, err := networkdb.New(&networkdb.Config{
-		BindAddr: bindAddr,
-		NodeName: hostname,
-		Keys:     keys,
+		AdvertiseAddr: advertiseAddr,
+		NodeName:      hostname,
+		Keys:          keys,
 	})
 	})
 
 
 	if err != nil {
 	if err != nil {
@@ -339,6 +329,7 @@ func (c *controller) agentInit(bindAddrOrInterface string) error {
 	c.agent = &agent{
 	c.agent = &agent{
 		networkDB:         nDB,
 		networkDB:         nDB,
 		bindAddr:          bindAddr,
 		bindAddr:          bindAddr,
+		advertiseAddr:     advertiseAddr,
 		epTblCancel:       cancel,
 		epTblCancel:       cancel,
 		driverCancelFuncs: make(map[string][]func()),
 		driverCancelFuncs: make(map[string][]func()),
 	}
 	}
@@ -377,8 +368,9 @@ func (c *controller) agentDriverNotify(d driverapi.Driver) {
 	}
 	}
 
 
 	d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{
 	d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{
-		Address: c.agent.bindAddr,
-		Self:    true,
+		Address:     c.agent.advertiseAddr,
+		BindAddress: c.agent.bindAddr,
+		Self:        true,
 	})
 	})
 
 
 	drvEnc := discoverapi.DriverEncryptionConfig{}
 	drvEnc := discoverapi.DriverEncryptionConfig{}

+ 2 - 1
vendor/src/github.com/docker/libnetwork/cluster/provider.go

@@ -4,7 +4,8 @@ package cluster
 type Provider interface {
 type Provider interface {
 	IsManager() bool
 	IsManager() bool
 	IsAgent() bool
 	IsAgent() bool
-	GetListenAddress() string
+	GetLocalAddress() string
+	GetAdvertiseAddress() string
 	GetRemoteAddress() string
 	GetRemoteAddress() string
 	ListenClusterEvents() <-chan struct{}
 	ListenClusterEvents() <-chan struct{}
 }
 }

+ 8 - 0
vendor/src/github.com/docker/libnetwork/config/config.go

@@ -11,6 +11,7 @@ import (
 	"github.com/docker/libnetwork/cluster"
 	"github.com/docker/libnetwork/cluster"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/osl"
 )
 )
 
 
 // Config encapsulates configurations of various Libnetwork components
 // Config encapsulates configurations of various Libnetwork components
@@ -197,6 +198,13 @@ func OptionDataDir(dataDir string) Option {
 	}
 	}
 }
 }
 
 
+// OptionExecRoot function returns an option setter for exec root folder
+func OptionExecRoot(execRoot string) Option {
+	return func(c *Config) {
+		osl.SetBasePath(execRoot)
+	}
+}
+
 // ProcessOptions processes options and stores it in config
 // ProcessOptions processes options and stores it in config
 func (c *Config) ProcessOptions(options ...Option) {
 func (c *Config) ProcessOptions(options ...Option) {
 	for _, opt := range options {
 	for _, opt := range options {

+ 4 - 0
vendor/src/github.com/docker/libnetwork/controller.go

@@ -378,6 +378,10 @@ func (c *controller) ReloadConfiguration(cfgOptions ...config.Option) error {
 		return nil
 		return nil
 	}
 	}
 
 
+	c.Lock()
+	c.cfg = cfg
+	c.Unlock()
+
 	var dsConfig *discoverapi.DatastoreConfigData
 	var dsConfig *discoverapi.DatastoreConfigData
 	for scope, sCfg := range cfg.Scopes {
 	for scope, sCfg := range cfg.Scopes {
 		if scope == datastore.LocalScope || !sCfg.IsValid() {
 		if scope == datastore.LocalScope || !sCfg.IsValid() {

+ 3 - 2
vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go

@@ -26,8 +26,9 @@ const (
 
 
 // NodeDiscoveryData represents the structure backing the node discovery data json string
 // NodeDiscoveryData represents the structure backing the node discovery data json string
 type NodeDiscoveryData struct {
 type NodeDiscoveryData struct {
-	Address string
-	Self    bool
+	Address     string
+	BindAddress string
+	Self        bool
 }
 }
 
 
 // DatastoreConfigData is the data for the datastore update event message
 // DatastoreConfigData is the data for the datastore update event message

+ 2 - 2
vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go

@@ -83,9 +83,9 @@ func (d *driver) populateEndpoints() error {
 		n, ok := d.networks[ep.nid]
 		n, ok := d.networks[ep.nid]
 		if !ok {
 		if !ok {
 			logrus.Debugf("Network (%s) not found for restored bridge endpoint (%s)", ep.nid[0:7], ep.id[0:7])
 			logrus.Debugf("Network (%s) not found for restored bridge endpoint (%s)", ep.nid[0:7], ep.id[0:7])
-			logrus.Debugf("Deleting stale bridge endpoint (%s) from store", ep.nid[0:7])
+			logrus.Debugf("Deleting stale bridge endpoint (%s) from store", ep.id[0:7])
 			if err := d.storeDelete(ep); err != nil {
 			if err := d.storeDelete(ep); err != nil {
-				logrus.Debugf("Failed to delete stale bridge endpoint (%s) from store", ep.nid[0:7])
+				logrus.Debugf("Failed to delete stale bridge endpoint (%s) from store", ep.id[0:7])
 			}
 			}
 			continue
 			continue
 		}
 		}

+ 1 - 1
vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_endpoint.go

@@ -82,6 +82,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
 	if err := d.storeDelete(ep); err != nil {
 	if err := d.storeDelete(ep); err != nil {
 		logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err)
 		logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err)
 	}
 	}
-
+	n.deleteEndpoint(ep.id)
 	return nil
 	return nil
 }
 }

+ 2 - 2
vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_store.go

@@ -96,9 +96,9 @@ func (d *driver) populateEndpoints() error {
 		n, ok := d.networks[ep.nid]
 		n, ok := d.networks[ep.nid]
 		if !ok {
 		if !ok {
 			logrus.Debugf("Network (%s) not found for restored ipvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
 			logrus.Debugf("Network (%s) not found for restored ipvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
-			logrus.Debugf("Deleting stale ipvlan endpoint (%s) from store", ep.nid[0:7])
+			logrus.Debugf("Deleting stale ipvlan endpoint (%s) from store", ep.id[0:7])
 			if err := d.storeDelete(ep); err != nil {
 			if err := d.storeDelete(ep); err != nil {
-				logrus.Debugf("Failed to delete stale ipvlan endpoint (%s) from store", ep.nid[0:7])
+				logrus.Debugf("Failed to delete stale ipvlan endpoint (%s) from store", ep.id[0:7])
 			}
 			}
 			continue
 			continue
 		}
 		}

+ 2 - 2
vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_store.go

@@ -96,9 +96,9 @@ func (d *driver) populateEndpoints() error {
 		n, ok := d.networks[ep.nid]
 		n, ok := d.networks[ep.nid]
 		if !ok {
 		if !ok {
 			logrus.Debugf("Network (%s) not found for restored macvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
 			logrus.Debugf("Network (%s) not found for restored macvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
-			logrus.Debugf("Deleting stale macvlan endpoint (%s) from store", ep.nid[0:7])
+			logrus.Debugf("Deleting stale macvlan endpoint (%s) from store", ep.id[0:7])
 			if err := d.storeDelete(ep); err != nil {
 			if err := d.storeDelete(ep); err != nil {
-				logrus.Debugf("Failed to delete stale macvlan endpoint (%s) from store", ep.nid[0:7])
+				logrus.Debugf("Failed to delete stale macvlan endpoint (%s) from store", ep.id[0:7])
 			}
 			}
 			continue
 			continue
 		}
 		}

+ 40 - 16
vendor/src/github.com/docker/libnetwork/drivers/overlay/encryption.go

@@ -2,23 +2,27 @@ package overlay
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"encoding/binary"
 	"encoding/hex"
 	"encoding/hex"
 	"fmt"
 	"fmt"
+	"hash/fnv"
 	"net"
 	"net"
 	"sync"
 	"sync"
 	"syscall"
 	"syscall"
 
 
+	"strconv"
+
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/ns"
 	"github.com/docker/libnetwork/ns"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
-	"strconv"
 )
 )
 
 
 const (
 const (
-	mark    = uint32(0xD0C4E3)
-	timeout = 30
+	mark         = uint32(0xD0C4E3)
+	timeout      = 30
+	pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8)
 )
 )
 
 
 const (
 const (
@@ -85,6 +89,7 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal
 	}
 	}
 
 
 	lIP := types.GetMinimalIP(net.ParseIP(d.bindAddress))
 	lIP := types.GetMinimalIP(net.ParseIP(d.bindAddress))
+	aIP := types.GetMinimalIP(net.ParseIP(d.advertiseAddress))
 	nodes := map[string]net.IP{}
 	nodes := map[string]net.IP{}
 
 
 	switch {
 	switch {
@@ -107,7 +112,7 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal
 
 
 	if add {
 	if add {
 		for _, rIP := range nodes {
 		for _, rIP := range nodes {
-			if err := setupEncryption(lIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
+			if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
 				log.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
 				log.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
 			}
 			}
 		}
 		}
@@ -122,7 +127,7 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal
 	return nil
 	return nil
 }
 }
 
 
-func setupEncryption(localIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
+func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
 	log.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
 	log.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
 	rIPs := remoteIP.String()
 	rIPs := remoteIP.String()
 
 
@@ -134,7 +139,7 @@ func setupEncryption(localIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*
 	}
 	}
 
 
 	for i, k := range keys {
 	for i, k := range keys {
-		spis := &spi{buildSPI(localIP, remoteIP, k.tag), buildSPI(remoteIP, localIP, k.tag)}
+		spis := &spi{buildSPI(advIP, remoteIP, k.tag), buildSPI(remoteIP, advIP, k.tag)}
 		dir := reverse
 		dir := reverse
 		if i == 0 {
 		if i == 0 {
 			dir = bidir
 			dir = bidir
@@ -216,7 +221,6 @@ func programMangle(vni uint32, add bool) (err error) {
 
 
 func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (fSA *netlink.XfrmState, rSA *netlink.XfrmState, err error) {
 func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (fSA *netlink.XfrmState, rSA *netlink.XfrmState, err error) {
 	var (
 	var (
-		crypt       *netlink.XfrmStateAlgo
 		action      = "Removing"
 		action      = "Removing"
 		xfrmProgram = ns.NlHandle().XfrmStateDel
 		xfrmProgram = ns.NlHandle().XfrmStateDel
 	)
 	)
@@ -224,7 +228,6 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
 	if add {
 	if add {
 		action = "Adding"
 		action = "Adding"
 		xfrmProgram = ns.NlHandle().XfrmStateAdd
 		xfrmProgram = ns.NlHandle().XfrmStateAdd
-		crypt = &netlink.XfrmStateAlgo{Name: "cbc(aes)", Key: k.value}
 	}
 	}
 
 
 	if dir&reverse > 0 {
 	if dir&reverse > 0 {
@@ -236,7 +239,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
 			Mode:  netlink.XFRM_MODE_TRANSPORT,
 			Mode:  netlink.XFRM_MODE_TRANSPORT,
 		}
 		}
 		if add {
 		if add {
-			rSA.Crypt = crypt
+			rSA.Aead = buildAeadAlgo(k, spi.reverse)
 		}
 		}
 
 
 		exists, err := saExists(rSA)
 		exists, err := saExists(rSA)
@@ -261,7 +264,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
 			Mode:  netlink.XFRM_MODE_TRANSPORT,
 			Mode:  netlink.XFRM_MODE_TRANSPORT,
 		}
 		}
 		if add {
 		if add {
-			fSA.Crypt = crypt
+			fSA.Aead = buildAeadAlgo(k, spi.forward)
 		}
 		}
 
 
 		exists, err := saExists(fSA)
 		exists, err := saExists(fSA)
@@ -354,13 +357,23 @@ func spExists(sp *netlink.XfrmPolicy) (bool, error) {
 }
 }
 
 
 func buildSPI(src, dst net.IP, st uint32) int {
 func buildSPI(src, dst net.IP, st uint32) int {
-	spi := int(st)
-	f := src[len(src)-4:]
-	t := dst[len(dst)-4:]
-	for i := 0; i < 4; i++ {
-		spi = spi ^ (int(f[i])^int(t[3-i]))<<uint32(8*i)
+	b := make([]byte, 4)
+	binary.BigEndian.PutUint32(b, st)
+	h := fnv.New32a()
+	h.Write(src)
+	h.Write(b)
+	h.Write(dst)
+	return int(binary.BigEndian.Uint32(h.Sum(nil)))
+}
+
+func buildAeadAlgo(k *key, s int) *netlink.XfrmStateAlgo {
+	salt := make([]byte, 4)
+	binary.BigEndian.PutUint32(salt, uint32(s))
+	return &netlink.XfrmStateAlgo{
+		Name:   "rfc4106(gcm(aes))",
+		Key:    append(k.value, salt...),
+		ICVLen: 64,
 	}
 	}
-	return spi
 }
 }
 
 
 func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
 func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
@@ -560,3 +573,14 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx,
 
 
 	return spis
 	return spis
 }
 }
+
+func (n *network) maxMTU() int {
+	mtu := vxlanVethMTU
+	if n.secure {
+		// In case of encryption account for the
+		// esp packet espansion and padding
+		mtu -= pktExpansion
+		mtu -= (mtu % 4)
+	}
+	return mtu
+}

+ 7 - 5
vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go

@@ -75,11 +75,13 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	// Set the container interface and its peer MTU to 1450 to allow
 	// Set the container interface and its peer MTU to 1450 to allow
 	// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
 	// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
 	// outer UDP(8) + vxlan header(8))
 	// outer UDP(8) + vxlan header(8))
+	mtu := n.maxMTU()
+
 	veth, err := nlh.LinkByName(overlayIfName)
 	veth, err := nlh.LinkByName(overlayIfName)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("cound not find link by name %s: %v", overlayIfName, err)
 		return fmt.Errorf("cound not find link by name %s: %v", overlayIfName, err)
 	}
 	}
-	err = nlh.LinkSetMTU(veth, vxlanVethMTU)
+	err = nlh.LinkSetMTU(veth, mtu)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -93,7 +95,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("could not find link by name %s: %v", containerIfName, err)
 		return fmt.Errorf("could not find link by name %s: %v", containerIfName, err)
 	}
 	}
-	err = nlh.LinkSetMTU(veth, vxlanVethMTU)
+	err = nlh.LinkSetMTU(veth, mtu)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -119,7 +121,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	}
 	}
 
 
 	d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
 	d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
-		net.ParseIP(d.bindAddress), true)
+		net.ParseIP(d.advertiseAddress), true)
 
 
 	if err := d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
 	if err := d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
 		log.Warn(err)
 		log.Warn(err)
@@ -128,7 +130,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	buf, err := proto.Marshal(&PeerRecord{
 	buf, err := proto.Marshal(&PeerRecord{
 		EndpointIP:       ep.addr.String(),
 		EndpointIP:       ep.addr.String(),
 		EndpointMAC:      ep.mac.String(),
 		EndpointMAC:      ep.mac.String(),
-		TunnelEndpointIP: d.bindAddress,
+		TunnelEndpointIP: d.advertiseAddress,
 	})
 	})
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -159,7 +161,7 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri
 
 
 	// Ignore local peers. We already know about them and they
 	// Ignore local peers. We already know about them and they
 	// should not be added to vxlan fdb.
 	// should not be added to vxlan fdb.
-	if peer.TunnelEndpointIP == d.bindAddress {
+	if peer.TunnelEndpointIP == d.advertiseAddress {
 		return
 		return
 	}
 	}
 
 

+ 1 - 1
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go

@@ -40,7 +40,7 @@ func (d *driver) serfInit() error {
 
 
 	config := serf.DefaultConfig()
 	config := serf.DefaultConfig()
 	config.Init()
 	config.Init()
-	config.MemberlistConfig.BindAddr = d.bindAddress
+	config.MemberlistConfig.BindAddr = d.advertiseAddress
 
 
 	d.eventCh = make(chan serf.Event, 4)
 	d.eventCh = make(chan serf.Event, 4)
 	config.EventCh = d.eventCh
 	config.EventCh = d.eventCh

+ 36 - 26
vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go

@@ -31,22 +31,23 @@ const (
 var initVxlanIdm = make(chan (bool), 1)
 var initVxlanIdm = make(chan (bool), 1)
 
 
 type driver struct {
 type driver struct {
-	eventCh      chan serf.Event
-	notifyCh     chan ovNotify
-	exitCh       chan chan struct{}
-	bindAddress  string
-	neighIP      string
-	config       map[string]interface{}
-	peerDb       peerNetworkMap
-	secMap       *encrMap
-	serfInstance *serf.Serf
-	networks     networkTable
-	store        datastore.DataStore
-	localStore   datastore.DataStore
-	vxlanIdm     *idm.Idm
-	once         sync.Once
-	joinOnce     sync.Once
-	keys         []*key
+	eventCh          chan serf.Event
+	notifyCh         chan ovNotify
+	exitCh           chan chan struct{}
+	bindAddress      string
+	advertiseAddress string
+	neighIP          string
+	config           map[string]interface{}
+	peerDb           peerNetworkMap
+	secMap           *encrMap
+	serfInstance     *serf.Serf
+	networks         networkTable
+	store            datastore.DataStore
+	localStore       datastore.DataStore
+	vxlanIdm         *idm.Idm
+	once             sync.Once
+	joinOnce         sync.Once
+	keys             []*key
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
@@ -111,7 +112,11 @@ func (d *driver) restoreEndpoints() error {
 		ep := kvo.(*endpoint)
 		ep := kvo.(*endpoint)
 		n := d.network(ep.nid)
 		n := d.network(ep.nid)
 		if n == nil {
 		if n == nil {
-			logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid, ep.id)
+			logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
+			logrus.Debugf("Deleting stale overlay endpoint (%s) from store", ep.id[0:7])
+			if err := d.deleteEndpointFromStore(ep); err != nil {
+				logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
+			}
 			continue
 			continue
 		}
 		}
 		n.addEndpoint(ep)
 		n.addEndpoint(ep)
@@ -140,7 +145,7 @@ func (d *driver) restoreEndpoints() error {
 		}
 		}
 
 
 		n.incEndpointCount()
 		n.incEndpointCount()
-		d.peerDbAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.bindAddress), true)
+		d.peerDbAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true)
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -211,20 +216,25 @@ func validateSelf(node string) error {
 	return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
 	return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
 }
 }
 
 
-func (d *driver) nodeJoin(node string, self bool) {
+func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
 	if self && !d.isSerfAlive() {
 	if self && !d.isSerfAlive() {
-		if err := validateSelf(node); err != nil {
-			logrus.Errorf("%s", err.Error())
-		}
 		d.Lock()
 		d.Lock()
-		d.bindAddress = node
+		d.advertiseAddress = advertiseAddress
+		d.bindAddress = bindAddress
 		d.Unlock()
 		d.Unlock()
 
 
 		// If there is no cluster store there is no need to start serf.
 		// If there is no cluster store there is no need to start serf.
 		if d.store != nil {
 		if d.store != nil {
+			if err := validateSelf(advertiseAddress); err != nil {
+				logrus.Warnf("%s", err.Error())
+			}
 			err := d.serfInit()
 			err := d.serfInit()
 			if err != nil {
 			if err != nil {
 				logrus.Errorf("initializing serf instance failed: %v", err)
 				logrus.Errorf("initializing serf instance failed: %v", err)
+				d.Lock()
+				d.advertiseAddress = ""
+				d.bindAddress = ""
+				d.Unlock()
 				return
 				return
 			}
 			}
 		}
 		}
@@ -232,7 +242,7 @@ func (d *driver) nodeJoin(node string, self bool) {
 
 
 	d.Lock()
 	d.Lock()
 	if !self {
 	if !self {
-		d.neighIP = node
+		d.neighIP = advertiseAddress
 	}
 	}
 	neighIP := d.neighIP
 	neighIP := d.neighIP
 	d.Unlock()
 	d.Unlock()
@@ -246,7 +256,7 @@ func (d *driver) nodeJoin(node string, self bool) {
 			}
 			}
 		})
 		})
 		if err != nil {
 		if err != nil {
-			logrus.Errorf("joining serf neighbor %s failed: %v", node, err)
+			logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
 			d.Lock()
 			d.Lock()
 			d.joinOnce = sync.Once{}
 			d.joinOnce = sync.Once{}
 			d.Unlock()
 			d.Unlock()
@@ -286,7 +296,7 @@ func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{})
 		if !ok || nodeData.Address == "" {
 		if !ok || nodeData.Address == "" {
 			return fmt.Errorf("invalid discovery data")
 			return fmt.Errorf("invalid discovery data")
 		}
 		}
-		d.nodeJoin(nodeData.Address, nodeData.Self)
+		d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self)
 	case discoverapi.DatastoreConfig:
 	case discoverapi.DatastoreConfig:
 		if d.store != nil {
 		if d.store != nil {
 			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
 			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")

+ 10 - 1
vendor/src/github.com/docker/libnetwork/endpoint_cnt.go

@@ -113,6 +113,9 @@ func (ec *endpointCnt) updateStore() error {
 	if store == nil {
 	if store == nil {
 		return fmt.Errorf("store not found for scope %s on endpoint count update", ec.DataScope())
 		return fmt.Errorf("store not found for scope %s on endpoint count update", ec.DataScope())
 	}
 	}
+	// make a copy of count and n to avoid being overwritten by store.GetObject
+	count := ec.EndpointCnt()
+	n := ec.n
 	for {
 	for {
 		if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified {
 		if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified {
 			return err
 			return err
@@ -120,6 +123,10 @@ func (ec *endpointCnt) updateStore() error {
 		if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
 		if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
 			return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err)
 			return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err)
 		}
 		}
+		ec.Lock()
+		ec.Count = count
+		ec.n = n
+		ec.Unlock()
 	}
 	}
 }
 }
 
 
@@ -136,7 +143,9 @@ retry:
 	if inc {
 	if inc {
 		ec.Count++
 		ec.Count++
 	} else {
 	} else {
-		ec.Count--
+		if ec.Count > 0 {
+			ec.Count--
+		}
 	}
 	}
 	ec.Unlock()
 	ec.Unlock()
 
 

+ 5 - 1
vendor/src/github.com/docker/libnetwork/network.go

@@ -1105,9 +1105,13 @@ func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
 	}
 	}
 
 
 	var recs []etchosts.Record
 	var recs []etchosts.Record
-	sr, _ := n.ctrlr.svcRecords[n.id]
+
 	epName := ep.Name()
 	epName := ep.Name()
 
 
+	n.ctrlr.Lock()
+	sr, _ := n.ctrlr.svcRecords[n.id]
+	n.ctrlr.Unlock()
+
 	for h, ip := range sr.svcMap {
 	for h, ip := range sr.svcMap {
 		if strings.Split(h, ".")[0] == epName {
 		if strings.Split(h, ".")[0] == epName {
 			continue
 			continue

+ 1 - 1
vendor/src/github.com/docker/libnetwork/networkdb/cluster.go

@@ -81,7 +81,7 @@ func (nDB *NetworkDB) RemoveKey(key []byte) {
 func (nDB *NetworkDB) clusterInit() error {
 func (nDB *NetworkDB) clusterInit() error {
 	config := memberlist.DefaultLANConfig()
 	config := memberlist.DefaultLANConfig()
 	config.Name = nDB.config.NodeName
 	config.Name = nDB.config.NodeName
-	config.BindAddr = nDB.config.BindAddr
+	config.AdvertiseAddr = nDB.config.AdvertiseAddr
 
 
 	if nDB.config.BindPort != 0 {
 	if nDB.config.BindPort != 0 {
 		config.BindPort = nDB.config.BindPort
 		config.BindPort = nDB.config.BindPort

+ 2 - 2
vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go

@@ -107,9 +107,9 @@ type Config struct {
 	// NodeName is the cluster wide unique name for this node.
 	// NodeName is the cluster wide unique name for this node.
 	NodeName string
 	NodeName string
 
 
-	// BindAddr is the local node's IP address that we bind to for
+	// AdvertiseAddr is the node's IP address that we advertise for
 	// cluster communication.
 	// cluster communication.
-	BindAddr string
+	AdvertiseAddr string
 
 
 	// BindPort is the local node's port to which we bind to for
 	// BindPort is the local node's port to which we bind to for
 	// cluster communication.
 	// cluster communication.

+ 1 - 0
vendor/src/github.com/docker/libnetwork/osl/interface_linux.go

@@ -303,6 +303,7 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If
 	for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ {
 	for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ {
 		log.Debugf("retrying link setup because of: %v", err)
 		log.Debugf("retrying link setup because of: %v", err)
 		time.Sleep(10 * time.Millisecond)
 		time.Sleep(10 * time.Millisecond)
+		err = nlh.LinkSetUp(iface)
 	}
 	}
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("failed to set link up: %v", err)
 		return fmt.Errorf("failed to set link up: %v", err)

+ 15 - 4
vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go

@@ -6,6 +6,7 @@ import (
 	"net"
 	"net"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
+	"path/filepath"
 	"runtime"
 	"runtime"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
@@ -21,7 +22,7 @@ import (
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
 )
 )
 
 
-const prefix = "/var/run/docker/netns"
+const defaultPrefix = "/var/run/docker"
 
 
 var (
 var (
 	once             sync.Once
 	once             sync.Once
@@ -30,6 +31,7 @@ var (
 	gpmWg            sync.WaitGroup
 	gpmWg            sync.WaitGroup
 	gpmCleanupPeriod = 60 * time.Second
 	gpmCleanupPeriod = 60 * time.Second
 	gpmChan          = make(chan chan struct{})
 	gpmChan          = make(chan chan struct{})
+	prefix           = defaultPrefix
 )
 )
 
 
 // The networkNamespace type is the linux implementation of the Sandbox
 // The networkNamespace type is the linux implementation of the Sandbox
@@ -48,12 +50,21 @@ type networkNamespace struct {
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+	prefix = path
+}
+
 func init() {
 func init() {
 	reexec.Register("netns-create", reexecCreateNamespace)
 	reexec.Register("netns-create", reexecCreateNamespace)
 }
 }
 
 
+func basePath() string {
+	return filepath.Join(prefix, "netns")
+}
+
 func createBasePath() {
 func createBasePath() {
-	err := os.MkdirAll(prefix, 0755)
+	err := os.MkdirAll(basePath(), 0755)
 	if err != nil {
 	if err != nil {
 		panic("Could not create net namespace path directory")
 		panic("Could not create net namespace path directory")
 	}
 	}
@@ -142,7 +153,7 @@ func GenerateKey(containerID string) string {
 			indexStr string
 			indexStr string
 			tmpkey   string
 			tmpkey   string
 		)
 		)
-		dir, err := ioutil.ReadDir(prefix)
+		dir, err := ioutil.ReadDir(basePath())
 		if err != nil {
 		if err != nil {
 			return ""
 			return ""
 		}
 		}
@@ -172,7 +183,7 @@ func GenerateKey(containerID string) string {
 		maxLen = len(containerID)
 		maxLen = len(containerID)
 	}
 	}
 
 
-	return prefix + "/" + containerID[:maxLen]
+	return basePath() + "/" + containerID[:maxLen]
 }
 }
 
 
 // NewSandbox provides a new sandbox instance created in an os specific way
 // NewSandbox provides a new sandbox instance created in an os specific way

+ 4 - 0
vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go

@@ -10,3 +10,7 @@ func GC() {
 func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
 func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
 	return nil, nil
 	return nil, nil
 }
 }
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}

+ 4 - 0
vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go

@@ -37,3 +37,7 @@ func InitOSContext() func() {
 func SetupTestOSContext(t *testing.T) func() {
 func SetupTestOSContext(t *testing.T) func() {
 	return func() {}
 	return func() {}
 }
 }
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}

+ 4 - 0
vendor/src/github.com/docker/libnetwork/osl/sandbox_freebsd.go

@@ -38,3 +38,7 @@ func InitOSContext() func() {
 func SetupTestOSContext(t *testing.T) func() {
 func SetupTestOSContext(t *testing.T) func() {
 	return func() {}
 	return func() {}
 }
 }
+
+// SetBasePath sets the base url prefix for the ns path
+func SetBasePath(path string) {
+}

+ 17 - 3
vendor/src/github.com/docker/libnetwork/sandbox.go

@@ -413,7 +413,12 @@ func (sb *sandbox) ResolveIP(ip string) string {
 	for _, ep := range sb.getConnectedEndpoints() {
 	for _, ep := range sb.getConnectedEndpoints() {
 		n := ep.getNetwork()
 		n := ep.getNetwork()
 
 
-		sr, ok := n.getController().svcRecords[n.ID()]
+		c := n.getController()
+
+		c.Lock()
+		sr, ok := c.svcRecords[n.ID()]
+		c.Unlock()
+
 		if !ok {
 		if !ok {
 			continue
 			continue
 		}
 		}
@@ -454,7 +459,12 @@ func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP, error) {
 	for _, ep := range sb.getConnectedEndpoints() {
 	for _, ep := range sb.getConnectedEndpoints() {
 		n := ep.getNetwork()
 		n := ep.getNetwork()
 
 
-		sr, ok := n.getController().svcRecords[n.ID()]
+		c := n.getController()
+
+		c.Lock()
+		sr, ok := c.svcRecords[n.ID()]
+		c.Unlock()
+
 		if !ok {
 		if !ok {
 			continue
 			continue
 		}
 		}
@@ -575,7 +585,11 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
 			ep.Unlock()
 			ep.Unlock()
 		}
 		}
 
 
-		sr, ok := n.getController().svcRecords[n.ID()]
+		c := n.getController()
+		c.Lock()
+		sr, ok := c.svcRecords[n.ID()]
+		c.Unlock()
+
 		if !ok {
 		if !ok {
 			continue
 			continue
 		}
 		}

+ 1 - 1
vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go

@@ -15,7 +15,7 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 )
 
 
-const udsBase = "/var/lib/docker/network/files/"
+const udsBase = "/run/docker/libnetwork/"
 const success = "success"
 const success = "success"
 
 
 // processSetKeyReexec is a private function that must be called only on an reexec path
 // processSetKeyReexec is a private function that must be called only on an reexec path

+ 12 - 1
vendor/src/github.com/vishvananda/netlink/addr_linux.go

@@ -8,6 +8,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 )
 
 
 // IFA_FLAGS is a u32 attribute.
 // IFA_FLAGS is a u32 attribute.
@@ -192,7 +193,17 @@ type AddrUpdate struct {
 // AddrSubscribe takes a chan down which notifications will be sent
 // AddrSubscribe takes a chan down which notifications will be sent
 // when addresses change.  Close the 'done' chan to stop subscription.
 // when addresses change.  Close the 'done' chan to stop subscription.
 func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
 func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
+	return addrSubscribe(netns.None(), netns.None(), ch, done)
+}
+
+// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
+	return addrSubscribe(ns, netns.None(), ch, done)
+}
+
+func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 2
vendor/src/github.com/vishvananda/netlink/filter_linux.go

@@ -143,7 +143,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
 		if u32.RedirIndex != 0 {
 		if u32.RedirIndex != 0 {
 			u32.Actions = append([]Action{NewMirredAction(u32.RedirIndex)}, u32.Actions...)
 			u32.Actions = append([]Action{NewMirredAction(u32.RedirIndex)}, u32.Actions...)
 		}
 		}
-		if err := encodeActions(actionsAttr, u32.Actions); err != nil {
+		if err := EncodeActions(actionsAttr, u32.Actions); err != nil {
 			return err
 			return err
 		}
 		}
 	} else if fw, ok := filter.(*Fw); ok {
 	} else if fw, ok := filter.(*Fw); ok {
@@ -309,7 +309,7 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
 	attrs.Bindcnt = int(tcgen.Bindcnt)
 	attrs.Bindcnt = int(tcgen.Bindcnt)
 }
 }
 
 
-func encodeActions(attr *nl.RtAttr, actions []Action) error {
+func EncodeActions(attr *nl.RtAttr, actions []Action) error {
 	tabIndex := int(nl.TCA_ACT_TAB)
 	tabIndex := int(nl.TCA_ACT_TAB)
 
 
 	for _, action := range actions {
 	for _, action := range actions {

+ 14 - 3
vendor/src/github.com/vishvananda/netlink/link_linux.go

@@ -10,6 +10,7 @@ import (
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 )
 
 
 const SizeofLinkStats = 0x5c
 const SizeofLinkStats = 0x5c
@@ -425,7 +426,7 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
 	}
 	}
 	if vxlan.GBP {
 	if vxlan.GBP {
-		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, boolAttr(vxlan.GBP))
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{})
 	}
 	}
 	if vxlan.NoAge {
 	if vxlan.NoAge {
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
 		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
@@ -1011,7 +1012,17 @@ type LinkUpdate struct {
 // LinkSubscribe takes a chan down which notifications will be sent
 // LinkSubscribe takes a chan down which notifications will be sent
 // when links change.  Close the 'done' chan to stop subscription.
 // when links change.  Close the 'done' chan to stop subscription.
 func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
 func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
+	return linkSubscribe(netns.None(), netns.None(), ch, done)
+}
+
+// LinkSubscribeAt works like LinkSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
+	return linkSubscribe(ns, netns.None(), ch, done)
+}
+
+func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_LINK)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -1152,7 +1163,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
 		case nl.IFLA_VXLAN_UDP_CSUM:
 		case nl.IFLA_VXLAN_UDP_CSUM:
 			vxlan.UDPCSum = int8(datum.Value[0]) != 0
 			vxlan.UDPCSum = int8(datum.Value[0]) != 0
 		case nl.IFLA_VXLAN_GBP:
 		case nl.IFLA_VXLAN_GBP:
-			vxlan.GBP = int8(datum.Value[0]) != 0
+			vxlan.GBP = true
 		case nl.IFLA_VXLAN_AGEING:
 		case nl.IFLA_VXLAN_AGEING:
 			vxlan.Age = int(native.Uint32(datum.Value[0:4]))
 			vxlan.Age = int(native.Uint32(datum.Value[0:4]))
 			vxlan.NoAge = vxlan.Age == 0
 			vxlan.NoAge = vxlan.Age == 0

+ 57 - 6
vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -331,24 +331,63 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
 // moves back into it when done. If newNs is close, the socket will be opened
 // moves back into it when done. If newNs is close, the socket will be opened
 // in the current network namespace.
 // in the current network namespace.
 func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) {
 func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) {
-	var err error
+	c, err := executeInNetns(newNs, curNs)
+	if err != nil {
+		return nil, err
+	}
+	defer c()
+	return getNetlinkSocket(protocol)
+}
 
 
+// executeInNetns sets execution of the code following this call to the
+// network namespace newNs, then moves the thread back to curNs if open,
+// otherwise to the current netns at the time the function was invoked
+// In case of success, the caller is expected to execute the returned function
+// at the end of the code that needs to be executed in the network namespace.
+// Example:
+// func jobAt(...) error {
+//      d, err := executeInNetns(...)
+//      if err != nil { return err}
+//      defer d()
+//      < code which needs to be executed in specific netns>
+//  }
+// TODO: his function probably belongs to netns pkg.
+func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
+	var (
+		err       error
+		moveBack  func(netns.NsHandle) error
+		closeNs   func() error
+		unlockThd func()
+	)
+	restore := func() {
+		// order matters
+		if moveBack != nil {
+			moveBack(curNs)
+		}
+		if closeNs != nil {
+			closeNs()
+		}
+		if unlockThd != nil {
+			unlockThd()
+		}
+	}
 	if newNs.IsOpen() {
 	if newNs.IsOpen() {
 		runtime.LockOSThread()
 		runtime.LockOSThread()
-		defer runtime.UnlockOSThread()
+		unlockThd = runtime.UnlockOSThread
 		if !curNs.IsOpen() {
 		if !curNs.IsOpen() {
 			if curNs, err = netns.Get(); err != nil {
 			if curNs, err = netns.Get(); err != nil {
+				restore()
 				return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err)
 				return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err)
 			}
 			}
-			defer curNs.Close()
+			closeNs = curNs.Close
 		}
 		}
 		if err := netns.Set(newNs); err != nil {
 		if err := netns.Set(newNs); err != nil {
+			restore()
 			return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err)
 			return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err)
 		}
 		}
-		defer netns.Set(curNs)
+		moveBack = netns.Set
 	}
 	}
-
-	return getNetlinkSocket(protocol)
+	return restore, nil
 }
 }
 
 
 // Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
 // Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
@@ -377,6 +416,18 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 	return s, nil
 	return s, nil
 }
 }
 
 
+// SubscribeAt works like Subscribe plus let's the caller choose the network
+// namespace in which the socket would be opened (newNs). Then control goes back
+// to curNs if open, otherwise to the netns at the time this function was called.
+func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) {
+	c, err := executeInNetns(newNs, curNs)
+	if err != nil {
+		return nil, err
+	}
+	defer c()
+	return Subscribe(protocol, groups...)
+}
+
 func (s *NetlinkSocket) Close() {
 func (s *NetlinkSocket) Close() {
 	syscall.Close(s.fd)
 	syscall.Close(s.fd)
 	s.fd = -1
 	s.fd = -1

+ 30 - 0
vendor/src/github.com/vishvananda/netlink/nl/xfrm_state_linux.go

@@ -10,6 +10,7 @@ const (
 	SizeofXfrmUsersaInfo  = 0xe0
 	SizeofXfrmUsersaInfo  = 0xe0
 	SizeofXfrmAlgo        = 0x44
 	SizeofXfrmAlgo        = 0x44
 	SizeofXfrmAlgoAuth    = 0x48
 	SizeofXfrmAlgoAuth    = 0x48
+	SizeofXfrmAlgoAEAD    = 0x48
 	SizeofXfrmEncapTmpl   = 0x18
 	SizeofXfrmEncapTmpl   = 0x18
 	SizeofXfrmUsersaFlush = 0x8
 	SizeofXfrmUsersaFlush = 0x8
 )
 )
@@ -194,6 +195,35 @@ func (msg *XfrmAlgoAuth) Serialize() []byte {
 //   char    alg_key[0];
 //   char    alg_key[0];
 // }
 // }
 
 
+type XfrmAlgoAEAD struct {
+	AlgName   [64]byte
+	AlgKeyLen uint32
+	AlgICVLen uint32
+	AlgKey    []byte
+}
+
+func (msg *XfrmAlgoAEAD) Len() int {
+	return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8)
+}
+
+func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD {
+	ret := XfrmAlgoAEAD{}
+	copy(ret.AlgName[:], b[0:64])
+	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
+	ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68]))
+	ret.AlgKey = b[72:ret.Len()]
+	return &ret
+}
+
+func (msg *XfrmAlgoAEAD) Serialize() []byte {
+	b := make([]byte, msg.Len())
+	copy(b[0:64], msg.AlgName[:])
+	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
+	copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:])
+	copy(b[72:msg.Len()], msg.AlgKey[:])
+	return b
+}
+
 // struct xfrm_encap_tmpl {
 // struct xfrm_encap_tmpl {
 //   __u16   encap_type;
 //   __u16   encap_type;
 //   __be16    encap_sport;
 //   __be16    encap_sport;

+ 12 - 1
vendor/src/github.com/vishvananda/netlink/route_linux.go

@@ -6,6 +6,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
 )
 )
 
 
 // RtAttr is shared so it is in netlink_linux.go
 // RtAttr is shared so it is in netlink_linux.go
@@ -421,7 +422,17 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
 // RouteSubscribe takes a chan down which notifications will be sent
 // RouteSubscribe takes a chan down which notifications will be sent
 // when routes are added or deleted. Close the 'done' chan to stop subscription.
 // when routes are added or deleted. Close the 'done' chan to stop subscription.
 func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
 func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
-	s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
+	return routeSubscribeAt(netns.None(), netns.None(), ch, done)
+}
+
+// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
+	return routeSubscribeAt(ns, netns.None(), ch, done)
+}
+
+func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
+	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 12 - 3
vendor/src/github.com/vishvananda/netlink/xfrm_state.go

@@ -10,10 +10,18 @@ type XfrmStateAlgo struct {
 	Name        string
 	Name        string
 	Key         []byte
 	Key         []byte
 	TruncateLen int // Auth only
 	TruncateLen int // Auth only
+	ICVLen      int // AEAD only
 }
 }
 
 
 func (a XfrmStateAlgo) String() string {
 func (a XfrmStateAlgo) String() string {
-	return fmt.Sprintf("{Name: %s, Key: 0x%x, TruncateLen: %d}", a.Name, a.Key, a.TruncateLen)
+	base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key)
+	if a.TruncateLen != 0 {
+		base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen)
+	}
+	if a.ICVLen != 0 {
+		base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen)
+	}
+	return fmt.Sprintf("%s}", base)
 }
 }
 
 
 // EncapType is an enum representing the optional packet encapsulation.
 // EncapType is an enum representing the optional packet encapsulation.
@@ -73,12 +81,13 @@ type XfrmState struct {
 	Mark         *XfrmMark
 	Mark         *XfrmMark
 	Auth         *XfrmStateAlgo
 	Auth         *XfrmStateAlgo
 	Crypt        *XfrmStateAlgo
 	Crypt        *XfrmStateAlgo
+	Aead         *XfrmStateAlgo
 	Encap        *XfrmStateEncap
 	Encap        *XfrmStateEncap
 }
 }
 
 
 func (sa XfrmState) String() string {
 func (sa XfrmState) String() string {
-	return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Encap: %v",
-		sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Encap)
+	return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v,Encap: %v",
+		sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap)
 }
 }
 func (sa XfrmState) Print(stats bool) string {
 func (sa XfrmState) Print(stats bool) string {
 	if !stats {
 	if !stats {

+ 24 - 0
vendor/src/github.com/vishvananda/netlink/xfrm_state_linux.go

@@ -35,6 +35,20 @@ func writeStateAlgoAuth(a *XfrmStateAlgo) []byte {
 	return algo.Serialize()
 	return algo.Serialize()
 }
 }
 
 
+func writeStateAlgoAead(a *XfrmStateAlgo) []byte {
+	algo := nl.XfrmAlgoAEAD{
+		AlgKeyLen: uint32(len(a.Key) * 8),
+		AlgICVLen: uint32(a.ICVLen),
+		AlgKey:    a.Key,
+	}
+	end := len(a.Name)
+	if end > 64 {
+		end = 64
+	}
+	copy(algo.AlgName[:end], a.Name)
+	return algo.Serialize()
+}
+
 func writeMark(m *XfrmMark) []byte {
 func writeMark(m *XfrmMark) []byte {
 	mark := &nl.XfrmMark{
 	mark := &nl.XfrmMark{
 		Value: m.Value,
 		Value: m.Value,
@@ -97,6 +111,10 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
 		out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt))
 		out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt))
 		req.AddData(out)
 		req.AddData(out)
 	}
 	}
+	if state.Aead != nil {
+		out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead))
+		req.AddData(out)
+	}
 	if state.Encap != nil {
 	if state.Encap != nil {
 		encapData := make([]byte, nl.SizeofXfrmEncapTmpl)
 		encapData := make([]byte, nl.SizeofXfrmEncapTmpl)
 		encap := nl.DeserializeXfrmEncapTmpl(encapData)
 		encap := nl.DeserializeXfrmEncapTmpl(encapData)
@@ -271,6 +289,12 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
 			state.Auth.Name = nl.BytesToString(algo.AlgName[:])
 			state.Auth.Name = nl.BytesToString(algo.AlgName[:])
 			state.Auth.Key = algo.AlgKey
 			state.Auth.Key = algo.AlgKey
 			state.Auth.TruncateLen = int(algo.AlgTruncLen)
 			state.Auth.TruncateLen = int(algo.AlgTruncLen)
+		case nl.XFRMA_ALG_AEAD:
+			state.Aead = new(XfrmStateAlgo)
+			algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:])
+			state.Aead.Name = nl.BytesToString(algo.AlgName[:])
+			state.Aead.Key = algo.AlgKey
+			state.Aead.ICVLen = int(algo.AlgICVLen)
 		case nl.XFRMA_ENCAP:
 		case nl.XFRMA_ENCAP:
 			encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
 			encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
 			state.Encap = new(XfrmStateEncap)
 			state.Encap = new(XfrmStateEncap)