Переглянути джерело

Merge pull request #29004 from aboch/c1.12.x

[1.12.x] Porting libnetwork fixes
Victor Vieux 8 роки тому
батько
коміт
f25e197379
35 змінених файлів з 603 додано та 117 видалено
  1. 3 3
      hack/vendor.sh
  2. 2 2
      integration-cli/docker_cli_network_unix_test.go
  3. 1 1
      vendor/src/github.com/docker/libkv/.travis.yml
  4. 0 6
      vendor/src/github.com/docker/libkv/MAINTAINERS
  5. 6 1
      vendor/src/github.com/docker/libkv/store/boltdb/boltdb.go
  6. 106 50
      vendor/src/github.com/docker/libnetwork/agent.go
  7. 9 2
      vendor/src/github.com/docker/libnetwork/controller.go
  8. 3 1
      vendor/src/github.com/docker/libnetwork/datastore/datastore.go
  9. 1 1
      vendor/src/github.com/docker/libnetwork/default_gateway.go
  10. 1 1
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go
  11. 5 0
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go
  12. 6 0
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go
  13. 1 1
      vendor/src/github.com/docker/libnetwork/drivers/overlay/peerdb.go
  14. 3 3
      vendor/src/github.com/docker/libnetwork/endpoint_info.go
  15. 1 1
      vendor/src/github.com/docker/libnetwork/ipam/allocator.go
  16. 2 2
      vendor/src/github.com/docker/libnetwork/iptables/iptables.go
  17. 0 3
      vendor/src/github.com/docker/libnetwork/network.go
  18. 6 0
      vendor/src/github.com/docker/libnetwork/networkdb/cluster.go
  19. 21 2
      vendor/src/github.com/docker/libnetwork/ns/init_linux.go
  20. 10 0
      vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go
  21. 1 0
      vendor/src/github.com/docker/libnetwork/osl/neigh_linux.go
  22. 16 4
      vendor/src/github.com/docker/libnetwork/resolver.go
  23. 7 1
      vendor/src/github.com/docker/libnetwork/sandbox.go
  24. 1 1
      vendor/src/github.com/docker/libnetwork/service_linux.go
  25. 7 5
      vendor/src/github.com/vishvananda/netlink/bpf_linux.go
  26. 2 2
      vendor/src/github.com/vishvananda/netlink/filter.go
  27. 25 0
      vendor/src/github.com/vishvananda/netlink/handle_linux.go
  28. 13 1
      vendor/src/github.com/vishvananda/netlink/link.go
  29. 138 9
      vendor/src/github.com/vishvananda/netlink/link_linux.go
  30. 23 2
      vendor/src/github.com/vishvananda/netlink/neigh_linux.go
  31. 30 6
      vendor/src/github.com/vishvananda/netlink/nl/link_linux.go
  32. 141 0
      vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go
  33. 1 1
      vendor/src/github.com/vishvananda/netlink/route_linux.go
  34. 10 4
      vendor/src/github.com/vishvananda/netlink/rule_linux.go
  35. 1 1
      vendor/src/github.com/vishvananda/netlink/xfrm_state_linux.go

+ 3 - 3
hack/vendor.sh

@@ -65,7 +65,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
 clone git github.com/imdario/mergo 0.2.1
 
 #get libnetwork packages
-clone git github.com/docker/libnetwork 66c844678f7d7df33e4f46184e5b4749f0204b5a
+clone git github.com/docker/libnetwork 73363066ecb4df200da5a056d79ca4026376a5ad
 clone git github.com/docker/go-events afb2b9f2c23f33ada1a22b03651775fdc65a5089
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
@@ -73,9 +73,9 @@ clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece581016509
 clone git github.com/hashicorp/memberlist 88ac4de0d1a0ca6def284b571342db3b777a4c37
 clone git github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
 clone git github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
-clone git github.com/docker/libkv v0.2.1
+clone git github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
 clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
-clone git github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6c
+clone git github.com/vishvananda/netlink 17ea11b5a11c5614597c65a671105e8ee58c4d04
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d

+ 2 - 2
integration-cli/docker_cli_network_unix_test.go

@@ -671,7 +671,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomUnspecified(c *check.
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C) {
-	dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0")
+	dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=fd80:24e2:f998:72d6::/64", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0")
 	assertNwIsAvailable(c, "br0")
 
 	nr := getNetworkResource(c, "br0")
@@ -680,7 +680,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C)
 	c.Assert(nr.Internal, checker.Equals, false)
 	c.Assert(nr.EnableIPv6, checker.Equals, true)
 	c.Assert(nr.IPAM.Driver, checker.Equals, "default")
-	c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
+	c.Assert(len(nr.IPAM.Config), checker.Equals, 2)
 	c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
 	c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
 	c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")

+ 1 - 1
vendor/src/github.com/docker/libkv/.travis.yml

@@ -1,7 +1,7 @@
 language: go
 
 go:
-  - 1.5.3
+  - 1.7.1
 
 # let us have speedy Docker-based Travis workers
 sudo: false

+ 0 - 6
vendor/src/github.com/docker/libkv/MAINTAINERS

@@ -11,7 +11,6 @@
 [Org]
 	[Org."Core maintainers"]
 		people = [
-			"abronan",
 			"aluzzardi",
 			"sanimej",
 			"vieux",
@@ -25,11 +24,6 @@
 
 	# ADD YOURSELF HERE IN ALPHABETICAL ORDER
 
-	[people.abronan]
-	Name = "Alexandre Beslic"
-	Email = "abronan@docker.com"
-	GitHub = "abronan"
-
 	[people.aluzzardi]
 	Name = "Andrea Luzzardi"
 	Email = "al@docker.com"

+ 6 - 1
vendor/src/github.com/docker/libkv/store/boltdb/boltdb.go

@@ -59,6 +59,7 @@ func New(endpoints []string, options *store.Config) (store.Store, error) {
 		db          *bolt.DB
 		err         error
 		boltOptions *bolt.Options
+		timeout     = transientTimeout
 	)
 
 	if len(endpoints) > 1 {
@@ -82,11 +83,15 @@ func New(endpoints []string, options *store.Config) (store.Store, error) {
 		}
 	}
 
+	if options.ConnectionTimeout != 0 {
+		timeout = options.ConnectionTimeout
+	}
+
 	b := &BoltDB{
 		client:            db,
 		path:              endpoints[0],
 		boltBucket:        []byte(options.Bucket),
-		timeout:           transientTimeout,
+		timeout:           timeout,
 		PersistConnection: options.PersistConnection,
 	}
 

+ 106 - 50
vendor/src/github.com/docker/libnetwork/agent.go

@@ -7,6 +7,7 @@ import (
 	"net"
 	"os"
 	"sort"
+	"sync"
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/stringid"
@@ -39,6 +40,7 @@ type agent struct {
 	advertiseAddr     string
 	epTblCancel       func()
 	driverCancelFuncs map[string][]func()
+	sync.Mutex
 }
 
 func getBindAddr(ifaceName string) (string, error) {
@@ -86,9 +88,16 @@ func resolveAddr(addrOrInterface string) (string, error) {
 func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
 	drvEnc := discoverapi.DriverEncryptionUpdate{}
 
-	a := c.agent
+	a := c.getAgent()
+	if a == nil {
+		logrus.Debug("Skipping key change as agent is nil")
+		return nil
+	}
+
 	// Find the deleted key. If the deleted key was the primary key,
 	// a new primary key should be set before removing if from keyring.
+	c.Lock()
+	added := []byte{}
 	deleted := []byte{}
 	j := len(c.keys)
 	for i := 0; i < j; {
@@ -127,7 +136,7 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
 		if !same {
 			c.keys = append(c.keys, key)
 			if key.Subsystem == subsysGossip {
-				a.networkDB.SetKey(key.Key)
+				added = key.Key
 			}
 
 			if key.Subsystem == subsysIPSec {
@@ -136,6 +145,11 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
 			}
 		}
 	}
+	c.Unlock()
+
+	if len(added) > 0 {
+		a.networkDB.SetKey(added)
+	}
 
 	key, tag, err := c.getPrimaryKeyTag(subsysGossip)
 	if err != nil {
@@ -166,8 +180,10 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
 }
 
 func (c *controller) agentSetup() error {
+	c.Lock()
 	clusterProvider := c.cfg.Daemon.ClusterProvider
-
+	agent := c.agent
+	c.Unlock()
 	bindAddr := clusterProvider.GetLocalAddress()
 	advAddr := clusterProvider.GetAdvertiseAddress()
 	remote := clusterProvider.GetRemoteAddress()
@@ -176,7 +192,7 @@ func (c *controller) agentSetup() error {
 	listenAddr, _, _ := net.SplitHostPort(listen)
 
 	logrus.Infof("Initializing Libnetwork Agent Listen-Addr=%s Local-addr=%s Adv-addr=%s Remote-addr =%s", listenAddr, bindAddr, advAddr, remoteAddr)
-	if advAddr != "" && c.agent == nil {
+	if advAddr != "" && agent == nil {
 		if err := c.agentInit(listenAddr, bindAddr, advAddr); err != nil {
 			logrus.Errorf("Error in agentInit : %v", err)
 		} else {
@@ -208,6 +224,9 @@ func (c *controller) agentSetup() error {
 // For a given subsystem getKeys sorts the keys by lamport time and returns
 // slice of keys and lamport time which can used as a unique tag for the keys
 func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
+	c.Lock()
+	defer c.Unlock()
+
 	sort.Sort(ByTime(c.keys))
 
 	keys := [][]byte{}
@@ -227,6 +246,8 @@ func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
 // getPrimaryKeyTag returns the primary key for a given subsystem from the
 // list of sorted key and the associated tag
 func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64, error) {
+	c.Lock()
+	defer c.Unlock()
 	sort.Sort(ByTime(c.keys))
 	keys := []*types.EncryptionKey{}
 	for _, key := range c.keys {
@@ -265,6 +286,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
 
 	ch, cancel := nDB.Watch("endpoint_table", "", "")
 
+	c.Lock()
 	c.agent = &agent{
 		networkDB:         nDB,
 		bindAddr:          bindAddr,
@@ -272,6 +294,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
 		epTblCancel:       cancel,
 		driverCancelFuncs: make(map[string][]func()),
 	}
+	c.Unlock()
 
 	go c.handleTableEvents(ch, c.handleEpTableEvent)
 
@@ -294,21 +317,22 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
 }
 
 func (c *controller) agentJoin(remote string) error {
-	if c.agent == nil {
+	agent := c.getAgent()
+	if agent == nil {
 		return nil
 	}
-
-	return c.agent.networkDB.Join([]string{remote})
+	return agent.networkDB.Join([]string{remote})
 }
 
 func (c *controller) agentDriverNotify(d driverapi.Driver) {
-	if c.agent == nil {
+	agent := c.getAgent()
+	if agent == nil {
 		return
 	}
 
 	d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{
-		Address:     c.agent.advertiseAddr,
-		BindAddress: c.agent.bindAddr,
+		Address:     agent.advertiseAddr,
+		BindAddress: agent.bindAddr,
 		Self:        true,
 	})
 
@@ -328,35 +352,41 @@ func (c *controller) agentDriverNotify(d driverapi.Driver) {
 }
 
 func (c *controller) agentClose() {
-	if c.agent == nil {
+	// Acquire current agent instance and reset its pointer
+	// then run closing functions
+	c.Lock()
+	agent := c.agent
+	c.agent = nil
+	c.Unlock()
+
+	if agent == nil {
 		return
 	}
 
-	for _, cancelFuncs := range c.agent.driverCancelFuncs {
+	var cancelList []func()
+
+	agent.Lock()
+	for _, cancelFuncs := range agent.driverCancelFuncs {
 		for _, cancel := range cancelFuncs {
-			cancel()
+			cancelList = append(cancelList, cancel)
 		}
 	}
-	c.agent.epTblCancel()
+	agent.Unlock()
 
-	c.agent.networkDB.Close()
+	for _, cancel := range cancelList {
+		cancel()
+	}
 
-	c.Lock()
-	c.agent = nil
-	c.Unlock()
+	agent.epTblCancel()
+
+	agent.networkDB.Close()
 }
 
 func (n *network) isClusterEligible() bool {
 	if n.driverScope() != datastore.GlobalScope {
 		return false
 	}
-
-	c := n.getController()
-	if c.agent == nil {
-		return false
-	}
-
-	return true
+	return n.getController().getAgent() != nil
 }
 
 func (n *network) joinCluster() error {
@@ -364,8 +394,12 @@ func (n *network) joinCluster() error {
 		return nil
 	}
 
-	c := n.getController()
-	return c.agent.networkDB.JoinNetwork(n.ID())
+	agent := n.getController().getAgent()
+	if agent == nil {
+		return nil
+	}
+
+	return agent.networkDB.JoinNetwork(n.ID())
 }
 
 func (n *network) leaveCluster() error {
@@ -373,8 +407,12 @@ func (n *network) leaveCluster() error {
 		return nil
 	}
 
-	c := n.getController()
-	return c.agent.networkDB.LeaveNetwork(n.ID())
+	agent := n.getController().getAgent()
+	if agent == nil {
+		return nil
+	}
+
+	return agent.networkDB.LeaveNetwork(n.ID())
 }
 
 func (ep *endpoint) addToCluster() error {
@@ -384,6 +422,7 @@ func (ep *endpoint) addToCluster() error {
 	}
 
 	c := n.getController()
+	agent := c.getAgent()
 	if !ep.isAnonymous() && ep.Iface().Address() != nil {
 		var ingressPorts []*PortConfig
 		if ep.svcID != "" {
@@ -412,13 +451,19 @@ func (ep *endpoint) addToCluster() error {
 			return err
 		}
 
-		if err := c.agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil {
-			return err
+		if agent != nil {
+			if err := agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil {
+				return err
+			}
 		}
 	}
 
+	if agent == nil {
+		return nil
+	}
+
 	for _, te := range ep.joinInfo.driverTableEntries {
-		if err := c.agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
+		if err := agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
 			return err
 		}
 	}
@@ -433,6 +478,8 @@ func (ep *endpoint) deleteFromCluster() error {
 	}
 
 	c := n.getController()
+	agent := c.getAgent()
+
 	if !ep.isAnonymous() {
 		if ep.svcID != "" && ep.Iface().Address() != nil {
 			var ingressPorts []*PortConfig
@@ -445,8 +492,10 @@ func (ep *endpoint) deleteFromCluster() error {
 			}
 		}
 
-		if err := c.agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil {
-			return err
+		if agent != nil {
+			if err := agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -454,8 +503,12 @@ func (ep *endpoint) deleteFromCluster() error {
 		return nil
 	}
 
+	if agent == nil {
+		return nil
+	}
+
 	for _, te := range ep.joinInfo.driverTableEntries {
-		if err := c.agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
+		if err := agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
 			return err
 		}
 	}
@@ -469,16 +522,15 @@ func (n *network) addDriverWatches() {
 	}
 
 	c := n.getController()
+	agent := c.getAgent()
+	if agent == nil {
+		return
+	}
 	for _, tableName := range n.driverTables {
-		c.Lock()
-		if c.agent == nil {
-			c.Unlock()
-			return
-		}
-		ch, cancel := c.agent.networkDB.Watch(tableName, n.ID(), "")
-		c.agent.driverCancelFuncs[n.ID()] = append(c.agent.driverCancelFuncs[n.ID()], cancel)
-		c.Unlock()
-
+		ch, cancel := agent.networkDB.Watch(tableName, n.ID(), "")
+		agent.Lock()
+		agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel)
+		agent.Unlock()
 		go c.handleTableEvents(ch, n.handleDriverTableEvent)
 		d, err := n.driver(false)
 		if err != nil {
@@ -486,7 +538,7 @@ func (n *network) addDriverWatches() {
 			return
 		}
 
-		c.agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool {
+		agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool {
 			if nid == n.ID() {
 				d.EventNotify(driverapi.Create, nid, tableName, key, value)
 			}
@@ -501,11 +553,15 @@ func (n *network) cancelDriverWatches() {
 		return
 	}
 
-	c := n.getController()
-	c.Lock()
-	cancelFuncs := c.agent.driverCancelFuncs[n.ID()]
-	delete(c.agent.driverCancelFuncs, n.ID())
-	c.Unlock()
+	agent := n.getController().getAgent()
+	if agent == nil {
+		return
+	}
+
+	agent.Lock()
+	cancelFuncs := agent.driverCancelFuncs[n.ID()]
+	delete(agent.driverCancelFuncs, n.ID())
+	agent.Unlock()
 
 	for _, cancel := range cancelFuncs {
 		cancel()

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

@@ -232,12 +232,13 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
 
 func (c *controller) SetClusterProvider(provider cluster.Provider) {
 	c.Lock()
-	defer c.Unlock()
 	c.cfg.Daemon.ClusterProvider = provider
+	disableProviderCh := c.cfg.Daemon.DisableProvider
+	c.Unlock()
 	if provider != nil {
 		go c.clusterAgentInit()
 	} else {
-		c.cfg.Daemon.DisableProvider <- struct{}{}
+		disableProviderCh <- struct{}{}
 	}
 }
 
@@ -290,6 +291,12 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error {
 	return c.handleKeyChange(keys)
 }
 
+func (c *controller) getAgent() *agent {
+	c.Lock()
+	defer c.Unlock()
+	return c.agent
+}
+
 func (c *controller) clusterAgentInit() {
 	clusterProvider := c.cfg.Daemon.ClusterProvider
 	for {

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

@@ -6,6 +6,7 @@ import (
 	"reflect"
 	"strings"
 	"sync"
+	"time"
 
 	"github.com/docker/libkv"
 	"github.com/docker/libkv/store"
@@ -134,7 +135,8 @@ func makeDefaultScopes() map[string]*ScopeCfg {
 			Provider: string(store.BOLTDB),
 			Address:  defaultPrefix + "/local-kv.db",
 			Config: &store.Config{
-				Bucket: "libnetwork",
+				Bucket:            "libnetwork",
+				ConnectionTimeout: time.Minute,
 			},
 		},
 	}

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

@@ -107,7 +107,7 @@ func (sb *sandbox) needDefaultGW() bool {
 			return false
 		}
 		for _, r := range ep.StaticRoutes() {
-			if r.Destination.String() == "0.0.0.0/0" {
+			if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" {
 				return false
 			}
 		}

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

@@ -77,7 +77,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
 	}
 
 	if s := n.getSubnetforIP(ep.addr); s == nil {
-		return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid)
+		return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
 	}
 
 	if ep.mac == nil {

+ 5 - 0
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go

@@ -308,6 +308,11 @@ func populateVNITbl() {
 			}
 			defer nlh.Delete()
 
+			err = nlh.SetSocketTimeout(soTimeout)
+			if err != nil {
+				logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vni table population: %v", err)
+			}
+
 			links, err := nlh.LinkList()
 			if err != nil {
 				logrus.Errorf("Failed to list interfaces during vni population for ns %s: %v", path, err)

+ 6 - 0
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go

@@ -13,6 +13,8 @@ import (
 	"github.com/vishvananda/netns"
 )
 
+var soTimeout = ns.NetlinkSocketsTimeout
+
 func validateID(nid, eid string) error {
 	if nid == "" {
 		return fmt.Errorf("invalid network id")
@@ -134,6 +136,10 @@ func deleteVxlanByVNI(path string, vni uint32) error {
 			return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err)
 		}
 		defer nlh.Delete()
+		err = nlh.SetSocketTimeout(soTimeout)
+		if err != nil {
+			logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vxlan deletion: %v", err)
+		}
 	}
 
 	links, err := nlh.LinkList()

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

@@ -277,7 +277,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
 
 	s := n.getSubnetforIP(IP)
 	if s == nil {
-		return fmt.Errorf("couldn't find the subnet %q in network %q\n", IP.String(), n.id)
+		return fmt.Errorf("couldn't find the subnet %q in network %q", IP.String(), n.id)
 	}
 
 	if err := n.obtainVxlanID(s); err != nil {

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

@@ -114,12 +114,12 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
 		}
 	}
 	if v, ok := epMap["llAddrs"]; ok {
-		list := v.([]string)
+		list := v.([]interface{})
 		epi.llAddrs = make([]*net.IPNet, 0, len(list))
 		for _, llS := range list {
-			ll, err := types.ParseCIDR(llS)
+			ll, err := types.ParseCIDR(llS.(string))
 			if err != nil {
-				return types.InternalErrorf("failed to decode endpoint interface link-local address (%s) after json unmarshal: %v", llS, err)
+				return types.InternalErrorf("failed to decode endpoint interface link-local address (%v) after json unmarshal: %v", llS, err)
 			}
 			epi.llAddrs = append(epi.llAddrs, ll)
 		}

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

@@ -406,7 +406,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
 		}
 	}
 
-	return nil, types.NotFoundErrorf("could not find an available predefined network")
+	return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v)
 }
 
 // RequestAddress returns an address from the specified pool ID

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

@@ -123,7 +123,7 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
 // ProgramChain is used to add rules to a chain
 func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
 	if c.Name == "" {
-		return fmt.Errorf("Could not program chain, missing chain name.")
+		return fmt.Errorf("Could not program chain, missing chain name")
 	}
 
 	switch c.Table {
@@ -159,7 +159,7 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err
 		}
 	case Filter:
 		if bridgeName == "" {
-			return fmt.Errorf("Could not program chain %s/%s, missing bridge name.",
+			return fmt.Errorf("Could not program chain %s/%s, missing bridge name",
 				c.Table, c.Name)
 		}
 		link := []string{

+ 0 - 3
vendor/src/github.com/docker/libnetwork/network.go

@@ -1254,9 +1254,6 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
 	}
 
 	if len(*cfgList) == 0 {
-		if ipVer == 6 {
-			return nil
-		}
 		*cfgList = []*IpamConf{{}}
 	}
 

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

@@ -43,6 +43,8 @@ func (l *logWriter) Write(p []byte) (int, error) {
 // SetKey adds a new key to the key ring
 func (nDB *NetworkDB) SetKey(key []byte) {
 	logrus.Debugf("Adding key %s", hex.EncodeToString(key)[0:5])
+	nDB.Lock()
+	defer nDB.Unlock()
 	for _, dbKey := range nDB.config.Keys {
 		if bytes.Equal(key, dbKey) {
 			return
@@ -58,6 +60,8 @@ func (nDB *NetworkDB) SetKey(key []byte) {
 // been added apriori through SetKey
 func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
 	logrus.Debugf("Primary Key %s", hex.EncodeToString(key)[0:5])
+	nDB.RLock()
+	defer nDB.RUnlock()
 	for _, dbKey := range nDB.config.Keys {
 		if bytes.Equal(key, dbKey) {
 			if nDB.keyring != nil {
@@ -72,6 +76,8 @@ func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
 // can't be the primary key
 func (nDB *NetworkDB) RemoveKey(key []byte) {
 	logrus.Debugf("Remove Key %s", hex.EncodeToString(key)[0:5])
+	nDB.Lock()
+	defer nDB.Unlock()
 	for i, dbKey := range nDB.config.Keys {
 		if bytes.Equal(key, dbKey) {
 			nDB.config.Keys = append(nDB.config.Keys[:i], nDB.config.Keys[i+1:]...)

+ 21 - 2
vendor/src/github.com/docker/libnetwork/ns/init_linux.go

@@ -7,6 +7,7 @@ import (
 	"strings"
 	"sync"
 	"syscall"
+	"time"
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/vishvananda/netlink"
@@ -17,6 +18,8 @@ var (
 	initNs   netns.NsHandle
 	initNl   *netlink.Handle
 	initOnce sync.Once
+	// NetlinkSocketsTimeout represents the default timeout duration for the sockets
+	NetlinkSocketsTimeout = 3 * time.Second
 )
 
 // Init initializes a new network namespace
@@ -30,6 +33,10 @@ func Init() {
 	if err != nil {
 		log.Errorf("could not create netlink handle on initial namespace: %v", err)
 	}
+	err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
+	if err != nil {
+		log.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
+	}
 }
 
 // SetNamespace sets the initial namespace handler
@@ -69,8 +76,10 @@ func NlHandle() *netlink.Handle {
 func getSupportedNlFamilies() []int {
 	fams := []int{syscall.NETLINK_ROUTE}
 	if err := loadXfrmModules(); err != nil {
-		log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
-		return fams
+		if checkXfrmSocket() != nil {
+			log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
+			return fams
+		}
 	}
 	return append(fams, syscall.NETLINK_XFRM)
 }
@@ -84,3 +93,13 @@ func loadXfrmModules() error {
 	}
 	return nil
 }
+
+// API check on required xfrm modules (xfrm_user, xfrm_algo)
+func checkXfrmSocket() error {
+	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_XFRM)
+	if err != nil {
+		return err
+	}
+	syscall.Close(fd)
+	return nil
+}

+ 10 - 0
vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go

@@ -211,6 +211,11 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
 		return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
 	}
 
+	err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
+	if err != nil {
+		log.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
+	}
+
 	if err = n.loopbackUp(); err != nil {
 		n.nlHandle.Delete()
 		return nil, err
@@ -253,6 +258,11 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
 		return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
 	}
 
+	err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
+	if err != nil {
+		log.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
+	}
+
 	if err = n.loopbackUp(); err != nil {
 		n.nlHandle.Delete()
 		return nil, err

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

@@ -80,6 +80,7 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr,
 	for i, nh := range n.neighbors {
 		if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
 			n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
+			break
 		}
 	}
 	n.Unlock()

+ 16 - 4
vendor/src/github.com/docker/libnetwork/resolver.go

@@ -63,6 +63,7 @@ type resolver struct {
 	count      int32
 	tStamp     time.Time
 	queryLock  sync.Mutex
+	startCh    chan struct{}
 }
 
 func init() {
@@ -72,8 +73,9 @@ func init() {
 // NewResolver creates a new instance of the Resolver
 func NewResolver(sb *sandbox) Resolver {
 	return &resolver{
-		sb:  sb,
-		err: fmt.Errorf("setup not done yet"),
+		sb:      sb,
+		err:     fmt.Errorf("setup not done yet"),
+		startCh: make(chan struct{}, 1),
 	}
 }
 
@@ -107,6 +109,9 @@ func (r *resolver) SetupFunc() func() {
 }
 
 func (r *resolver) Start() error {
+	r.startCh <- struct{}{}
+	defer func() { <-r.startCh }()
+
 	// make sure the resolver has been setup before starting
 	if r.err != nil {
 		return r.err
@@ -131,6 +136,9 @@ func (r *resolver) Start() error {
 }
 
 func (r *resolver) Stop() {
+	r.startCh <- struct{}{}
+	defer func() { <-r.startCh }()
+
 	if r.server != nil {
 		r.server.Shutdown()
 	}
@@ -355,8 +363,12 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
 			}
 
 			execErr := r.sb.execFunc(extConnect)
-			if execErr != nil || err != nil {
-				log.Debugf("Connect failed, %s", err)
+			if execErr != nil {
+				log.Warn(execErr)
+				continue
+			}
+			if err != nil {
+				log.Warnf("Connect failed: %s", err)
 				continue
 			}
 			log.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,

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

@@ -437,7 +437,13 @@ func (sb *sandbox) ResolveIP(ip string) string {
 }
 
 func (sb *sandbox) execFunc(f func()) error {
-	return sb.osSbox.InvokeFunc(f)
+	sb.Lock()
+	osSbox := sb.osSbox
+	sb.Unlock()
+	if osSbox != nil {
+		return osSbox.InvokeFunc(f)
+	}
+	return fmt.Errorf("osl sandbox unavailable in ExecFunc for %v", sb.ContainerID())
 }
 
 func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP, error) {

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

@@ -250,8 +250,8 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in
 func (n *network) connectedLoadbalancers() []*loadBalancer {
 	c := n.getController()
 
-	serviceBindings := make([]*service, 0, len(c.serviceBindings))
 	c.Lock()
+	serviceBindings := make([]*service, 0, len(c.serviceBindings))
 	for _, s := range c.serviceBindings {
 		serviceBindings = append(serviceBindings, s)
 	}

+ 7 - 5
vendor/src/github.com/vishvananda/netlink/bpf_linux.go

@@ -8,11 +8,11 @@ package netlink
 #include <stdint.h>
 #include <unistd.h>
 
-static int load_simple_bpf(int prog_type) {
+static int load_simple_bpf(int prog_type, int ret) {
 #ifdef __NR_bpf
-	// { return 1; }
+	// { return ret; }
 	__u64 __attribute__((aligned(8))) insns[] = {
-		0x00000001000000b7ull,
+		0x00000000000000b7ull | ((__u64)ret<<32),
 		0x0000000000000095ull,
 	};
 	__u8 __attribute__((aligned(8))) license[] = "ASL2";
@@ -51,10 +51,12 @@ const (
 	BPF_PROG_TYPE_KPROBE
 	BPF_PROG_TYPE_SCHED_CLS
 	BPF_PROG_TYPE_SCHED_ACT
+	BPF_PROG_TYPE_TRACEPOINT
+	BPF_PROG_TYPE_XDP
 )
 
 // loadSimpleBpf loads a trivial bpf program for testing purposes
-func loadSimpleBpf(progType BpfProgType) (int, error) {
-	fd, err := C.load_simple_bpf(C.int(progType))
+func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
+	fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
 	return int(fd), err
 }

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

@@ -60,7 +60,7 @@ func (a TcAct) String() string {
 	case TC_ACT_JUMP:
 		return "jump"
 	}
-	return fmt.Sprintf("0x%x", a)
+	return fmt.Sprintf("0x%x", int32(a))
 }
 
 type TcPolAct int32
@@ -86,7 +86,7 @@ func (a TcPolAct) String() string {
 	case TC_POLICE_PIPE:
 		return "pipe"
 	}
-	return fmt.Sprintf("0x%x", a)
+	return fmt.Sprintf("0x%x", int32(a))
 }
 
 type ActionAttrs struct {

+ 25 - 0
vendor/src/github.com/vishvananda/netlink/handle_linux.go

@@ -1,7 +1,9 @@
 package netlink
 
 import (
+	"fmt"
 	"syscall"
+	"time"
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
@@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) {
 	return newHandle(netns.None(), netns.None(), nlFamilies...)
 }
 
+// SetSocketTimeout sets the send and receive timeout for each socket in the
+// netlink handle. Although the socket timeout has granularity of one
+// microsecond, the effective granularity is floored by the kernel timer tick,
+// which default value is four milliseconds.
+func (h *Handle) SetSocketTimeout(to time.Duration) error {
+	if to < time.Microsecond {
+		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
+	}
+	tv := syscall.NsecToTimeval(to.Nanoseconds())
+	for _, sh := range h.sockets {
+		fd := sh.Socket.GetFd()
+		err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
+		if err != nil {
+			return err
+		}
+		err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 // NewHandle returns a netlink handle on the network namespace
 // specified by ns. If ns=netns.None(), current network namespace
 // will be assumed

+ 13 - 1
vendor/src/github.com/vishvananda/netlink/link.go

@@ -26,11 +26,15 @@ type LinkAttrs struct {
 	Name         string
 	HardwareAddr net.HardwareAddr
 	Flags        net.Flags
+	RawFlags     uint32
 	ParentIndex  int         // index of the parent link device
 	MasterIndex  int         // must be the index of a bridge
 	Namespace    interface{} // nil | NsPid | NsFd
 	Alias        string
 	Statistics   *LinkStatistics
+	Promisc      int
+	Xdp          *LinkXdp
+	EncapType    string
 }
 
 // NewLinkAttrs returns LinkAttrs structure filled with default values
@@ -69,6 +73,11 @@ type LinkStatistics struct {
 	TxCompressed      uint32
 }
 
+type LinkXdp struct {
+	Fd       int
+	Attached bool
+}
+
 // Device links cannot be created via netlink. These links
 // are links created by udev like 'lo' and 'etho0'
 type Device struct {
@@ -171,11 +180,13 @@ func (macvtap Macvtap) Type() string {
 }
 
 type TuntapMode uint16
+type TuntapFlag uint16
 
 // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
 type Tuntap struct {
 	LinkAttrs
-	Mode TuntapMode
+	Mode  TuntapMode
+	Flags TuntapFlag
 }
 
 func (tuntap *Tuntap) Attrs() *LinkAttrs {
@@ -251,6 +262,7 @@ type IPVlanMode uint16
 const (
 	IPVLAN_MODE_L2 IPVlanMode = iota
 	IPVLAN_MODE_L3
+	IPVLAN_MODE_L3S
 	IPVLAN_MODE_MAX
 )
 

+ 138 - 9
vendor/src/github.com/vishvananda/netlink/link_linux.go

@@ -16,8 +16,13 @@ import (
 const SizeofLinkStats = 0x5c
 
 const (
-	TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
-	TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
+	TUNTAP_MODE_TUN  TuntapMode = syscall.IFF_TUN
+	TUNTAP_MODE_TAP  TuntapMode = syscall.IFF_TAP
+	TUNTAP_DEFAULTS  TuntapFlag = syscall.IFF_TUN_EXCL | syscall.IFF_ONE_QUEUE
+	TUNTAP_VNET_HDR  TuntapFlag = syscall.IFF_VNET_HDR
+	TUNTAP_TUN_EXCL  TuntapFlag = syscall.IFF_TUN_EXCL
+	TUNTAP_NO_PI     TuntapFlag = syscall.IFF_NO_PI
+	TUNTAP_ONE_QUEUE TuntapFlag = syscall.IFF_ONE_QUEUE
 )
 
 var native = nl.NativeEndian()
@@ -50,6 +55,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) {
 	}
 }
 
+func (h *Handle) SetPromiscOn(link Link) error {
+	base := link.Attrs()
+	h.ensureIndex(base)
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Change = syscall.IFF_PROMISC
+	msg.Flags = syscall.IFF_UP
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+func SetPromiscOn(link Link) error {
+	return pkgHandle.SetPromiscOn(link)
+}
+
+func (h *Handle) SetPromiscOff(link Link) error {
+	base := link.Attrs()
+	h.ensureIndex(base)
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Change = syscall.IFF_PROMISC
+	msg.Flags = 0 & ^syscall.IFF_UP
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+func SetPromiscOff(link Link) error {
+	return pkgHandle.SetPromiscOff(link)
+}
+
 // LinkSetUp enables the link device.
 // Equivalent to: `ip link set $link up`
 func LinkSetUp(link Link) error {
@@ -255,6 +298,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
 	return err
 }
 
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf rate $rate`
+func LinkSetVfTxRate(link Link, vf, rate int) error {
+	return pkgHandle.LinkSetVfTxRate(link, vf, rate)
+}
+
+// LinkSetVfTxRate sets the tx rate of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf rate $rate`
+func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
+	base := link.Attrs()
+	h.ensureIndex(base)
+	req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
+	info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+	vfmsg := nl.VfTxRate{
+		Vf:   uint32(vf),
+		Rate: uint32(rate),
+	}
+	nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
 // LinkSetMaster sets the master of the link device.
 // Equivalent to: `ip link set $link master $master`
 func LinkSetMaster(link Link, master *Bridge) error {
@@ -373,6 +446,23 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
 	return err
 }
 
+// LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
+// program loaded with bpf(type=BPF_PROG_TYPE_XDP)
+func LinkSetXdpFd(link Link, fd int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	addXdpAttrs(&LinkXdp{Fd: fd}, req)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
 func boolAttr(val bool) []byte {
 	var v uint8
 	if val {
@@ -552,9 +642,7 @@ func (h *Handle) LinkAdd(link Link) error {
 	if tuntap, ok := link.(*Tuntap); ok {
 		// TODO: support user
 		// TODO: support group
-		// TODO: support non- one_queue
-		// TODO: support pi | vnet_hdr | multi_queue
-		// TODO: support non- exclusive
+		// TODO: multi_queue
 		// TODO: support non- persistent
 		if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
 			return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
@@ -565,10 +653,13 @@ func (h *Handle) LinkAdd(link Link) error {
 		}
 		defer file.Close()
 		var req ifReq
-		req.Flags |= syscall.IFF_ONE_QUEUE
-		req.Flags |= syscall.IFF_TUN_EXCL
-		copy(req.Name[:15], base.Name)
+		if tuntap.Flags == 0 {
+			req.Flags = uint16(TUNTAP_DEFAULTS)
+		} else {
+			req.Flags = uint16(tuntap.Flags)
+		}
 		req.Flags |= uint16(tuntap.Mode)
+		copy(req.Name[:15], base.Name)
 		_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
 		if errno != 0 {
 			return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
@@ -649,6 +740,10 @@ func (h *Handle) LinkAdd(link Link) error {
 		req.AddData(attr)
 	}
 
+	if base.Xdp != nil {
+		addXdpAttrs(base.Xdp, req)
+	}
+
 	linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
 	nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
 
@@ -871,7 +966,10 @@ func linkDeserialize(m []byte) (Link, error) {
 		return nil, err
 	}
 
-	base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)}
+	base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()}
+	if msg.Flags&syscall.IFF_PROMISC != 0 {
+		base.Promisc = 1
+	}
 	var link Link
 	linkType := ""
 	for _, attr := range attrs {
@@ -958,6 +1056,12 @@ func linkDeserialize(m []byte) (Link, error) {
 			base.Alias = string(attr.Value[:len(attr.Value)-1])
 		case syscall.IFLA_STATS:
 			base.Statistics = parseLinkStats(attr.Value[:])
+		case nl.IFLA_XDP:
+			xdp, err := parseLinkXdp(attr.Value[:])
+			if err != nil {
+				return nil, err
+			}
+			base.Xdp = xdp
 		}
 	}
 	// Links that don't have IFLA_INFO_KIND are hardware devices
@@ -1389,3 +1493,28 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
 func parseLinkStats(data []byte) *LinkStatistics {
 	return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
 }
+
+func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
+	attrs := nl.NewRtAttr(nl.IFLA_XDP|syscall.NLA_F_NESTED, nil)
+	b := make([]byte, 4)
+	native.PutUint32(b, uint32(xdp.Fd))
+	nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
+	req.AddData(attrs)
+}
+
+func parseLinkXdp(data []byte) (*LinkXdp, error) {
+	attrs, err := nl.ParseRouteAttr(data)
+	if err != nil {
+		return nil, err
+	}
+	xdp := &LinkXdp{}
+	for _, attr := range attrs {
+		switch attr.Attr.Type {
+		case nl.IFLA_XDP_FD:
+			xdp.Fd = int(native.Uint32(attr.Value[0:4]))
+		case nl.IFLA_XDP_ATTACHED:
+			xdp.Attached = attr.Value[0] != 0
+		}
+	}
+	return xdp, nil
+}

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

@@ -151,8 +151,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
 	dstData := nl.NewRtAttr(NDA_DST, ipData)
 	req.AddData(dstData)
 
-	hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
-	req.AddData(hwData)
+	if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
+		hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
+		req.AddData(hwData)
+	}
 
 	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
 	return err
@@ -165,14 +167,33 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
 	return pkgHandle.NeighList(linkIndex, family)
 }
 
+// NeighProxyList gets a list of neighbor proxies in the system.
+// Equivalent to: `ip neighbor show proxy`.
+// The list can be filtered by link and ip family.
+func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
+	return pkgHandle.NeighProxyList(linkIndex, family)
+}
+
 // NeighList gets a list of IP-MAC mappings in the system (ARP table).
 // Equivalent to: `ip neighbor show`.
 // The list can be filtered by link and ip family.
 func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
+	return h.neighList(linkIndex, family, 0)
+}
+
+// NeighProxyList gets a list of neighbor proxies in the system.
+// Equivalent to: `ip neighbor show proxy`.
+// The list can be filtered by link, ip family.
+func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
+	return h.neighList(linkIndex, family, NTF_PROXY)
+}
+
+func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
 	req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
 	msg := Ndmsg{
 		Family: uint8(family),
 		Index:  uint32(linkIndex),
+		Flags:  uint8(flags),
 	}
 	req.AddData(&msg)
 

+ 30 - 6
vendor/src/github.com/vishvananda/netlink/nl/link_linux.go

@@ -1,13 +1,35 @@
 package nl
 
 import (
+	"syscall"
 	"unsafe"
 )
 
 const (
 	DEFAULT_CHANGE = 0xFFFFFFFF
 	// doesn't exist in syscall
-	IFLA_VFINFO_LIST = 0x16
+	IFLA_VFINFO_LIST = syscall.IFLA_IFALIAS + 1 + iota
+	IFLA_STATS64
+	IFLA_VF_PORTS
+	IFLA_PORT_SELF
+	IFLA_AF_SPEC
+	IFLA_GROUP
+	IFLA_NET_NS_FD
+	IFLA_EXT_MASK
+	IFLA_PROMISCUITY
+	IFLA_NUM_TX_QUEUES
+	IFLA_NUM_RX_QUEUES
+	IFLA_CARRIER
+	IFLA_PHYS_PORT_ID
+	IFLA_CARRIER_CHANGES
+	IFLA_PHYS_SWITCH_ID
+	IFLA_LINK_NETNSID
+	IFLA_PHYS_PORT_NAME
+	IFLA_PROTO_DOWN
+	IFLA_GSO_MAX_SEGS
+	IFLA_GSO_MAX_SIZE
+	IFLA_PAD
+	IFLA_XDP
 )
 
 const (
@@ -89,11 +111,6 @@ const (
 	IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
 )
 
-const (
-	// not defined in syscall
-	IFLA_NET_NS_FD = 28
-)
-
 const (
 	IFLA_MACVLAN_UNSPEC = iota
 	IFLA_MACVLAN_MODE
@@ -394,3 +411,10 @@ func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
 func (msg *VfRssQueryEn) Serialize() []byte {
 	return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
 }
+
+const (
+	IFLA_XDP_UNSPEC   = iota
+	IFLA_XDP_FD       /* fd of xdp program to attach, or -1 to remove */
+	IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
+	IFLA_XDP_MAX      = IFLA_XDP_ATTACHED
+)

+ 141 - 0
vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -100,6 +100,147 @@ func (msg *IfInfomsg) Len() int {
 	return syscall.SizeofIfInfomsg
 }
 
+func (msg *IfInfomsg) EncapType() string {
+	switch msg.Type {
+	case 0:
+		return "generic"
+	case syscall.ARPHRD_ETHER:
+		return "ether"
+	case syscall.ARPHRD_EETHER:
+		return "eether"
+	case syscall.ARPHRD_AX25:
+		return "ax25"
+	case syscall.ARPHRD_PRONET:
+		return "pronet"
+	case syscall.ARPHRD_CHAOS:
+		return "chaos"
+	case syscall.ARPHRD_IEEE802:
+		return "ieee802"
+	case syscall.ARPHRD_ARCNET:
+		return "arcnet"
+	case syscall.ARPHRD_APPLETLK:
+		return "atalk"
+	case syscall.ARPHRD_DLCI:
+		return "dlci"
+	case syscall.ARPHRD_ATM:
+		return "atm"
+	case syscall.ARPHRD_METRICOM:
+		return "metricom"
+	case syscall.ARPHRD_IEEE1394:
+		return "ieee1394"
+	case syscall.ARPHRD_INFINIBAND:
+		return "infiniband"
+	case syscall.ARPHRD_SLIP:
+		return "slip"
+	case syscall.ARPHRD_CSLIP:
+		return "cslip"
+	case syscall.ARPHRD_SLIP6:
+		return "slip6"
+	case syscall.ARPHRD_CSLIP6:
+		return "cslip6"
+	case syscall.ARPHRD_RSRVD:
+		return "rsrvd"
+	case syscall.ARPHRD_ADAPT:
+		return "adapt"
+	case syscall.ARPHRD_ROSE:
+		return "rose"
+	case syscall.ARPHRD_X25:
+		return "x25"
+	case syscall.ARPHRD_HWX25:
+		return "hwx25"
+	case syscall.ARPHRD_PPP:
+		return "ppp"
+	case syscall.ARPHRD_HDLC:
+		return "hdlc"
+	case syscall.ARPHRD_LAPB:
+		return "lapb"
+	case syscall.ARPHRD_DDCMP:
+		return "ddcmp"
+	case syscall.ARPHRD_RAWHDLC:
+		return "rawhdlc"
+	case syscall.ARPHRD_TUNNEL:
+		return "ipip"
+	case syscall.ARPHRD_TUNNEL6:
+		return "tunnel6"
+	case syscall.ARPHRD_FRAD:
+		return "frad"
+	case syscall.ARPHRD_SKIP:
+		return "skip"
+	case syscall.ARPHRD_LOOPBACK:
+		return "loopback"
+	case syscall.ARPHRD_LOCALTLK:
+		return "ltalk"
+	case syscall.ARPHRD_FDDI:
+		return "fddi"
+	case syscall.ARPHRD_BIF:
+		return "bif"
+	case syscall.ARPHRD_SIT:
+		return "sit"
+	case syscall.ARPHRD_IPDDP:
+		return "ip/ddp"
+	case syscall.ARPHRD_IPGRE:
+		return "gre"
+	case syscall.ARPHRD_PIMREG:
+		return "pimreg"
+	case syscall.ARPHRD_HIPPI:
+		return "hippi"
+	case syscall.ARPHRD_ASH:
+		return "ash"
+	case syscall.ARPHRD_ECONET:
+		return "econet"
+	case syscall.ARPHRD_IRDA:
+		return "irda"
+	case syscall.ARPHRD_FCPP:
+		return "fcpp"
+	case syscall.ARPHRD_FCAL:
+		return "fcal"
+	case syscall.ARPHRD_FCPL:
+		return "fcpl"
+	case syscall.ARPHRD_FCFABRIC:
+		return "fcfb0"
+	case syscall.ARPHRD_FCFABRIC + 1:
+		return "fcfb1"
+	case syscall.ARPHRD_FCFABRIC + 2:
+		return "fcfb2"
+	case syscall.ARPHRD_FCFABRIC + 3:
+		return "fcfb3"
+	case syscall.ARPHRD_FCFABRIC + 4:
+		return "fcfb4"
+	case syscall.ARPHRD_FCFABRIC + 5:
+		return "fcfb5"
+	case syscall.ARPHRD_FCFABRIC + 6:
+		return "fcfb6"
+	case syscall.ARPHRD_FCFABRIC + 7:
+		return "fcfb7"
+	case syscall.ARPHRD_FCFABRIC + 8:
+		return "fcfb8"
+	case syscall.ARPHRD_FCFABRIC + 9:
+		return "fcfb9"
+	case syscall.ARPHRD_FCFABRIC + 10:
+		return "fcfb10"
+	case syscall.ARPHRD_FCFABRIC + 11:
+		return "fcfb11"
+	case syscall.ARPHRD_FCFABRIC + 12:
+		return "fcfb12"
+	case syscall.ARPHRD_IEEE802_TR:
+		return "tr"
+	case syscall.ARPHRD_IEEE80211:
+		return "ieee802.11"
+	case syscall.ARPHRD_IEEE80211_PRISM:
+		return "ieee802.11/prism"
+	case syscall.ARPHRD_IEEE80211_RADIOTAP:
+		return "ieee802.11/radiotap"
+	case syscall.ARPHRD_IEEE802154:
+		return "ieee802.15.4"
+
+	case 65534:
+		return "none"
+	case 65535:
+		return "void"
+	}
+	return fmt.Sprintf("unknown%d", msg.Type)
+}
+
 func rtaAlignOf(attrlen int) int {
 	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
 }

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

@@ -153,7 +153,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 				} else {
 					gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16()))
 				}
-				gwData := gw.Serialize()
+				gwData = gw.Serialize()
 				rtnh.Len += uint16(len(gwData))
 			}
 			buf = append(buf, rtnh.Serialize()...)

+ 10 - 4
vendor/src/github.com/vishvananda/netlink/rule_linux.go

@@ -82,41 +82,46 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 		req.AddData(rtAttrs[i])
 	}
 
-	var (
-		b      = make([]byte, 4)
-		native = nl.NativeEndian()
-	)
+	native := nl.NativeEndian()
 
 	if rule.Priority >= 0 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Priority))
 		req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
 	}
 	if rule.Mark >= 0 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Mark))
 		req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
 	}
 	if rule.Mask >= 0 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Mask))
 		req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
 	}
 	if rule.Flow >= 0 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Flow))
 		req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
 	}
 	if rule.TunID > 0 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.TunID))
 		req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
 	}
 	if rule.Table >= 256 {
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Table))
 		req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
 	}
 	if msg.Table > 0 {
 		if rule.SuppressPrefixlen >= 0 {
+			b := make([]byte, 4)
 			native.PutUint32(b, uint32(rule.SuppressPrefixlen))
 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
 		}
 		if rule.SuppressIfgroup >= 0 {
+			b := make([]byte, 4)
 			native.PutUint32(b, uint32(rule.SuppressIfgroup))
 			req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
 		}
@@ -129,6 +134,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 	}
 	if rule.Goto >= 0 {
 		msg.Type = nl.FR_ACT_NOP
+		b := make([]byte, 4)
 		native.PutUint32(b, uint32(rule.Goto))
 		req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
 	}

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

@@ -213,7 +213,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
 		req.AddData(out)
 	}
 	if state.Src != nil {
-		out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src)
+		out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16())
 		req.AddData(out)
 	}