Просмотр исходного кода

Merge pull request #39054 from thaJeztah/bump_libnetwork2

bump libnetwork. vishvananda/netlink 1.0, vishvananda/netns
Tibor Vass 6 лет назад
Родитель
Сommit
9e6f83bee1
58 измененных файлов с 2004 добавлено и 766 удалено
  1. 1 1
      hack/dockerfile/install/proxy.installer
  2. 3 3
      vendor.conf
  3. 12 12
      vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go
  4. 32 2
      vendor/github.com/docker/libnetwork/firewall_linux.go
  5. 5 6
      vendor/github.com/docker/libnetwork/ipvs/ipvs.go
  6. 7 2
      vendor/github.com/docker/libnetwork/network.go
  7. 1 1
      vendor/github.com/docker/libnetwork/resolver.go
  8. 51 47
      vendor/github.com/docker/libnetwork/vendor.conf
  9. 1 0
      vendor/github.com/vishvananda/netlink/README.md
  10. 66 28
      vendor/github.com/vishvananda/netlink/addr_linux.go
  11. 37 46
      vendor/github.com/vishvananda/netlink/bpf_linux.go
  12. 12 12
      vendor/github.com/vishvananda/netlink/bridge_linux.go
  13. 13 12
      vendor/github.com/vishvananda/netlink/class_linux.go
  14. 7 7
      vendor/github.com/vishvananda/netlink/conntrack_linux.go
  15. 16 1
      vendor/github.com/vishvananda/netlink/filter.go
  16. 47 9
      vendor/github.com/vishvananda/netlink/filter_linux.go
  17. 21 0
      vendor/github.com/vishvananda/netlink/fou.go
  18. 215 0
      vendor/github.com/vishvananda/netlink/fou_linux.go
  19. 15 0
      vendor/github.com/vishvananda/netlink/fou_unspecified.go
  20. 4 3
      vendor/github.com/vishvananda/netlink/genetlink_linux.go
  21. 8 7
      vendor/github.com/vishvananda/netlink/gtp_linux.go
  22. 9 9
      vendor/github.com/vishvananda/netlink/handle_linux.go
  23. 36 0
      vendor/github.com/vishvananda/netlink/handle_unspecified.go
  24. 98 0
      vendor/github.com/vishvananda/netlink/ioctl_linux.go
  25. 85 38
      vendor/github.com/vishvananda/netlink/link.go
  26. 309 165
      vendor/github.com/vishvananda/netlink/link_linux.go
  27. 2 0
      vendor/github.com/vishvananda/netlink/neigh.go
  28. 24 10
      vendor/github.com/vishvananda/netlink/neigh_linux.go
  29. 7 6
      vendor/github.com/vishvananda/netlink/nl/addr_linux.go
  30. 17 25
      vendor/github.com/vishvananda/netlink/nl/link_linux.go
  31. 121 115
      vendor/github.com/vishvananda/netlink/nl/nl_linux.go
  32. 20 19
      vendor/github.com/vishvananda/netlink/nl/route_linux.go
  33. 111 0
      vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
  34. 10 0
      vendor/github.com/vishvananda/netlink/nl/syscall.go
  35. 35 0
      vendor/github.com/vishvananda/netlink/nl/tc_linux.go
  36. 5 4
      vendor/github.com/vishvananda/netlink/protinfo_linux.go
  37. 60 0
      vendor/github.com/vishvananda/netlink/qdisc.go
  38. 129 11
      vendor/github.com/vishvananda/netlink/qdisc_linux.go
  39. 2 0
      vendor/github.com/vishvananda/netlink/route.go
  40. 190 55
      vendor/github.com/vishvananda/netlink/route_linux.go
  41. 1 0
      vendor/github.com/vishvananda/netlink/rule.go
  42. 30 20
      vendor/github.com/vishvananda/netlink/rule_linux.go
  43. 4 4
      vendor/github.com/vishvananda/netlink/socket_linux.go
  44. 7 6
      vendor/github.com/vishvananda/netlink/xfrm.go
  45. 3 4
      vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
  46. 9 10
      vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
  47. 24 3
      vendor/github.com/vishvananda/netlink/xfrm_state.go
  48. 26 13
      vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
  49. 4 2
      vendor/github.com/vishvananda/netns/README.md
  50. 15 2
      vendor/github.com/vishvananda/netns/netns.go
  51. 29 4
      vendor/github.com/vishvananda/netns/netns_linux.go
  52. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_386.go
  53. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_amd64.go
  54. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_arm.go
  55. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_arm64.go
  56. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_ppc64le.go
  57. 0 7
      vendor/github.com/vishvananda/netns/netns_linux_s390x.go
  58. 8 0
      vendor/github.com/vishvananda/netns/netns_unspecified.go

+ 1 - 1
hack/dockerfile/install/proxy.installer

@@ -3,7 +3,7 @@
 # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When
 # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When
 # updating the binary version, consider updating github.com/docker/libnetwork
 # updating the binary version, consider updating github.com/docker/libnetwork
 # in vendor.conf accordingly
 # in vendor.conf accordingly
-LIBNETWORK_COMMIT=fc5a7d91d54cc98f64fc28f9e288b46a0bee756c
+LIBNETWORK_COMMIT=62a13ae87c6058bdc000fcccbf7e0f9f7525e2a9
 
 
 install_proxy() {
 install_proxy() {
 	case "$1" in
 	case "$1" in

+ 3 - 3
vendor.conf

@@ -39,7 +39,7 @@ github.com/gofrs/flock                              7f43ea2e6a643ad441fc12d0ecc0
 # libnetwork
 # libnetwork
 
 
 # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
 # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
-github.com/docker/libnetwork                        fc5a7d91d54cc98f64fc28f9e288b46a0bee756c
+github.com/docker/libnetwork                        62a13ae87c6058bdc000fcccbf7e0f9f7525e2a9
 github.com/docker/go-events                         9461782956ad83b30282bf90e31fa6a70c255ba9
 github.com/docker/go-events                         9461782956ad83b30282bf90e31fa6a70c255ba9
 github.com/armon/go-radix                           e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 github.com/armon/go-radix                           e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 github.com/armon/go-metrics                         eb0af217e5e9747e41dd5303755356b62d28e3ec
 github.com/armon/go-metrics                         eb0af217e5e9747e41dd5303755356b62d28e3ec
@@ -50,8 +50,8 @@ github.com/hashicorp/go-sockaddr                    6d291a969b86c4b633730bfc6b8b
 github.com/hashicorp/go-multierror                  fcdddc395df1ddf4247c69bd436e84cfa0733f7e
 github.com/hashicorp/go-multierror                  fcdddc395df1ddf4247c69bd436e84cfa0733f7e
 github.com/hashicorp/serf                           598c54895cc5a7b1a24a398d635e8c0ea0959870
 github.com/hashicorp/serf                           598c54895cc5a7b1a24a398d635e8c0ea0959870
 github.com/docker/libkv                             458977154600b9f23984d9f4b82e79570b5ae12b
 github.com/docker/libkv                             458977154600b9f23984d9f4b82e79570b5ae12b
-github.com/vishvananda/netns                        604eaf189ee867d8c147fafc28def2394e878d25
-github.com/vishvananda/netlink                      b2de5d10e38ecce8607e6b438b6d174f389a004e
+github.com/vishvananda/netns                        13995c7128ccc8e51e9a6bd2b551020a27180abd
+github.com/vishvananda/netlink                      a2ad57a690f3caf3015351d2d6e1c0b95c349752 # v1.0.0
 
 
 # When updating, consider updating TOMLV_COMMIT in hack/dockerfile/install/tomlv.installer accordingly
 # When updating, consider updating TOMLV_COMMIT in hack/dockerfile/install/tomlv.installer accordingly
 github.com/BurntSushi/toml                          3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
 github.com/BurntSushi/toml                          3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1

+ 12 - 12
vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go

@@ -12,7 +12,6 @@ import (
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
-	"syscall"
 
 
 	"github.com/docker/docker/pkg/reexec"
 	"github.com/docker/docker/pkg/reexec"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/datastore"
@@ -27,6 +26,7 @@ import (
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 var (
 var (
@@ -97,18 +97,18 @@ func setDefaultVlan() {
 	}
 	}
 
 
 	// make sure the sysfs mount doesn't propagate back
 	// make sure the sysfs mount doesn't propagate back
-	if err = syscall.Unshare(syscall.CLONE_NEWNS); err != nil {
+	if err = unix.Unshare(unix.CLONE_NEWNS); err != nil {
 		logrus.Errorf("unshare failed, %v", err)
 		logrus.Errorf("unshare failed, %v", err)
 		os.Exit(1)
 		os.Exit(1)
 	}
 	}
 
 
-	flag := syscall.MS_PRIVATE | syscall.MS_REC
-	if err = syscall.Mount("", "/", "", uintptr(flag), ""); err != nil {
+	flag := unix.MS_PRIVATE | unix.MS_REC
+	if err = unix.Mount("", "/", "", uintptr(flag), ""); err != nil {
 		logrus.Errorf("root mount failed, %v", err)
 		logrus.Errorf("root mount failed, %v", err)
 		os.Exit(1)
 		os.Exit(1)
 	}
 	}
 
 
-	if err = syscall.Mount("sysfs", "/sys", "sysfs", 0, ""); err != nil {
+	if err = unix.Mount("sysfs", "/sys", "sysfs", 0, ""); err != nil {
 		logrus.Errorf("mounting sysfs failed, %v", err)
 		logrus.Errorf("mounting sysfs failed, %v", err)
 		os.Exit(1)
 		os.Exit(1)
 	}
 	}
@@ -427,7 +427,7 @@ func populateVNITbl() {
 			}
 			}
 			defer ns.Close()
 			defer ns.Close()
 
 
-			nlh, err := netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE)
+			nlh, err := netlink.NewHandleAt(ns, unix.NETLINK_ROUTE)
 			if err != nil {
 			if err != nil {
 				logrus.Errorf("Could not open netlink handle during vni population for ns %s: %v", path, err)
 				logrus.Errorf("Could not open netlink handle during vni population for ns %s: %v", path, err)
 				return nil
 				return nil
@@ -583,7 +583,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error
 
 
 		if ok {
 		if ok {
 			deleteVxlanByVNI(path, s.vni)
 			deleteVxlanByVNI(path, s.vni)
-			if err := syscall.Unmount(path, syscall.MNT_FORCE); err != nil {
+			if err := unix.Unmount(path, unix.MNT_FORCE); err != nil {
 				logrus.Errorf("unmount of %s failed: %v", path, err)
 				logrus.Errorf("unmount of %s failed: %v", path, err)
 			}
 			}
 			os.Remove(path)
 			os.Remove(path)
@@ -693,7 +693,7 @@ func (n *network) cleanupStaleSandboxes() {
 			if strings.Contains(n.id, pattern) {
 			if strings.Contains(n.id, pattern) {
 				// Delete all vnis
 				// Delete all vnis
 				deleteVxlanByVNI(path, 0)
 				deleteVxlanByVNI(path, 0)
-				syscall.Unmount(path, syscall.MNT_DETACH)
+				unix.Unmount(path, unix.MNT_DETACH)
 				os.Remove(path)
 				os.Remove(path)
 
 
 				// Now that we have destroyed this
 				// Now that we have destroyed this
@@ -755,12 +755,12 @@ func (n *network) initSandbox(restore bool) error {
 
 
 	var nlSock *nl.NetlinkSocket
 	var nlSock *nl.NetlinkSocket
 	sbox.InvokeFunc(func() {
 	sbox.InvokeFunc(func() {
-		nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
+		nlSock, err = nl.Subscribe(unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH)
 		if err != nil {
 		if err != nil {
 			return
 			return
 		}
 		}
 		// set the receive timeout to not remain stuck on the RecvFrom if the fd gets closed
 		// set the receive timeout to not remain stuck on the RecvFrom if the fd gets closed
-		tv := syscall.NsecToTimeval(soTimeout.Nanoseconds())
+		tv := unix.NsecToTimeval(soTimeout.Nanoseconds())
 		err = nlSock.SetReceiveTimeout(&tv)
 		err = nlSock.SetReceiveTimeout(&tv)
 	})
 	})
 	n.nlSocket = nlSock
 	n.nlSocket = nlSock
@@ -803,7 +803,7 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket, nsPath string) {
 				return
 				return
 			}
 			}
 			// When the receive timeout expires the receive will return EAGAIN
 			// When the receive timeout expires the receive will return EAGAIN
-			if err == syscall.EAGAIN {
+			if err == unix.EAGAIN {
 				// we continue here to avoid spam for timeouts
 				// we continue here to avoid spam for timeouts
 				continue
 				continue
 			}
 			}
@@ -812,7 +812,7 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket, nsPath string) {
 		}
 		}
 
 
 		for _, msg := range msgs {
 		for _, msg := range msgs {
-			if msg.Header.Type != syscall.RTM_GETNEIGH && msg.Header.Type != syscall.RTM_NEWNEIGH {
+			if msg.Header.Type != unix.RTM_GETNEIGH && msg.Header.Type != unix.RTM_NEWNEIGH {
 				continue
 				continue
 			}
 			}
 
 

+ 32 - 2
vendor/github.com/docker/libnetwork/firewall_linux.go

@@ -2,6 +2,7 @@ package libnetwork
 
 
 import (
 import (
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/iptables"
+	"github.com/docker/libnetwork/netlabel"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
 
 
@@ -9,15 +10,44 @@ const userChain = "DOCKER-USER"
 
 
 func (c *controller) arrangeUserFilterRule() {
 func (c *controller) arrangeUserFilterRule() {
 	c.Lock()
 	c.Lock()
-	arrangeUserFilterRule()
+
+	if c.hasIPTablesEnabled() {
+		arrangeUserFilterRule()
+	}
+
 	c.Unlock()
 	c.Unlock()
+
 	iptables.OnReloaded(func() {
 	iptables.OnReloaded(func() {
 		c.Lock()
 		c.Lock()
-		arrangeUserFilterRule()
+
+		if c.hasIPTablesEnabled() {
+			arrangeUserFilterRule()
+		}
+
 		c.Unlock()
 		c.Unlock()
 	})
 	})
 }
 }
 
 
+func (c *controller) hasIPTablesEnabled() bool {
+	// Locking c should be handled in the calling method.
+	if c.cfg == nil || c.cfg.Daemon.DriverCfg[netlabel.GenericData] == nil {
+		return false
+	}
+
+	genericData, ok := c.cfg.Daemon.DriverCfg[netlabel.GenericData]
+	if !ok {
+		return false
+	}
+
+	optMap := genericData.(map[string]interface{})
+	enabled, ok := optMap["EnableIPTables"].(bool)
+	if !ok {
+		return false
+	}
+
+	return enabled
+}
+
 // This chain allow users to configure firewall policies in a way that persists
 // This chain allow users to configure firewall policies in a way that persists
 // docker operations/restarts. Docker will not delete or modify any pre-existing
 // docker operations/restarts. Docker will not delete or modify any pre-existing
 // rules from the DOCKER-USER filter chain.
 // rules from the DOCKER-USER filter chain.

+ 5 - 6
vendor/github.com/docker/libnetwork/ipvs/ipvs.go

@@ -3,14 +3,13 @@
 package ipvs
 package ipvs
 
 
 import (
 import (
+	"fmt"
 	"net"
 	"net"
-	"syscall"
 	"time"
 	"time"
 
 
-	"fmt"
-
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 const (
 const (
@@ -98,16 +97,16 @@ func New(path string) (*Handle, error) {
 	}
 	}
 	defer n.Close()
 	defer n.Close()
 
 
-	sock, err := nl.GetNetlinkSocketAt(n, netns.None(), syscall.NETLINK_GENERIC)
+	sock, err := nl.GetNetlinkSocketAt(n, netns.None(), unix.NETLINK_GENERIC)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	// Add operation timeout to avoid deadlocks
 	// Add operation timeout to avoid deadlocks
-	tv := syscall.NsecToTimeval(netlinkSendSocketTimeout.Nanoseconds())
+	tv := unix.NsecToTimeval(netlinkSendSocketTimeout.Nanoseconds())
 	if err := sock.SetSendTimeout(&tv); err != nil {
 	if err := sock.SetSendTimeout(&tv); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	tv = syscall.NsecToTimeval(netlinkRecvSocketsTimeout.Nanoseconds())
+	tv = unix.NsecToTimeval(netlinkRecvSocketsTimeout.Nanoseconds())
 	if err := sock.SetReceiveTimeout(&tv); err != nil {
 	if err := sock.SetReceiveTimeout(&tv); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 7 - 2
vendor/github.com/docker/libnetwork/network.go

@@ -1381,14 +1381,18 @@ func delIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) {
 }
 }
 
 
 func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
 func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
-	svcMap.Insert(name, svcMapEntry{
+	// Since DNS name resolution is case-insensitive, Use the lower-case form
+	// of the name as the key into svcMap
+	lowerCaseName := strings.ToLower(name)
+	svcMap.Insert(lowerCaseName, svcMapEntry{
 		ip:        epIP.String(),
 		ip:        epIP.String(),
 		serviceID: serviceID,
 		serviceID: serviceID,
 	})
 	})
 }
 }
 
 
 func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
 func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
-	svcMap.Remove(name, svcMapEntry{
+	lowerCaseName := strings.ToLower(name)
+	svcMap.Remove(lowerCaseName, svcMapEntry{
 		ip:        epIP.String(),
 		ip:        epIP.String(),
 		serviceID: serviceID,
 		serviceID: serviceID,
 	})
 	})
@@ -1956,6 +1960,7 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
 	}
 	}
 
 
 	req = strings.TrimSuffix(req, ".")
 	req = strings.TrimSuffix(req, ".")
+	req = strings.ToLower(req)
 	ipSet, ok := sr.svcMap.Get(req)
 	ipSet, ok := sr.svcMap.Get(req)
 
 
 	if ipType == types.IPv6 {
 	if ipType == types.IPv6 {

+ 1 - 1
vendor/github.com/docker/libnetwork/resolver.go

@@ -366,8 +366,8 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
 	if query == nil || len(query.Question) == 0 {
 	if query == nil || len(query.Question) == 0 {
 		return
 		return
 	}
 	}
-	name := query.Question[0].Name
 
 
+	name := query.Question[0].Name
 	switch query.Question[0].Qtype {
 	switch query.Question[0].Qtype {
 	case dns.TypeA:
 	case dns.TypeA:
 		resp, err = r.handleIPQuery(name, query, types.IPv4)
 		resp, err = r.handleIPQuery(name, query, types.IPv4)

+ 51 - 47
vendor/github.com/docker/libnetwork/vendor.conf

@@ -1,50 +1,54 @@
-github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
-github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
-github.com/Microsoft/go-winio v0.4.11
-github.com/Microsoft/hcsshim v0.7.3
-github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
-github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
-github.com/codegangsta/cli a65b733b303f0055f8d324d805f393cd3e7a7904
-github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
-github.com/coreos/etcd v3.2.1
-github.com/coreos/go-semver v0.2.0
-github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
-go.etcd.io/bbolt v1.3.1-etcd.8
+github.com/Azure/go-ansiterm            d6e3b3328b783f23731bc4d058875b0371ff8109
+github.com/BurntSushi/toml              3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
+github.com/Microsoft/go-winio           c599b533b43b1363d7d7c6cfda5ede70ed73ff13
+github.com/Microsoft/hcsshim            ba3d6667710fa905116f39a19d059c4c1016be7c
+github.com/armon/go-metrics             eb0af217e5e9747e41dd5303755356b62d28e3ec
+github.com/armon/go-radix               e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
+github.com/codegangsta/cli              a65b733b303f0055f8d324d805f393cd3e7a7904
+github.com/containerd/continuity        004b46473808b3e7a4a3049c20e4376c91eb966d
+github.com/coreos/etcd                  fca8add78a9d926166eb739b8e4a124434025ba3 # v3.3.9
+github.com/coreos/go-semver             8ab6407b697782a06568d4b7f1db25550ec2e4c6 # v0.2.0
+github.com/deckarep/golang-set          ef32fa3046d9f249d399f98ebaf9be944430fd1d
+go.etcd.io/bbolt                        7ee3ded59d4835e10f3e7d0f7603c42aa5e83820 # v1.3.1-etcd.8
 
 
-github.com/docker/docker 162ba6016def672690ee4a1f3978368853a1e149
-github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6
-github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
-github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
-github.com/docker/libkv 458977154600b9f23984d9f4b82e79570b5ae12b
+github.com/docker/docker                dbe4a30928d418e0570891a09703bcbc0e4997a1
+github.com/docker/distribution          0d3efadf0154c2b8a4e7b6621fff9809655cc580
+github.com/docker/go-connections        7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
+github.com/docker/go-events             9461782956ad83b30282bf90e31fa6a70c255ba9
+github.com/docker/go-units              47565b4f722fb6ceae66b95f853feed578a4a51c # v0.3.3
+github.com/docker/libkv                 458977154600b9f23984d9f4b82e79570b5ae12b
 
 
-github.com/godbus/dbus v4.0.0
-github.com/gogo/protobuf v1.0.0
-github.com/gorilla/context v1.1
-github.com/gorilla/mux v1.1
-github.com/hashicorp/consul v0.5.2
-github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
-github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
-github.com/hashicorp/memberlist 3d8438da9589e7b608a83ffac1ef8211486bcb7c
-github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372
-github.com/hashicorp/go-sockaddr 6d291a969b86c4b633730bfc6b8b9d64c3aafed9
-github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
-github.com/mattn/go-shellwords v1.0.3
-github.com/miekg/dns v1.0.7
-github.com/opencontainers/go-digest v1.0.0-rc1
-github.com/opencontainers/image-spec v1.0.1
-github.com/opencontainers/runc 96ec2177ae841256168fcf76954f7177af9446eb
-github.com/opencontainers/runtime-spec v1.0.1
-github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
-github.com/sirupsen/logrus v1.0.3
-github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
-github.com/vishvananda/netlink b2de5d10e38ecce8607e6b438b6d174f389a004e
-github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
-golang.org/x/crypto 1a580b3eff7814fc9b40602fd35256c63b50f491
-golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd
-golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd
-golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5
-github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
-github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
+github.com/gogo/protobuf                ba06b47c162d49f2af050fb4c75bcbc86a159d5c # v1.2.1
+github.com/golang/protobuf              aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0
+google.golang.org/grpc                  7a6a684ca69eb4cae85ad0a484f2e531598c047b # v1.12.2
+google.golang.org/genproto              694d95ba50e67b2e363f3483057db5d4910c18f9
 
 
-gotest.tools v2.1.0
-github.com/google/go-cmp v0.2.0
+github.com/godbus/dbus                  5f6efc7ef2759c81b7ba876593971bfce311eab3 # v4.0.0
+github.com/gorilla/mux                  c5c6c98bc25355028a63748a498942a6398ccd22 # v1.7.1
+github.com/hashicorp/consul             9a9cc9341bb487651a0399e3fc5e1e8a42e62dd9 # v0.5.2
+github.com/hashicorp/go-msgpack         71c2886f5a673a35f909803f38ece5810165097b
+github.com/hashicorp/go-multierror      fcdddc395df1ddf4247c69bd436e84cfa0733f7e
+github.com/hashicorp/memberlist         3d8438da9589e7b608a83ffac1ef8211486bcb7c
+github.com/sean-/seed                   e2103e2c35297fb7e17febb81e49b312087a2372
+github.com/hashicorp/go-sockaddr        6d291a969b86c4b633730bfc6b8b9d64c3aafed9
+github.com/hashicorp/serf               598c54895cc5a7b1a24a398d635e8c0ea0959870
+github.com/mattn/go-shellwords          02e3cf038dcea8290e44424da473dd12be796a8a # v1.0.3
+github.com/miekg/dns                    e57bf427e68187a27e22adceac868350d7a7079b # v1.0.7
+github.com/opencontainers/go-digest     279bed98673dd5bef374d3b6e4b09e2af76183bf # v1.0.0-rc1
+github.com/opencontainers/image-spec    d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
+github.com/opencontainers/runc          2b18fe1d885ee5083ef9f0838fee39b62d653e30
+github.com/opencontainers/runtime-spec  29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
+github.com/samuel/go-zookeeper          d0e0d8e11f318e000a8cc434616d69e329edc374
+github.com/sirupsen/logrus              f006c2ac4710855cf0f916dd6b77acf6b048dc6e # v1.0.3
+github.com/ugorji/go                    b4c50a2b199d93b13dc15e78929cfb23bfdf21ab # v1.1.1
+github.com/vishvananda/netlink          a2ad57a690f3caf3015351d2d6e1c0b95c349752 # v1.0.0
+github.com/vishvananda/netns            13995c7128ccc8e51e9a6bd2b551020a27180abd
+golang.org/x/crypto                     b7391e95e576cacdcdd422573063bc057239113d
+golang.org/x/net                        a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1
+golang.org/x/sys                        d455e41777fca6e8a5a79e34a14b8368bc11d9ba
+golang.org/x/sync                       1d60e4601c6fd243af51cc01ddf169918a5407ca
+github.com/pkg/errors                   ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
+github.com/ishidawataru/sctp            07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
+
+gotest.tools                            b6e20af1ed078cd01a6413b734051a292450b4cb # v2.1.0
+github.com/google/go-cmp                3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0

+ 1 - 0
vendor/github.com/vishvananda/netlink/README.md

@@ -89,3 +89,4 @@ There are also a few pieces of low level netlink functionality that still
 need to be implemented. Routing rules are not in place and some of the
 need to be implemented. Routing rules are not in place and some of the
 more advanced link types. Hopefully there is decent structure and testing
 more advanced link types. Hopefully there is decent structure and testing
 in place to make these fairly straightforward to add.
 in place to make these fairly straightforward to add.
+

+ 66 - 28
vendor/github.com/vishvananda/netlink/addr_linux.go

@@ -8,6 +8,7 @@ import (
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // IFA_FLAGS is a u32 attribute.
 // IFA_FLAGS is a u32 attribute.
@@ -22,7 +23,7 @@ func AddrAdd(link Link, addr *Addr) error {
 // AddrAdd will add an IP address to a link device.
 // AddrAdd will add an IP address to a link device.
 // Equivalent to: `ip addr add $addr dev $link`
 // Equivalent to: `ip addr add $addr dev $link`
 func (h *Handle) AddrAdd(link Link, addr *Addr) error {
 func (h *Handle) AddrAdd(link Link, addr *Addr) error {
-	req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 	return h.addrHandle(link, addr, req)
 	return h.addrHandle(link, addr, req)
 }
 }
 
 
@@ -35,7 +36,7 @@ func AddrReplace(link Link, addr *Addr) error {
 // AddrReplace will replace (or, if not present, add) an IP address on a link device.
 // AddrReplace will replace (or, if not present, add) an IP address on a link device.
 // Equivalent to: `ip addr replace $addr dev $link`
 // Equivalent to: `ip addr replace $addr dev $link`
 func (h *Handle) AddrReplace(link Link, addr *Addr) error {
 func (h *Handle) AddrReplace(link Link, addr *Addr) error {
-	req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
 	return h.addrHandle(link, addr, req)
 	return h.addrHandle(link, addr, req)
 }
 }
 
 
@@ -48,7 +49,7 @@ func AddrDel(link Link, addr *Addr) error {
 // AddrDel will delete an IP address from a link device.
 // AddrDel will delete an IP address from a link device.
 // Equivalent to: `ip addr del $addr dev $link`
 // Equivalent to: `ip addr del $addr dev $link`
 func (h *Handle) AddrDel(link Link, addr *Addr) error {
 func (h *Handle) AddrDel(link Link, addr *Addr) error {
-	req := h.newNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
 	return h.addrHandle(link, addr, req)
 	return h.addrHandle(link, addr, req)
 }
 }
 
 
@@ -75,7 +76,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
 		localAddrData = addr.IP.To16()
 		localAddrData = addr.IP.To16()
 	}
 	}
 
 
-	localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
+	localData := nl.NewRtAttr(unix.IFA_LOCAL, localAddrData)
 	req.AddData(localData)
 	req.AddData(localData)
 	var peerAddrData []byte
 	var peerAddrData []byte
 	if addr.Peer != nil {
 	if addr.Peer != nil {
@@ -88,7 +89,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
 		peerAddrData = localAddrData
 		peerAddrData = localAddrData
 	}
 	}
 
 
-	addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
+	addressData := nl.NewRtAttr(unix.IFA_ADDRESS, peerAddrData)
 	req.AddData(addressData)
 	req.AddData(addressData)
 
 
 	if addr.Flags != 0 {
 	if addr.Flags != 0 {
@@ -102,21 +103,34 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
 		}
 		}
 	}
 	}
 
 
-	if addr.Broadcast == nil {
-		calcBroadcast := make(net.IP, masklen/8)
-		for i := range localAddrData {
-			calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
+	if family == FAMILY_V4 {
+		if addr.Broadcast == nil {
+			calcBroadcast := make(net.IP, masklen/8)
+			for i := range localAddrData {
+				calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
+			}
+			addr.Broadcast = calcBroadcast
+		}
+		req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
+
+		if addr.Label != "" {
+			labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
+			req.AddData(labelData)
 		}
 		}
-		addr.Broadcast = calcBroadcast
 	}
 	}
-	req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
 
 
-	if addr.Label != "" {
-		labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
-		req.AddData(labelData)
+	// 0 is the default value for these attributes. However, 0 means "expired", while the least-surprising default
+	// value should be "forever". To compensate for that, only add the attributes if at least one of the values is
+	// non-zero, which means the caller has explicitly set them
+	if addr.ValidLft > 0 || addr.PreferedLft > 0 {
+		cachedata := nl.IfaCacheInfo{
+			IfaValid:    uint32(addr.ValidLft),
+			IfaPrefered: uint32(addr.PreferedLft),
+		}
+		req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize()))
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -131,11 +145,11 @@ func AddrList(link Link, family int) ([]Addr, error) {
 // Equivalent to: `ip addr show`.
 // Equivalent to: `ip addr show`.
 // The list can be filtered by link and ip family.
 // The list can be filtered by link and ip family.
 func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
 func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP)
 	msg := nl.NewIfInfomsg(family)
 	msg := nl.NewIfInfomsg(family)
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -187,21 +201,21 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
 	var local, dst *net.IPNet
 	var local, dst *net.IPNet
 	for _, attr := range attrs {
 	for _, attr := range attrs {
 		switch attr.Attr.Type {
 		switch attr.Attr.Type {
-		case syscall.IFA_ADDRESS:
+		case unix.IFA_ADDRESS:
 			dst = &net.IPNet{
 			dst = &net.IPNet{
 				IP:   attr.Value,
 				IP:   attr.Value,
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 			}
 			}
 			addr.Peer = dst
 			addr.Peer = dst
-		case syscall.IFA_LOCAL:
+		case unix.IFA_LOCAL:
 			local = &net.IPNet{
 			local = &net.IPNet{
 				IP:   attr.Value,
 				IP:   attr.Value,
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 			}
 			}
 			addr.IPNet = local
 			addr.IPNet = local
-		case syscall.IFA_BROADCAST:
+		case unix.IFA_BROADCAST:
 			addr.Broadcast = attr.Value
 			addr.Broadcast = attr.Value
-		case syscall.IFA_LABEL:
+		case unix.IFA_LABEL:
 			addr.Label = string(attr.Value[:len(attr.Value)-1])
 			addr.Label = string(attr.Value[:len(attr.Value)-1])
 		case IFA_FLAGS:
 		case IFA_FLAGS:
 			addr.Flags = int(native.Uint32(attr.Value[0:4]))
 			addr.Flags = int(native.Uint32(attr.Value[0:4]))
@@ -236,13 +250,13 @@ 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 {
-	return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil)
+	return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
 }
 }
 
 
 // AddrSubscribeAt works like AddrSubscribe plus it allows the caller
 // AddrSubscribeAt works like AddrSubscribe plus it allows the caller
 // to choose the network namespace in which to subscribe (ns).
 // to choose the network namespace in which to subscribe (ns).
 func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
 func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
-	return addrSubscribeAt(ns, netns.None(), ch, done, nil)
+	return addrSubscribeAt(ns, netns.None(), ch, done, nil, false)
 }
 }
 
 
 // AddrSubscribeOptions contains a set of options to use with
 // AddrSubscribeOptions contains a set of options to use with
@@ -250,6 +264,7 @@ func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct
 type AddrSubscribeOptions struct {
 type AddrSubscribeOptions struct {
 	Namespace     *netns.NsHandle
 	Namespace     *netns.NsHandle
 	ErrorCallback func(error)
 	ErrorCallback func(error)
+	ListExisting  bool
 }
 }
 
 
 // AddrSubscribeWithOptions work like AddrSubscribe but enable to
 // AddrSubscribeWithOptions work like AddrSubscribe but enable to
@@ -260,11 +275,11 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
 		none := netns.None()
 		none := netns.None()
 		options.Namespace = &none
 		options.Namespace = &none
 	}
 	}
-	return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback)
+	return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
 }
 }
 
 
-func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error)) error {
-	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
+func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
+	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -274,6 +289,15 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
 			s.Close()
 			s.Close()
 		}()
 		}()
 	}
 	}
+	if listExisting {
+		req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
+			unix.NLM_F_DUMP)
+		infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+		req.AddData(infmsg)
+		if err := s.Send(req); err != nil {
+			return err
+		}
+	}
 	go func() {
 	go func() {
 		defer close(ch)
 		defer close(ch)
 		for {
 		for {
@@ -285,8 +309,22 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
 				return
 				return
 			}
 			}
 			for _, m := range msgs {
 			for _, m := range msgs {
+				if m.Header.Type == unix.NLMSG_DONE {
+					continue
+				}
+				if m.Header.Type == unix.NLMSG_ERROR {
+					native := nl.NativeEndian()
+					error := int32(native.Uint32(m.Data[0:4]))
+					if error == 0 {
+						continue
+					}
+					if cberr != nil {
+						cberr(syscall.Errno(-error))
+					}
+					return
+				}
 				msgType := m.Header.Type
 				msgType := m.Header.Type
-				if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR {
+				if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
 					if cberr != nil {
 					if cberr != nil {
 						cberr(fmt.Errorf("bad message type: %d", msgType))
 						cberr(fmt.Errorf("bad message type: %d", msgType))
 					}
 					}
@@ -303,7 +341,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
 
 
 				ch <- AddrUpdate{LinkAddress: *addr.IPNet,
 				ch <- AddrUpdate{LinkAddress: *addr.IPNet,
 					LinkIndex:   ifindex,
 					LinkIndex:   ifindex,
-					NewAddr:     msgType == syscall.RTM_NEWADDR,
+					NewAddr:     msgType == unix.RTM_NEWADDR,
 					Flags:       addr.Flags,
 					Flags:       addr.Flags,
 					Scope:       addr.Scope,
 					Scope:       addr.Scope,
 					PreferedLft: addr.PreferedLft,
 					PreferedLft: addr.PreferedLft,

+ 37 - 46
vendor/github.com/vishvananda/netlink/bpf_linux.go

@@ -1,49 +1,12 @@
 package netlink
 package netlink
 
 
-/*
-#include <asm/types.h>
-#include <asm/unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
+import (
+	"unsafe"
 
 
-static int load_simple_bpf(int prog_type, int ret) {
-#ifdef __NR_bpf
-	// { return ret; }
-	__u64 __attribute__((aligned(8))) insns[] = {
-		0x00000000000000b7ull | ((__u64)ret<<32),
-		0x0000000000000095ull,
-	};
-	__u8 __attribute__((aligned(8))) license[] = "ASL2";
-	// Copied from a header file since libc is notoriously slow to update.
-	// The call will succeed or fail and that will be our indication on
-	// whether or not it is supported.
-	struct {
-		__u32 prog_type;
-		__u32 insn_cnt;
-		__u64 insns;
-		__u64 license;
-		__u32 log_level;
-		__u32 log_size;
-		__u64 log_buf;
-		__u32 kern_version;
-	} __attribute__((aligned(8))) attr = {
-		.prog_type = prog_type,
-		.insn_cnt = 2,
-		.insns = (uintptr_t)&insns,
-		.license = (uintptr_t)&license,
-	};
-	return syscall(__NR_bpf, 5, &attr, sizeof(attr));
-#else
-	errno = EINVAL;
-	return -1;
-#endif
-}
-*/
-import "C"
+	"golang.org/x/sys/unix"
+)
 
 
-type BpfProgType C.int
+type BpfProgType uint32
 
 
 const (
 const (
 	BPF_PROG_TYPE_UNSPEC BpfProgType = iota
 	BPF_PROG_TYPE_UNSPEC BpfProgType = iota
@@ -55,8 +18,36 @@ const (
 	BPF_PROG_TYPE_XDP
 	BPF_PROG_TYPE_XDP
 )
 )
 
 
-// loadSimpleBpf loads a trivial bpf program for testing purposes
-func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
-	fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
-	return int(fd), err
+type BPFAttr struct {
+	ProgType    uint32
+	InsnCnt     uint32
+	Insns       uintptr
+	License     uintptr
+	LogLevel    uint32
+	LogSize     uint32
+	LogBuf      uintptr
+	KernVersion uint32
+}
+
+// loadSimpleBpf loads a trivial bpf program for testing purposes.
+func loadSimpleBpf(progType BpfProgType, ret uint32) (int, error) {
+	insns := []uint64{
+		0x00000000000000b7 | (uint64(ret) << 32),
+		0x0000000000000095,
+	}
+	license := []byte{'A', 'S', 'L', '2', '\x00'}
+	attr := BPFAttr{
+		ProgType: uint32(progType),
+		InsnCnt:  uint32(len(insns)),
+		Insns:    uintptr(unsafe.Pointer(&insns[0])),
+		License:  uintptr(unsafe.Pointer(&license[0])),
+	}
+	fd, _, errno := unix.Syscall(unix.SYS_BPF,
+		5, /* bpf cmd */
+		uintptr(unsafe.Pointer(&attr)),
+		unsafe.Sizeof(attr))
+	if errno != 0 {
+		return 0, errno
+	}
+	return int(fd), nil
 }
 }

+ 12 - 12
vendor/github.com/vishvananda/netlink/bridge_linux.go

@@ -2,9 +2,9 @@ package netlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // BridgeVlanList gets a map of device id to bridge vlan infos.
 // BridgeVlanList gets a map of device id to bridge vlan infos.
@@ -16,12 +16,12 @@ func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
 // BridgeVlanList gets a map of device id to bridge vlan infos.
 // BridgeVlanList gets a map of device id to bridge vlan infos.
 // Equivalent to: `bridge vlan show`
 // Equivalent to: `bridge vlan show`
 func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
 func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
-	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
+	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
+	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
 	req.AddData(msg)
 	req.AddData(msg)
-	req.AddData(nl.NewRtAttr(nl.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
+	req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWLINK)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -35,7 +35,7 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
 		}
 		}
 		for _, attr := range attrs {
 		for _, attr := range attrs {
 			switch attr.Attr.Type {
 			switch attr.Attr.Type {
-			case nl.IFLA_AF_SPEC:
+			case unix.IFLA_AF_SPEC:
 				//nested attr
 				//nested attr
 				nestAttrs, err := nl.ParseRouteAttr(attr.Value)
 				nestAttrs, err := nl.ParseRouteAttr(attr.Value)
 				if err != nil {
 				if err != nil {
@@ -63,7 +63,7 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
 // BridgeVlanAdd adds a new vlan filter entry
 // BridgeVlanAdd adds a new vlan filter entry
 // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
 // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
 func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
 func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
-	return h.bridgeVlanModify(syscall.RTM_SETLINK, link, vid, pvid, untagged, self, master)
+	return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master)
 }
 }
 
 
 // BridgeVlanDel adds a new vlan filter entry
 // BridgeVlanDel adds a new vlan filter entry
@@ -75,19 +75,19 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
 // BridgeVlanDel adds a new vlan filter entry
 // BridgeVlanDel adds a new vlan filter entry
 // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
 // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
 func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
 func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
-	return h.bridgeVlanModify(syscall.RTM_DELLINK, link, vid, pvid, untagged, self, master)
+	return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master)
 }
 }
 
 
 func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
 func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
 	base := link.Attrs()
 	base := link.Attrs()
 	h.ensureIndex(base)
 	h.ensureIndex(base)
-	req := h.newNetlinkRequest(cmd, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
 
 
-	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
+	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
 	msg.Index = int32(base.Index)
 	msg.Index = int32(base.Index)
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	br := nl.NewRtAttr(nl.IFLA_AF_SPEC, nil)
+	br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
 	var flags uint16
 	var flags uint16
 	if self {
 	if self {
 		flags |= nl.BRIDGE_FLAGS_SELF
 		flags |= nl.BRIDGE_FLAGS_SELF
@@ -107,7 +107,7 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
 	}
 	}
 	nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
 	nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
 	req.AddData(br)
 	req.AddData(br)
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 13 - 12
vendor/github.com/vishvananda/netlink/class_linux.go

@@ -5,6 +5,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // NOTE: function is in here because it uses other linux functions
 // NOTE: function is in here because it uses other linux functions
@@ -50,7 +51,7 @@ func ClassDel(class Class) error {
 // ClassDel will delete a class from the system.
 // ClassDel will delete a class from the system.
 // Equivalent to: `tc class del $class`
 // Equivalent to: `tc class del $class`
 func (h *Handle) ClassDel(class Class) error {
 func (h *Handle) ClassDel(class Class) error {
-	return h.classModify(syscall.RTM_DELTCLASS, 0, class)
+	return h.classModify(unix.RTM_DELTCLASS, 0, class)
 }
 }
 
 
 // ClassChange will change a class in place
 // ClassChange will change a class in place
@@ -64,7 +65,7 @@ func ClassChange(class Class) error {
 // Equivalent to: `tc class change $class`
 // Equivalent to: `tc class change $class`
 // The parent and handle MUST NOT be changed.
 // The parent and handle MUST NOT be changed.
 func (h *Handle) ClassChange(class Class) error {
 func (h *Handle) ClassChange(class Class) error {
-	return h.classModify(syscall.RTM_NEWTCLASS, 0, class)
+	return h.classModify(unix.RTM_NEWTCLASS, 0, class)
 }
 }
 
 
 // ClassReplace will replace a class to the system.
 // ClassReplace will replace a class to the system.
@@ -82,7 +83,7 @@ func ClassReplace(class Class) error {
 // If a class already exist with this parent/handle pair, the class is changed.
 // If a class already exist with this parent/handle pair, the class is changed.
 // If a class does not already exist with this parent/handle, a new class is created.
 // If a class does not already exist with this parent/handle, a new class is created.
 func (h *Handle) ClassReplace(class Class) error {
 func (h *Handle) ClassReplace(class Class) error {
-	return h.classModify(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE, class)
+	return h.classModify(unix.RTM_NEWTCLASS, unix.NLM_F_CREATE, class)
 }
 }
 
 
 // ClassAdd will add a class to the system.
 // ClassAdd will add a class to the system.
@@ -95,14 +96,14 @@ func ClassAdd(class Class) error {
 // Equivalent to: `tc class add $class`
 // Equivalent to: `tc class add $class`
 func (h *Handle) ClassAdd(class Class) error {
 func (h *Handle) ClassAdd(class Class) error {
 	return h.classModify(
 	return h.classModify(
-		syscall.RTM_NEWTCLASS,
-		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
+		unix.RTM_NEWTCLASS,
+		unix.NLM_F_CREATE|unix.NLM_F_EXCL,
 		class,
 		class,
 	)
 	)
 }
 }
 
 
 func (h *Handle) classModify(cmd, flags int, class Class) error {
 func (h *Handle) classModify(cmd, flags int, class Class) error {
-	req := h.newNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
 	base := class.Attrs()
 	base := class.Attrs()
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family:  nl.FAMILY_ALL,
 		Family:  nl.FAMILY_ALL,
@@ -112,12 +113,12 @@ func (h *Handle) classModify(cmd, flags int, class Class) error {
 	}
 	}
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	if cmd != syscall.RTM_DELTCLASS {
+	if cmd != unix.RTM_DELTCLASS {
 		if err := classPayload(req, class); err != nil {
 		if err := classPayload(req, class); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -141,12 +142,12 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
 		var rtab [256]uint32
 		var rtab [256]uint32
 		var ctab [256]uint32
 		var ctab [256]uint32
 		tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
 		tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
-		if CalcRtable(&tcrate, rtab, cellLog, uint32(mtu), linklayer) < 0 {
+		if CalcRtable(&tcrate, rtab[:], cellLog, uint32(mtu), linklayer) < 0 {
 			return errors.New("HTB: failed to calculate rate table")
 			return errors.New("HTB: failed to calculate rate table")
 		}
 		}
 		opt.Rate = tcrate
 		opt.Rate = tcrate
 		tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
 		tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
-		if CalcRtable(&tcceil, ctab, ccellLog, uint32(mtu), linklayer) < 0 {
+		if CalcRtable(&tcceil, ctab[:], ccellLog, uint32(mtu), linklayer) < 0 {
 			return errors.New("HTB: failed to calculate ceil rate table")
 			return errors.New("HTB: failed to calculate ceil rate table")
 		}
 		}
 		opt.Ceil = tcceil
 		opt.Ceil = tcceil
@@ -169,7 +170,7 @@ func ClassList(link Link, parent uint32) ([]Class, error) {
 // Equivalent to: `tc class show`.
 // Equivalent to: `tc class show`.
 // Generally returns nothing if link and parent are not specified.
 // Generally returns nothing if link and parent are not specified.
 func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
 func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETTCLASS, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP)
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family: nl.FAMILY_ALL,
 		Family: nl.FAMILY_ALL,
 		Parent: parent,
 		Parent: parent,
@@ -181,7 +182,7 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
 	}
 	}
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTCLASS)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 7 - 7
vendor/github.com/vishvananda/netlink/conntrack_linux.go

@@ -6,9 +6,9 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
-	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // ConntrackTableType Conntrack table for the netlink operation
 // ConntrackTableType Conntrack table for the netlink operation
@@ -85,8 +85,8 @@ func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily)
 // conntrack -F [table]            Flush table
 // conntrack -F [table]            Flush table
 // The flush operation applies to all the family types
 // The flush operation applies to all the family types
 func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
 func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
-	req := h.newConntrackRequest(table, syscall.AF_INET, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK)
-	_, err := req.Execute(syscall.NETLINK_NETFILTER, 0)
+	req := h.newConntrackRequest(table, unix.AF_INET, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
+	_, err := req.Execute(unix.NETLINK_NETFILTER, 0)
 	return err
 	return err
 }
 }
 
 
@@ -102,10 +102,10 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
 	for _, dataRaw := range res {
 	for _, dataRaw := range res {
 		flow := parseRawData(dataRaw)
 		flow := parseRawData(dataRaw)
 		if match := filter.MatchConntrackFlow(flow); match {
 		if match := filter.MatchConntrackFlow(flow); match {
-			req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK)
+			req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
 			// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
 			// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
 			req2.AddRawData(dataRaw[4:])
 			req2.AddRawData(dataRaw[4:])
-			req2.Execute(syscall.NETLINK_NETFILTER, 0)
+			req2.Execute(unix.NETLINK_NETFILTER, 0)
 			matched++
 			matched++
 		}
 		}
 	}
 	}
@@ -127,8 +127,8 @@ func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily
 }
 }
 
 
 func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) {
 func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) {
-	req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, syscall.NLM_F_DUMP)
-	return req.Execute(syscall.NETLINK_NETFILTER, 0)
+	req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, unix.NLM_F_DUMP)
+	return req.Execute(unix.NETLINK_NETFILTER, 0)
 }
 }
 
 
 // The full conntrack flow structure is very complicated and can be found in the file:
 // The full conntrack flow structure is very complicated and can be found in the file:

+ 16 - 1
vendor/github.com/vishvananda/netlink/filter.go

@@ -17,7 +17,7 @@ type FilterAttrs struct {
 	Handle    uint32
 	Handle    uint32
 	Parent    uint32
 	Parent    uint32
 	Priority  uint16 // lower is higher priority
 	Priority  uint16 // lower is higher priority
-	Protocol  uint16 // syscall.ETH_P_*
+	Protocol  uint16 // unix.ETH_P_*
 }
 }
 
 
 func (q FilterAttrs) String() string {
 func (q FilterAttrs) String() string {
@@ -225,6 +225,21 @@ func (filter *U32) Type() string {
 	return "u32"
 	return "u32"
 }
 }
 
 
+// MatchAll filters match all packets
+type MatchAll struct {
+	FilterAttrs
+	ClassId uint32
+	Actions []Action
+}
+
+func (filter *MatchAll) Attrs() *FilterAttrs {
+	return &filter.FilterAttrs
+}
+
+func (filter *MatchAll) Type() string {
+	return "matchall"
+}
+
 type FilterFwAttrs struct {
 type FilterFwAttrs struct {
 	ClassId   uint32
 	ClassId   uint32
 	InDev     string
 	InDev     string

+ 47 - 9
vendor/github.com/vishvananda/netlink/filter_linux.go

@@ -9,6 +9,7 @@ import (
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // Constants used in TcU32Sel.Flags.
 // Constants used in TcU32Sel.Flags.
@@ -55,7 +56,7 @@ func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
 	if police.Rate.Rate != 0 {
 	if police.Rate.Rate != 0 {
 		police.Rate.Mpu = fattrs.Mpu
 		police.Rate.Mpu = fattrs.Mpu
 		police.Rate.Overhead = fattrs.Overhead
 		police.Rate.Overhead = fattrs.Overhead
-		if CalcRtable(&police.Rate, rtab, rcellLog, fattrs.Mtu, linklayer) < 0 {
+		if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
 			return nil, errors.New("TBF: failed to calculate rate table")
 			return nil, errors.New("TBF: failed to calculate rate table")
 		}
 		}
 		police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer)))
 		police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer)))
@@ -64,7 +65,7 @@ func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
 	if police.PeakRate.Rate != 0 {
 	if police.PeakRate.Rate != 0 {
 		police.PeakRate.Mpu = fattrs.Mpu
 		police.PeakRate.Mpu = fattrs.Mpu
 		police.PeakRate.Overhead = fattrs.Overhead
 		police.PeakRate.Overhead = fattrs.Overhead
-		if CalcRtable(&police.PeakRate, ptab, pcellLog, fattrs.Mtu, linklayer) < 0 {
+		if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
 			return nil, errors.New("POLICE: failed to calculate peak rate table")
 			return nil, errors.New("POLICE: failed to calculate peak rate table")
 		}
 		}
 	}
 	}
@@ -98,7 +99,7 @@ func FilterDel(filter Filter) error {
 // FilterDel will delete a filter from the system.
 // FilterDel will delete a filter from the system.
 // Equivalent to: `tc filter del $filter`
 // Equivalent to: `tc filter del $filter`
 func (h *Handle) FilterDel(filter Filter) error {
 func (h *Handle) FilterDel(filter Filter) error {
-	req := h.newNetlinkRequest(syscall.RTM_DELTFILTER, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK)
 	base := filter.Attrs()
 	base := filter.Attrs()
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family:  nl.FAMILY_ALL,
 		Family:  nl.FAMILY_ALL,
@@ -109,7 +110,7 @@ func (h *Handle) FilterDel(filter Filter) error {
 	}
 	}
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -123,7 +124,7 @@ func FilterAdd(filter Filter) error {
 // Equivalent to: `tc filter add $filter`
 // Equivalent to: `tc filter add $filter`
 func (h *Handle) FilterAdd(filter Filter) error {
 func (h *Handle) FilterAdd(filter Filter) error {
 	native = nl.NativeEndian()
 	native = nl.NativeEndian()
-	req := h.newNetlinkRequest(syscall.RTM_NEWTFILTER, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 	base := filter.Attrs()
 	base := filter.Attrs()
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family:  nl.FAMILY_ALL,
 		Family:  nl.FAMILY_ALL,
@@ -221,10 +222,18 @@ func (h *Handle) FilterAdd(filter Filter) error {
 			bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
 			bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
 		}
 		}
 		nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
 		nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
+	case *MatchAll:
+		actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil)
+		if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
+			return err
+		}
+		if filter.ClassId != 0 {
+			nl.NewRtAttrChild(options, nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
+		}
 	}
 	}
 
 
 	req.AddData(options)
 	req.AddData(options)
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -239,7 +248,7 @@ func FilterList(link Link, parent uint32) ([]Filter, error) {
 // Equivalent to: `tc filter show`.
 // Equivalent to: `tc filter show`.
 // Generally returns nothing if link and parent are not specified.
 // Generally returns nothing if link and parent are not specified.
 func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
 func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETTFILTER, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP)
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family: nl.FAMILY_ALL,
 		Family: nl.FAMILY_ALL,
 		Parent: parent,
 		Parent: parent,
@@ -251,7 +260,7 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
 	}
 	}
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTFILTER)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -287,6 +296,8 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
 					filter = &Fw{}
 					filter = &Fw{}
 				case "bpf":
 				case "bpf":
 					filter = &BpfFilter{}
 					filter = &BpfFilter{}
+				case "matchall":
+					filter = &MatchAll{}
 				default:
 				default:
 					filter = &GenericFilter{FilterType: filterType}
 					filter = &GenericFilter{FilterType: filterType}
 				}
 				}
@@ -311,6 +322,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
 					if err != nil {
 					if err != nil {
 						return nil, err
 						return nil, err
 					}
 					}
+				case "matchall":
+					detailed, err = parseMatchAllData(filter, data)
+					if err != nil {
+						return nil, err
+					}
 				default:
 				default:
 					detailed = true
 					detailed = true
 				}
 				}
@@ -540,6 +556,28 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
 	return detailed, nil
 	return detailed, nil
 }
 }
 
 
+func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
+	native = nl.NativeEndian()
+	matchall := filter.(*MatchAll)
+	detailed := true
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.TCA_MATCHALL_CLASSID:
+			matchall.ClassId = native.Uint32(datum.Value[0:4])
+		case nl.TCA_MATCHALL_ACT:
+			tables, err := nl.ParseRouteAttr(datum.Value)
+			if err != nil {
+				return detailed, err
+			}
+			matchall.Actions, err = parseActions(tables)
+			if err != nil {
+				return detailed, err
+			}
+		}
+	}
+	return detailed, nil
+}
+
 func AlignToAtm(size uint) uint {
 func AlignToAtm(size uint) uint {
 	var linksize, cells int
 	var linksize, cells int
 	cells = int(size / nl.ATM_CELL_PAYLOAD)
 	cells = int(size / nl.ATM_CELL_PAYLOAD)
@@ -562,7 +600,7 @@ func AdjustSize(sz uint, mpu uint, linklayer int) uint {
 	}
 	}
 }
 }
 
 
-func CalcRtable(rate *nl.TcRateSpec, rtab [256]uint32, cellLog int, mtu uint32, linklayer int) int {
+func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int {
 	bps := rate.Rate
 	bps := rate.Rate
 	mpu := rate.Mpu
 	mpu := rate.Mpu
 	var sz uint
 	var sz uint

+ 21 - 0
vendor/github.com/vishvananda/netlink/fou.go

@@ -0,0 +1,21 @@
+package netlink
+
+import (
+	"errors"
+)
+
+var (
+	// ErrAttrHeaderTruncated is returned when a netlink attribute's header is
+	// truncated.
+	ErrAttrHeaderTruncated = errors.New("attribute header truncated")
+	// ErrAttrBodyTruncated is returned when a netlink attribute's body is
+	// truncated.
+	ErrAttrBodyTruncated = errors.New("attribute body truncated")
+)
+
+type Fou struct {
+	Family    int
+	Port      int
+	Protocol  int
+	EncapType int
+}

+ 215 - 0
vendor/github.com/vishvananda/netlink/fou_linux.go

@@ -0,0 +1,215 @@
+// +build linux
+
+package netlink
+
+import (
+	"encoding/binary"
+	"errors"
+
+	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
+)
+
+const (
+	FOU_GENL_NAME = "fou"
+)
+
+const (
+	FOU_CMD_UNSPEC uint8 = iota
+	FOU_CMD_ADD
+	FOU_CMD_DEL
+	FOU_CMD_GET
+	FOU_CMD_MAX = FOU_CMD_GET
+)
+
+const (
+	FOU_ATTR_UNSPEC = iota
+	FOU_ATTR_PORT
+	FOU_ATTR_AF
+	FOU_ATTR_IPPROTO
+	FOU_ATTR_TYPE
+	FOU_ATTR_REMCSUM_NOPARTIAL
+	FOU_ATTR_MAX = FOU_ATTR_REMCSUM_NOPARTIAL
+)
+
+const (
+	FOU_ENCAP_UNSPEC = iota
+	FOU_ENCAP_DIRECT
+	FOU_ENCAP_GUE
+	FOU_ENCAP_MAX = FOU_ENCAP_GUE
+)
+
+var fouFamilyId int
+
+func FouFamilyId() (int, error) {
+	if fouFamilyId != 0 {
+		return fouFamilyId, nil
+	}
+
+	fam, err := GenlFamilyGet(FOU_GENL_NAME)
+	if err != nil {
+		return -1, err
+	}
+
+	fouFamilyId = int(fam.ID)
+	return fouFamilyId, nil
+}
+
+func FouAdd(f Fou) error {
+	return pkgHandle.FouAdd(f)
+}
+
+func (h *Handle) FouAdd(f Fou) error {
+	fam_id, err := FouFamilyId()
+	if err != nil {
+		return err
+	}
+
+	// setting ip protocol conflicts with encapsulation type GUE
+	if f.EncapType == FOU_ENCAP_GUE && f.Protocol != 0 {
+		return errors.New("GUE encapsulation doesn't specify an IP protocol")
+	}
+
+	req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK)
+
+	// int to byte for port
+	bp := make([]byte, 2)
+	binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port))
+
+	attrs := []*nl.RtAttr{
+		nl.NewRtAttr(FOU_ATTR_PORT, bp),
+		nl.NewRtAttr(FOU_ATTR_TYPE, []byte{uint8(f.EncapType)}),
+		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}),
+		nl.NewRtAttr(FOU_ATTR_IPPROTO, []byte{uint8(f.Protocol)}),
+	}
+	raw := []byte{FOU_CMD_ADD, 1, 0, 0}
+	for _, a := range attrs {
+		raw = append(raw, a.Serialize()...)
+	}
+
+	req.AddRawData(raw)
+
+	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func FouDel(f Fou) error {
+	return pkgHandle.FouDel(f)
+}
+
+func (h *Handle) FouDel(f Fou) error {
+	fam_id, err := FouFamilyId()
+	if err != nil {
+		return err
+	}
+
+	req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK)
+
+	// int to byte for port
+	bp := make([]byte, 2)
+	binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port))
+
+	attrs := []*nl.RtAttr{
+		nl.NewRtAttr(FOU_ATTR_PORT, bp),
+		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}),
+	}
+	raw := []byte{FOU_CMD_DEL, 1, 0, 0}
+	for _, a := range attrs {
+		raw = append(raw, a.Serialize()...)
+	}
+
+	req.AddRawData(raw)
+
+	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func FouList(fam int) ([]Fou, error) {
+	return pkgHandle.FouList(fam)
+}
+
+func (h *Handle) FouList(fam int) ([]Fou, error) {
+	fam_id, err := FouFamilyId()
+	if err != nil {
+		return nil, err
+	}
+
+	req := h.newNetlinkRequest(fam_id, unix.NLM_F_DUMP)
+
+	attrs := []*nl.RtAttr{
+		nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(fam)}),
+	}
+	raw := []byte{FOU_CMD_GET, 1, 0, 0}
+	for _, a := range attrs {
+		raw = append(raw, a.Serialize()...)
+	}
+
+	req.AddRawData(raw)
+
+	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	fous := make([]Fou, 0, len(msgs))
+	for _, m := range msgs {
+		f, err := deserializeFouMsg(m)
+		if err != nil {
+			return fous, err
+		}
+
+		fous = append(fous, f)
+	}
+
+	return fous, nil
+}
+
+func deserializeFouMsg(msg []byte) (Fou, error) {
+	// we'll skip to byte 4 to first attribute
+	msg = msg[3:]
+	var shift int
+	fou := Fou{}
+
+	for {
+		// attribute header is at least 16 bits
+		if len(msg) < 4 {
+			return fou, ErrAttrHeaderTruncated
+		}
+
+		lgt := int(binary.BigEndian.Uint16(msg[0:2]))
+		if len(msg) < lgt+4 {
+			return fou, ErrAttrBodyTruncated
+		}
+		attr := binary.BigEndian.Uint16(msg[2:4])
+
+		shift = lgt + 3
+		switch attr {
+		case FOU_ATTR_AF:
+			fou.Family = int(msg[5])
+		case FOU_ATTR_PORT:
+			fou.Port = int(binary.BigEndian.Uint16(msg[5:7]))
+			// port is 2 bytes
+			shift = lgt + 2
+		case FOU_ATTR_IPPROTO:
+			fou.Protocol = int(msg[5])
+		case FOU_ATTR_TYPE:
+			fou.EncapType = int(msg[5])
+		}
+
+		msg = msg[shift:]
+
+		if len(msg) < 4 {
+			break
+		}
+	}
+
+	return fou, nil
+}

+ 15 - 0
vendor/github.com/vishvananda/netlink/fou_unspecified.go

@@ -0,0 +1,15 @@
+// +build !linux
+
+package netlink
+
+func FouAdd(f Fou) error {
+	return ErrNotImplemented
+}
+
+func FouDel(f Fou) error {
+	return ErrNotImplemented
+}
+
+func FouList(fam int) ([]Fou, error) {
+	return nil, ErrNotImplemented
+}

+ 4 - 3
vendor/github.com/vishvananda/netlink/genetlink_linux.go

@@ -5,6 +5,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 type GenlOp struct {
 type GenlOp struct {
@@ -130,9 +131,9 @@ func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
 		Command: nl.GENL_CTRL_CMD_GETFAMILY,
 		Command: nl.GENL_CTRL_CMD_GETFAMILY,
 		Version: nl.GENL_CTRL_VERSION,
 		Version: nl.GENL_CTRL_VERSION,
 	}
 	}
-	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, unix.NLM_F_DUMP)
 	req.AddData(msg)
 	req.AddData(msg)
-	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -151,7 +152,7 @@ func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
 	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
 	req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
 	req.AddData(msg)
 	req.AddData(msg)
 	req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
 	req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
-	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 8 - 7
vendor/github.com/vishvananda/netlink/gtp_linux.go

@@ -7,6 +7,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 type PDP struct {
 type PDP struct {
@@ -82,9 +83,9 @@ func (h *Handle) GTPPDPList() ([]*PDP, error) {
 		Command: nl.GENL_GTP_CMD_GETPDP,
 		Command: nl.GENL_GTP_CMD_GETPDP,
 		Version: nl.GENL_GTP_VERSION,
 		Version: nl.GENL_GTP_VERSION,
 	}
 	}
-	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_DUMP)
 	req.AddData(msg)
 	req.AddData(msg)
-	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -96,7 +97,7 @@ func GTPPDPList() ([]*PDP, error) {
 }
 }
 
 
 func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
 func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
-	msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
+	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -182,7 +183,7 @@ func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
 		Command: nl.GENL_GTP_CMD_NEWPDP,
 		Command: nl.GENL_GTP_CMD_NEWPDP,
 		Version: nl.GENL_GTP_VERSION,
 		Version: nl.GENL_GTP_VERSION,
 	}
 	}
-	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
 	req.AddData(msg)
 	req.AddData(msg)
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
@@ -199,7 +200,7 @@ func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
 	default:
 	default:
 		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
 		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
 	}
 	}
-	_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
+	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
 	return err
 	return err
 }
 }
 
 
@@ -216,7 +217,7 @@ func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
 		Command: nl.GENL_GTP_CMD_DELPDP,
 		Command: nl.GENL_GTP_CMD_DELPDP,
 		Version: nl.GENL_GTP_VERSION,
 		Version: nl.GENL_GTP_VERSION,
 	}
 	}
-	req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
 	req.AddData(msg)
 	req.AddData(msg)
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
 	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
@@ -229,7 +230,7 @@ func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
 	default:
 	default:
 		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
 		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
 	}
 	}
-	_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
+	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
 	return err
 	return err
 }
 }
 
 

+ 9 - 9
vendor/github.com/vishvananda/netlink/handle_linux.go

@@ -2,11 +2,11 @@ package netlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"syscall"
 	"time"
 	"time"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // Empty handle used by the netlink package methods
 // Empty handle used by the netlink package methods
@@ -43,7 +43,7 @@ func (h *Handle) SetSocketTimeout(to time.Duration) error {
 	if to < time.Microsecond {
 	if to < time.Microsecond {
 		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
 		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
 	}
 	}
-	tv := syscall.NsecToTimeval(to.Nanoseconds())
+	tv := unix.NsecToTimeval(to.Nanoseconds())
 	for _, sh := range h.sockets {
 	for _, sh := range h.sockets {
 		if err := sh.Socket.SetSendTimeout(&tv); err != nil {
 		if err := sh.Socket.SetSendTimeout(&tv); err != nil {
 			return err
 			return err
@@ -59,13 +59,13 @@ func (h *Handle) SetSocketTimeout(to time.Duration) error {
 // socket in the netlink handle. The maximum value is capped by
 // socket in the netlink handle. The maximum value is capped by
 // /proc/sys/net/core/rmem_max.
 // /proc/sys/net/core/rmem_max.
 func (h *Handle) SetSocketReceiveBufferSize(size int, force bool) error {
 func (h *Handle) SetSocketReceiveBufferSize(size int, force bool) error {
-	opt := syscall.SO_RCVBUF
+	opt := unix.SO_RCVBUF
 	if force {
 	if force {
-		opt = syscall.SO_RCVBUFFORCE
+		opt = unix.SO_RCVBUFFORCE
 	}
 	}
 	for _, sh := range h.sockets {
 	for _, sh := range h.sockets {
 		fd := sh.Socket.GetFd()
 		fd := sh.Socket.GetFd()
-		err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, opt, size)
+		err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, opt, size)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -81,7 +81,7 @@ func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
 	i := 0
 	i := 0
 	for _, sh := range h.sockets {
 	for _, sh := range h.sockets {
 		fd := sh.Socket.GetFd()
 		fd := sh.Socket.GetFd()
-		size, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF)
+		size, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_RCVBUF)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -134,10 +134,10 @@ func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
 		return nl.NewNetlinkRequest(proto, flags)
 		return nl.NewNetlinkRequest(proto, flags)
 	}
 	}
 	return &nl.NetlinkRequest{
 	return &nl.NetlinkRequest{
-		NlMsghdr: syscall.NlMsghdr{
-			Len:   uint32(syscall.SizeofNlMsghdr),
+		NlMsghdr: unix.NlMsghdr{
+			Len:   uint32(unix.SizeofNlMsghdr),
 			Type:  uint16(proto),
 			Type:  uint16(proto),
-			Flags: syscall.NLM_F_REQUEST | uint16(flags),
+			Flags: unix.NLM_F_REQUEST | uint16(flags),
 		},
 		},
 		Sockets: h.sockets,
 		Sockets: h.sockets,
 	}
 	}

+ 36 - 0
vendor/github.com/vishvananda/netlink/handle_unspecified.go

@@ -220,3 +220,39 @@ func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
 func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
 func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
 	return nil, ErrNotImplemented
 	return nil, ErrNotImplemented
 }
 }
+
+func (h *Handle) RouteAdd(route *Route) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) RouteDel(route *Route) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) RouteReplace(route *Route) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) RuleAdd(rule *Rule) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) RuleDel(rule *Rule) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) RuleList(family int) ([]Rule, error) {
+	return nil, ErrNotImplemented
+}

+ 98 - 0
vendor/github.com/vishvananda/netlink/ioctl_linux.go

@@ -0,0 +1,98 @@
+package netlink
+
+import (
+	"syscall"
+	"unsafe"
+
+	"golang.org/x/sys/unix"
+)
+
+// ioctl for statistics.
+const (
+	// ETHTOOL_GSSET_INFO gets string set info
+	ETHTOOL_GSSET_INFO = 0x00000037
+	// SIOCETHTOOL is Ethtool interface
+	SIOCETHTOOL = 0x8946
+	// ETHTOOL_GSTRINGS gets specified string set
+	ETHTOOL_GSTRINGS = 0x0000001b
+	// ETHTOOL_GSTATS gets NIC-specific statistics
+	ETHTOOL_GSTATS = 0x0000001d
+)
+
+// string set id.
+const (
+	// ETH_SS_TEST is self-test result names, for use with %ETHTOOL_TEST
+	ETH_SS_TEST = iota
+	// ETH_SS_STATS statistic names, for use with %ETHTOOL_GSTATS
+	ETH_SS_STATS
+	// ETH_SS_PRIV_FLAGS are driver private flag names
+	ETH_SS_PRIV_FLAGS
+	// _ETH_SS_NTUPLE_FILTERS is deprecated
+	_ETH_SS_NTUPLE_FILTERS
+	// ETH_SS_FEATURES are device feature names
+	ETH_SS_FEATURES
+	// ETH_SS_RSS_HASH_FUNCS is RSS hush function names
+	ETH_SS_RSS_HASH_FUNCS
+)
+
+// IfreqSlave is a struct for ioctl bond manipulation syscalls.
+// It is used to assign slave to bond interface with Name.
+type IfreqSlave struct {
+	Name  [unix.IFNAMSIZ]byte
+	Slave [unix.IFNAMSIZ]byte
+}
+
+// Ifreq is a struct for ioctl ethernet manipulation syscalls.
+type Ifreq struct {
+	Name [unix.IFNAMSIZ]byte
+	Data uintptr
+}
+
+// ethtoolSset is a string set information
+type ethtoolSset struct {
+	cmd      uint32
+	reserved uint32
+	mask     uint64
+	data     [1]uint32
+}
+
+// ethtoolGstrings is string set for data tagging
+type ethtoolGstrings struct {
+	cmd       uint32
+	stringSet uint32
+	length    uint32
+	data      [32]byte
+}
+
+type ethtoolStats struct {
+	cmd    uint32
+	nStats uint32
+	data   [1]uint64
+}
+
+// newIocltSlaveReq returns filled IfreqSlave with proper interface names
+// It is used by ioctl to assign slave to bond master
+func newIocltSlaveReq(slave, master string) *IfreqSlave {
+	ifreq := &IfreqSlave{}
+	copy(ifreq.Name[:unix.IFNAMSIZ-1], master)
+	copy(ifreq.Slave[:unix.IFNAMSIZ-1], slave)
+	return ifreq
+}
+
+// newIocltStringSetReq creates request to get interface string set
+func newIocltStringSetReq(linkName string) (*Ifreq, *ethtoolSset) {
+	e := &ethtoolSset{
+		cmd:  ETHTOOL_GSSET_INFO,
+		mask: 1 << ETH_SS_STATS,
+	}
+
+	ifreq := &Ifreq{Data: uintptr(unsafe.Pointer(e))}
+	copy(ifreq.Name[:unix.IFNAMSIZ-1], linkName)
+	return ifreq, e
+}
+
+// getSocketUDP returns file descriptor to new UDP socket
+// It is used for communication with ioctl interface.
+func getSocketUDP() (int, error) {
+	return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0)
+}

+ 85 - 38
vendor/github.com/vishvananda/netlink/link.go

@@ -3,6 +3,7 @@ package netlink
 import (
 import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
+	"os"
 )
 )
 
 
 // Link represents a link device from netlink. Shared link attributes
 // Link represents a link device from netlink. Shared link attributes
@@ -38,6 +39,8 @@ type LinkAttrs struct {
 	Protinfo     *Protinfo
 	Protinfo     *Protinfo
 	OperState    LinkOperState
 	OperState    LinkOperState
 	NetNsID      int
 	NetNsID      int
+	NumTxQueues  int
+	NumRxQueues  int
 }
 }
 
 
 // LinkOperState represents the values of the IFLA_OPERSTATE link
 // LinkOperState represents the values of the IFLA_OPERSTATE link
@@ -259,6 +262,9 @@ const (
 type Macvlan struct {
 type Macvlan struct {
 	LinkAttrs
 	LinkAttrs
 	Mode MacvlanMode
 	Mode MacvlanMode
+
+	// MACAddrs is only populated for Macvlan SOURCE links
+	MACAddrs []net.HardwareAddr
 }
 }
 
 
 func (macvlan *Macvlan) Attrs() *LinkAttrs {
 func (macvlan *Macvlan) Attrs() *LinkAttrs {
@@ -284,8 +290,10 @@ type TuntapFlag uint16
 // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
 // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
 type Tuntap struct {
 type Tuntap struct {
 	LinkAttrs
 	LinkAttrs
-	Mode  TuntapMode
-	Flags TuntapFlag
+	Mode   TuntapMode
+	Flags  TuntapFlag
+	Queues int
+	Fds    []*os.File
 }
 }
 
 
 func (tuntap *Tuntap) Attrs() *LinkAttrs {
 func (tuntap *Tuntap) Attrs() *LinkAttrs {
@@ -327,26 +335,28 @@ func (generic *GenericLink) Type() string {
 
 
 type Vxlan struct {
 type Vxlan struct {
 	LinkAttrs
 	LinkAttrs
-	VxlanId      int
-	VtepDevIndex int
-	SrcAddr      net.IP
-	Group        net.IP
-	TTL          int
-	TOS          int
-	Learning     bool
-	Proxy        bool
-	RSC          bool
-	L2miss       bool
-	L3miss       bool
-	UDPCSum      bool
-	NoAge        bool
-	GBP          bool
-	FlowBased    bool
-	Age          int
-	Limit        int
-	Port         int
-	PortLow      int
-	PortHigh     int
+	VxlanId        int
+	VtepDevIndex   int
+	SrcAddr        net.IP
+	Group          net.IP
+	TTL            int
+	TOS            int
+	Learning       bool
+	Proxy          bool
+	RSC            bool
+	L2miss         bool
+	L3miss         bool
+	UDPCSum        bool
+	UDP6ZeroCSumTx bool
+	UDP6ZeroCSumRx bool
+	NoAge          bool
+	GBP            bool
+	FlowBased      bool
+	Age            int
+	Limit          int
+	Port           int
+	PortLow        int
+	PortHigh       int
 }
 }
 
 
 func (vxlan *Vxlan) Attrs() *LinkAttrs {
 func (vxlan *Vxlan) Attrs() *LinkAttrs {
@@ -695,17 +705,25 @@ func (gretap *Gretap) Attrs() *LinkAttrs {
 }
 }
 
 
 func (gretap *Gretap) Type() string {
 func (gretap *Gretap) Type() string {
+	if gretap.Local.To4() == nil {
+		return "ip6gretap"
+	}
 	return "gretap"
 	return "gretap"
 }
 }
 
 
 type Iptun struct {
 type Iptun struct {
 	LinkAttrs
 	LinkAttrs
-	Ttl      uint8
-	Tos      uint8
-	PMtuDisc uint8
-	Link     uint32
-	Local    net.IP
-	Remote   net.IP
+	Ttl        uint8
+	Tos        uint8
+	PMtuDisc   uint8
+	Link       uint32
+	Local      net.IP
+	Remote     net.IP
+	EncapSport uint16
+	EncapDport uint16
+	EncapType  uint16
+	EncapFlags uint16
+	FlowBased  bool
 }
 }
 
 
 func (iptun *Iptun) Attrs() *LinkAttrs {
 func (iptun *Iptun) Attrs() *LinkAttrs {
@@ -716,6 +734,28 @@ func (iptun *Iptun) Type() string {
 	return "ipip"
 	return "ipip"
 }
 }
 
 
+type Sittun struct {
+	LinkAttrs
+	Link       uint32
+	Local      net.IP
+	Remote     net.IP
+	Ttl        uint8
+	Tos        uint8
+	PMtuDisc   uint8
+	EncapType  uint16
+	EncapFlags uint16
+	EncapSport uint16
+	EncapDport uint16
+}
+
+func (sittun *Sittun) Attrs() *LinkAttrs {
+	return &sittun.LinkAttrs
+}
+
+func (sittun *Sittun) Type() string {
+	return "sit"
+}
+
 type Vti struct {
 type Vti struct {
 	LinkAttrs
 	LinkAttrs
 	IKey   uint32
 	IKey   uint32
@@ -735,16 +775,20 @@ func (iptun *Vti) Type() string {
 
 
 type Gretun struct {
 type Gretun struct {
 	LinkAttrs
 	LinkAttrs
-	Link     uint32
-	IFlags   uint16
-	OFlags   uint16
-	IKey     uint32
-	OKey     uint32
-	Local    net.IP
-	Remote   net.IP
-	Ttl      uint8
-	Tos      uint8
-	PMtuDisc uint8
+	Link       uint32
+	IFlags     uint16
+	OFlags     uint16
+	IKey       uint32
+	OKey       uint32
+	Local      net.IP
+	Remote     net.IP
+	Ttl        uint8
+	Tos        uint8
+	PMtuDisc   uint8
+	EncapType  uint16
+	EncapFlags uint16
+	EncapSport uint16
+	EncapDport uint16
 }
 }
 
 
 func (gretun *Gretun) Attrs() *LinkAttrs {
 func (gretun *Gretun) Attrs() *LinkAttrs {
@@ -752,6 +796,9 @@ func (gretun *Gretun) Attrs() *LinkAttrs {
 }
 }
 
 
 func (gretun *Gretun) Type() string {
 func (gretun *Gretun) Type() string {
+	if gretun.Local.To4() == nil {
+		return "ip6gre"
+	}
 	return "gre"
 	return "gre"
 }
 }
 
 

Разница между файлами не показана из-за своего большого размера
+ 309 - 165
vendor/github.com/vishvananda/netlink/link_linux.go


+ 2 - 0
vendor/github.com/vishvananda/netlink/neigh.go

@@ -15,6 +15,8 @@ type Neigh struct {
 	IP           net.IP
 	IP           net.IP
 	HardwareAddr net.HardwareAddr
 	HardwareAddr net.HardwareAddr
 	LLIPAddr     net.IP //Used in the case of NHRP
 	LLIPAddr     net.IP //Used in the case of NHRP
+	Vlan         int
+	VNI          int
 }
 }
 
 
 // String returns $ip/$hwaddr $label
 // String returns $ip/$hwaddr $label

+ 24 - 10
vendor/github.com/vishvananda/netlink/neigh_linux.go

@@ -2,10 +2,10 @@ package netlink
 
 
 import (
 import (
 	"net"
 	"net"
-	"syscall"
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 const (
 const (
@@ -73,7 +73,7 @@ func NeighAdd(neigh *Neigh) error {
 // NeighAdd will add an IP to MAC mapping to the ARP table
 // NeighAdd will add an IP to MAC mapping to the ARP table
 // Equivalent to: `ip neigh add ....`
 // Equivalent to: `ip neigh add ....`
 func (h *Handle) NeighAdd(neigh *Neigh) error {
 func (h *Handle) NeighAdd(neigh *Neigh) error {
-	return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
+	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
 }
 }
 
 
 // NeighSet will add or replace an IP to MAC mapping to the ARP table
 // NeighSet will add or replace an IP to MAC mapping to the ARP table
@@ -85,7 +85,7 @@ func NeighSet(neigh *Neigh) error {
 // NeighSet will add or replace an IP to MAC mapping to the ARP table
 // NeighSet will add or replace an IP to MAC mapping to the ARP table
 // Equivalent to: `ip neigh replace....`
 // Equivalent to: `ip neigh replace....`
 func (h *Handle) NeighSet(neigh *Neigh) error {
 func (h *Handle) NeighSet(neigh *Neigh) error {
-	return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
+	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_REPLACE)
 }
 }
 
 
 // NeighAppend will append an entry to FDB
 // NeighAppend will append an entry to FDB
@@ -97,7 +97,7 @@ func NeighAppend(neigh *Neigh) error {
 // NeighAppend will append an entry to FDB
 // NeighAppend will append an entry to FDB
 // Equivalent to: `bridge fdb append...`
 // Equivalent to: `bridge fdb append...`
 func (h *Handle) NeighAppend(neigh *Neigh) error {
 func (h *Handle) NeighAppend(neigh *Neigh) error {
-	return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
+	return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_APPEND)
 }
 }
 
 
 // NeighAppend will append an entry to FDB
 // NeighAppend will append an entry to FDB
@@ -109,7 +109,7 @@ func neighAdd(neigh *Neigh, mode int) error {
 // NeighAppend will append an entry to FDB
 // NeighAppend will append an entry to FDB
 // Equivalent to: `bridge fdb append...`
 // Equivalent to: `bridge fdb append...`
 func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
 func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
-	req := h.newNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_NEWNEIGH, mode|unix.NLM_F_ACK)
 	return neighHandle(neigh, req)
 	return neighHandle(neigh, req)
 }
 }
 
 
@@ -122,7 +122,7 @@ func NeighDel(neigh *Neigh) error {
 // NeighDel will delete an IP address from a link device.
 // NeighDel will delete an IP address from a link device.
 // Equivalent to: `ip addr del $addr dev $link`
 // Equivalent to: `ip addr del $addr dev $link`
 func (h *Handle) NeighDel(neigh *Neigh) error {
 func (h *Handle) NeighDel(neigh *Neigh) error {
-	req := h.newNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_DELNEIGH, unix.NLM_F_ACK)
 	return neighHandle(neigh, req)
 	return neighHandle(neigh, req)
 }
 }
 
 
@@ -160,7 +160,17 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
 		req.AddData(hwData)
 		req.AddData(hwData)
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	if neigh.Vlan != 0 {
+		vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
+		req.AddData(vlanData)
+	}
+
+	if neigh.VNI != 0 {
+		vniData := nl.NewRtAttr(NDA_VNI, nl.Uint32Attr(uint32(neigh.VNI)))
+		req.AddData(vniData)
+	}
+
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -193,7 +203,7 @@ func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
 }
 }
 
 
 func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
 func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
 	msg := Ndmsg{
 	msg := Ndmsg{
 		Family: uint8(family),
 		Family: uint8(family),
 		Index:  uint32(linkIndex),
 		Index:  uint32(linkIndex),
@@ -201,7 +211,7 @@ func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
 	}
 	}
 	req.AddData(&msg)
 	req.AddData(&msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -257,7 +267,7 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
 			// BUG: Is this a bug in the netlink library?
 			// BUG: Is this a bug in the netlink library?
 			// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
 			// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
 			// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
 			// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
-			attrLen := attr.Attr.Len - syscall.SizeofRtAttr
+			attrLen := attr.Attr.Len - unix.SizeofRtAttr
 			if attrLen == 4 && (encapType == "ipip" ||
 			if attrLen == 4 && (encapType == "ipip" ||
 				encapType == "sit" ||
 				encapType == "sit" ||
 				encapType == "gre") {
 				encapType == "gre") {
@@ -268,6 +278,10 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
 			} else {
 			} else {
 				neigh.HardwareAddr = net.HardwareAddr(attr.Value)
 				neigh.HardwareAddr = net.HardwareAddr(attr.Value)
 			}
 			}
+		case NDA_VLAN:
+			neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
+		case NDA_VNI:
+			neigh.VNI = int(native.Uint32(attr.Value[0:4]))
 		}
 		}
 	}
 	}
 
 

+ 7 - 6
vendor/github.com/vishvananda/netlink/nl/addr_linux.go

@@ -1,17 +1,18 @@
 package nl
 package nl
 
 
 import (
 import (
-	"syscall"
 	"unsafe"
 	"unsafe"
+
+	"golang.org/x/sys/unix"
 )
 )
 
 
 type IfAddrmsg struct {
 type IfAddrmsg struct {
-	syscall.IfAddrmsg
+	unix.IfAddrmsg
 }
 }
 
 
 func NewIfAddrmsg(family int) *IfAddrmsg {
 func NewIfAddrmsg(family int) *IfAddrmsg {
 	return &IfAddrmsg{
 	return &IfAddrmsg{
-		IfAddrmsg: syscall.IfAddrmsg{
+		IfAddrmsg: unix.IfAddrmsg{
 			Family: uint8(family),
 			Family: uint8(family),
 		},
 		},
 	}
 	}
@@ -35,15 +36,15 @@ func NewIfAddrmsg(family int) *IfAddrmsg {
 // SizeofIfAddrmsg     = 0x8
 // SizeofIfAddrmsg     = 0x8
 
 
 func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
 func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
-	return (*IfAddrmsg)(unsafe.Pointer(&b[0:syscall.SizeofIfAddrmsg][0]))
+	return (*IfAddrmsg)(unsafe.Pointer(&b[0:unix.SizeofIfAddrmsg][0]))
 }
 }
 
 
 func (msg *IfAddrmsg) Serialize() []byte {
 func (msg *IfAddrmsg) Serialize() []byte {
-	return (*(*[syscall.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
+	return (*(*[unix.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
 }
 }
 
 
 func (msg *IfAddrmsg) Len() int {
 func (msg *IfAddrmsg) Len() int {
-	return syscall.SizeofIfAddrmsg
+	return unix.SizeofIfAddrmsg
 }
 }
 
 
 // struct ifa_cacheinfo {
 // struct ifa_cacheinfo {

+ 17 - 25
vendor/github.com/vishvananda/netlink/nl/link_linux.go

@@ -1,35 +1,11 @@
 package nl
 package nl
 
 
 import (
 import (
-	"syscall"
 	"unsafe"
 	"unsafe"
 )
 )
 
 
 const (
 const (
 	DEFAULT_CHANGE = 0xFFFFFFFF
 	DEFAULT_CHANGE = 0xFFFFFFFF
-	// doesn't exist in syscall
-	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 (
 const (
@@ -118,6 +94,10 @@ const (
 	IFLA_MACVLAN_UNSPEC = iota
 	IFLA_MACVLAN_UNSPEC = iota
 	IFLA_MACVLAN_MODE
 	IFLA_MACVLAN_MODE
 	IFLA_MACVLAN_FLAGS
 	IFLA_MACVLAN_FLAGS
+	IFLA_MACVLAN_MACADDR_MODE
+	IFLA_MACVLAN_MACADDR
+	IFLA_MACVLAN_MACADDR_DATA
+	IFLA_MACVLAN_MACADDR_COUNT
 	IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
 	IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
 )
 )
 
 
@@ -129,6 +109,13 @@ const (
 	MACVLAN_MODE_SOURCE   = 16
 	MACVLAN_MODE_SOURCE   = 16
 )
 )
 
 
+const (
+	MACVLAN_MACADDR_ADD = iota
+	MACVLAN_MACADDR_DEL
+	MACVLAN_MACADDR_FLUSH
+	MACVLAN_MACADDR_SET
+)
+
 const (
 const (
 	IFLA_BOND_UNSPEC = iota
 	IFLA_BOND_UNSPEC = iota
 	IFLA_BOND_MODE
 	IFLA_BOND_MODE
@@ -475,7 +462,12 @@ const (
 	IFLA_IPTUN_6RD_RELAY_PREFIX
 	IFLA_IPTUN_6RD_RELAY_PREFIX
 	IFLA_IPTUN_6RD_PREFIXLEN
 	IFLA_IPTUN_6RD_PREFIXLEN
 	IFLA_IPTUN_6RD_RELAY_PREFIXLEN
 	IFLA_IPTUN_6RD_RELAY_PREFIXLEN
-	IFLA_IPTUN_MAX = IFLA_IPTUN_6RD_RELAY_PREFIXLEN
+	IFLA_IPTUN_ENCAP_TYPE
+	IFLA_IPTUN_ENCAP_FLAGS
+	IFLA_IPTUN_ENCAP_SPORT
+	IFLA_IPTUN_ENCAP_DPORT
+	IFLA_IPTUN_COLLECT_METADATA
+	IFLA_IPTUN_MAX = IFLA_IPTUN_COLLECT_METADATA
 )
 )
 
 
 const (
 const (

+ 121 - 115
vendor/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -13,18 +13,19 @@ import (
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 const (
 const (
 	// Family type definitions
 	// Family type definitions
-	FAMILY_ALL  = syscall.AF_UNSPEC
-	FAMILY_V4   = syscall.AF_INET
-	FAMILY_V6   = syscall.AF_INET6
+	FAMILY_ALL  = unix.AF_UNSPEC
+	FAMILY_V4   = unix.AF_INET
+	FAMILY_V6   = unix.AF_INET6
 	FAMILY_MPLS = AF_MPLS
 	FAMILY_MPLS = AF_MPLS
 )
 )
 
 
 // SupportedNlFamilies contains the list of netlink families this netlink package supports
 // SupportedNlFamilies contains the list of netlink families this netlink package supports
-var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM, syscall.NETLINK_NETFILTER}
+var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER}
 
 
 var nextSeqNr uint32
 var nextSeqNr uint32
 
 
@@ -77,161 +78,161 @@ type NetlinkRequestData interface {
 
 
 // IfInfomsg is related to links, but it is used for list requests as well
 // IfInfomsg is related to links, but it is used for list requests as well
 type IfInfomsg struct {
 type IfInfomsg struct {
-	syscall.IfInfomsg
+	unix.IfInfomsg
 }
 }
 
 
 // Create an IfInfomsg with family specified
 // Create an IfInfomsg with family specified
 func NewIfInfomsg(family int) *IfInfomsg {
 func NewIfInfomsg(family int) *IfInfomsg {
 	return &IfInfomsg{
 	return &IfInfomsg{
-		IfInfomsg: syscall.IfInfomsg{
+		IfInfomsg: unix.IfInfomsg{
 			Family: uint8(family),
 			Family: uint8(family),
 		},
 		},
 	}
 	}
 }
 }
 
 
 func DeserializeIfInfomsg(b []byte) *IfInfomsg {
 func DeserializeIfInfomsg(b []byte) *IfInfomsg {
-	return (*IfInfomsg)(unsafe.Pointer(&b[0:syscall.SizeofIfInfomsg][0]))
+	return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0]))
 }
 }
 
 
 func (msg *IfInfomsg) Serialize() []byte {
 func (msg *IfInfomsg) Serialize() []byte {
-	return (*(*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
+	return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
 }
 }
 
 
 func (msg *IfInfomsg) Len() int {
 func (msg *IfInfomsg) Len() int {
-	return syscall.SizeofIfInfomsg
+	return unix.SizeofIfInfomsg
 }
 }
 
 
 func (msg *IfInfomsg) EncapType() string {
 func (msg *IfInfomsg) EncapType() string {
 	switch msg.Type {
 	switch msg.Type {
 	case 0:
 	case 0:
 		return "generic"
 		return "generic"
-	case syscall.ARPHRD_ETHER:
+	case unix.ARPHRD_ETHER:
 		return "ether"
 		return "ether"
-	case syscall.ARPHRD_EETHER:
+	case unix.ARPHRD_EETHER:
 		return "eether"
 		return "eether"
-	case syscall.ARPHRD_AX25:
+	case unix.ARPHRD_AX25:
 		return "ax25"
 		return "ax25"
-	case syscall.ARPHRD_PRONET:
+	case unix.ARPHRD_PRONET:
 		return "pronet"
 		return "pronet"
-	case syscall.ARPHRD_CHAOS:
+	case unix.ARPHRD_CHAOS:
 		return "chaos"
 		return "chaos"
-	case syscall.ARPHRD_IEEE802:
+	case unix.ARPHRD_IEEE802:
 		return "ieee802"
 		return "ieee802"
-	case syscall.ARPHRD_ARCNET:
+	case unix.ARPHRD_ARCNET:
 		return "arcnet"
 		return "arcnet"
-	case syscall.ARPHRD_APPLETLK:
+	case unix.ARPHRD_APPLETLK:
 		return "atalk"
 		return "atalk"
-	case syscall.ARPHRD_DLCI:
+	case unix.ARPHRD_DLCI:
 		return "dlci"
 		return "dlci"
-	case syscall.ARPHRD_ATM:
+	case unix.ARPHRD_ATM:
 		return "atm"
 		return "atm"
-	case syscall.ARPHRD_METRICOM:
+	case unix.ARPHRD_METRICOM:
 		return "metricom"
 		return "metricom"
-	case syscall.ARPHRD_IEEE1394:
+	case unix.ARPHRD_IEEE1394:
 		return "ieee1394"
 		return "ieee1394"
-	case syscall.ARPHRD_INFINIBAND:
+	case unix.ARPHRD_INFINIBAND:
 		return "infiniband"
 		return "infiniband"
-	case syscall.ARPHRD_SLIP:
+	case unix.ARPHRD_SLIP:
 		return "slip"
 		return "slip"
-	case syscall.ARPHRD_CSLIP:
+	case unix.ARPHRD_CSLIP:
 		return "cslip"
 		return "cslip"
-	case syscall.ARPHRD_SLIP6:
+	case unix.ARPHRD_SLIP6:
 		return "slip6"
 		return "slip6"
-	case syscall.ARPHRD_CSLIP6:
+	case unix.ARPHRD_CSLIP6:
 		return "cslip6"
 		return "cslip6"
-	case syscall.ARPHRD_RSRVD:
+	case unix.ARPHRD_RSRVD:
 		return "rsrvd"
 		return "rsrvd"
-	case syscall.ARPHRD_ADAPT:
+	case unix.ARPHRD_ADAPT:
 		return "adapt"
 		return "adapt"
-	case syscall.ARPHRD_ROSE:
+	case unix.ARPHRD_ROSE:
 		return "rose"
 		return "rose"
-	case syscall.ARPHRD_X25:
+	case unix.ARPHRD_X25:
 		return "x25"
 		return "x25"
-	case syscall.ARPHRD_HWX25:
+	case unix.ARPHRD_HWX25:
 		return "hwx25"
 		return "hwx25"
-	case syscall.ARPHRD_PPP:
+	case unix.ARPHRD_PPP:
 		return "ppp"
 		return "ppp"
-	case syscall.ARPHRD_HDLC:
+	case unix.ARPHRD_HDLC:
 		return "hdlc"
 		return "hdlc"
-	case syscall.ARPHRD_LAPB:
+	case unix.ARPHRD_LAPB:
 		return "lapb"
 		return "lapb"
-	case syscall.ARPHRD_DDCMP:
+	case unix.ARPHRD_DDCMP:
 		return "ddcmp"
 		return "ddcmp"
-	case syscall.ARPHRD_RAWHDLC:
+	case unix.ARPHRD_RAWHDLC:
 		return "rawhdlc"
 		return "rawhdlc"
-	case syscall.ARPHRD_TUNNEL:
+	case unix.ARPHRD_TUNNEL:
 		return "ipip"
 		return "ipip"
-	case syscall.ARPHRD_TUNNEL6:
+	case unix.ARPHRD_TUNNEL6:
 		return "tunnel6"
 		return "tunnel6"
-	case syscall.ARPHRD_FRAD:
+	case unix.ARPHRD_FRAD:
 		return "frad"
 		return "frad"
-	case syscall.ARPHRD_SKIP:
+	case unix.ARPHRD_SKIP:
 		return "skip"
 		return "skip"
-	case syscall.ARPHRD_LOOPBACK:
+	case unix.ARPHRD_LOOPBACK:
 		return "loopback"
 		return "loopback"
-	case syscall.ARPHRD_LOCALTLK:
+	case unix.ARPHRD_LOCALTLK:
 		return "ltalk"
 		return "ltalk"
-	case syscall.ARPHRD_FDDI:
+	case unix.ARPHRD_FDDI:
 		return "fddi"
 		return "fddi"
-	case syscall.ARPHRD_BIF:
+	case unix.ARPHRD_BIF:
 		return "bif"
 		return "bif"
-	case syscall.ARPHRD_SIT:
+	case unix.ARPHRD_SIT:
 		return "sit"
 		return "sit"
-	case syscall.ARPHRD_IPDDP:
+	case unix.ARPHRD_IPDDP:
 		return "ip/ddp"
 		return "ip/ddp"
-	case syscall.ARPHRD_IPGRE:
+	case unix.ARPHRD_IPGRE:
 		return "gre"
 		return "gre"
-	case syscall.ARPHRD_PIMREG:
+	case unix.ARPHRD_PIMREG:
 		return "pimreg"
 		return "pimreg"
-	case syscall.ARPHRD_HIPPI:
+	case unix.ARPHRD_HIPPI:
 		return "hippi"
 		return "hippi"
-	case syscall.ARPHRD_ASH:
+	case unix.ARPHRD_ASH:
 		return "ash"
 		return "ash"
-	case syscall.ARPHRD_ECONET:
+	case unix.ARPHRD_ECONET:
 		return "econet"
 		return "econet"
-	case syscall.ARPHRD_IRDA:
+	case unix.ARPHRD_IRDA:
 		return "irda"
 		return "irda"
-	case syscall.ARPHRD_FCPP:
+	case unix.ARPHRD_FCPP:
 		return "fcpp"
 		return "fcpp"
-	case syscall.ARPHRD_FCAL:
+	case unix.ARPHRD_FCAL:
 		return "fcal"
 		return "fcal"
-	case syscall.ARPHRD_FCPL:
+	case unix.ARPHRD_FCPL:
 		return "fcpl"
 		return "fcpl"
-	case syscall.ARPHRD_FCFABRIC:
+	case unix.ARPHRD_FCFABRIC:
 		return "fcfb0"
 		return "fcfb0"
-	case syscall.ARPHRD_FCFABRIC + 1:
+	case unix.ARPHRD_FCFABRIC + 1:
 		return "fcfb1"
 		return "fcfb1"
-	case syscall.ARPHRD_FCFABRIC + 2:
+	case unix.ARPHRD_FCFABRIC + 2:
 		return "fcfb2"
 		return "fcfb2"
-	case syscall.ARPHRD_FCFABRIC + 3:
+	case unix.ARPHRD_FCFABRIC + 3:
 		return "fcfb3"
 		return "fcfb3"
-	case syscall.ARPHRD_FCFABRIC + 4:
+	case unix.ARPHRD_FCFABRIC + 4:
 		return "fcfb4"
 		return "fcfb4"
-	case syscall.ARPHRD_FCFABRIC + 5:
+	case unix.ARPHRD_FCFABRIC + 5:
 		return "fcfb5"
 		return "fcfb5"
-	case syscall.ARPHRD_FCFABRIC + 6:
+	case unix.ARPHRD_FCFABRIC + 6:
 		return "fcfb6"
 		return "fcfb6"
-	case syscall.ARPHRD_FCFABRIC + 7:
+	case unix.ARPHRD_FCFABRIC + 7:
 		return "fcfb7"
 		return "fcfb7"
-	case syscall.ARPHRD_FCFABRIC + 8:
+	case unix.ARPHRD_FCFABRIC + 8:
 		return "fcfb8"
 		return "fcfb8"
-	case syscall.ARPHRD_FCFABRIC + 9:
+	case unix.ARPHRD_FCFABRIC + 9:
 		return "fcfb9"
 		return "fcfb9"
-	case syscall.ARPHRD_FCFABRIC + 10:
+	case unix.ARPHRD_FCFABRIC + 10:
 		return "fcfb10"
 		return "fcfb10"
-	case syscall.ARPHRD_FCFABRIC + 11:
+	case unix.ARPHRD_FCFABRIC + 11:
 		return "fcfb11"
 		return "fcfb11"
-	case syscall.ARPHRD_FCFABRIC + 12:
+	case unix.ARPHRD_FCFABRIC + 12:
 		return "fcfb12"
 		return "fcfb12"
-	case syscall.ARPHRD_IEEE802_TR:
+	case unix.ARPHRD_IEEE802_TR:
 		return "tr"
 		return "tr"
-	case syscall.ARPHRD_IEEE80211:
+	case unix.ARPHRD_IEEE80211:
 		return "ieee802.11"
 		return "ieee802.11"
-	case syscall.ARPHRD_IEEE80211_PRISM:
+	case unix.ARPHRD_IEEE80211_PRISM:
 		return "ieee802.11/prism"
 		return "ieee802.11/prism"
-	case syscall.ARPHRD_IEEE80211_RADIOTAP:
+	case unix.ARPHRD_IEEE80211_RADIOTAP:
 		return "ieee802.11/radiotap"
 		return "ieee802.11/radiotap"
-	case syscall.ARPHRD_IEEE802154:
+	case unix.ARPHRD_IEEE802154:
 		return "ieee802.15.4"
 		return "ieee802.15.4"
 
 
 	case 65534:
 	case 65534:
@@ -243,7 +244,7 @@ func (msg *IfInfomsg) EncapType() string {
 }
 }
 
 
 func rtaAlignOf(attrlen int) int {
 func rtaAlignOf(attrlen int) int {
-	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
+	return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1)
 }
 }
 
 
 func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
 func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
@@ -254,7 +255,7 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
 
 
 // Extend RtAttr to handle data and children
 // Extend RtAttr to handle data and children
 type RtAttr struct {
 type RtAttr struct {
-	syscall.RtAttr
+	unix.RtAttr
 	Data     []byte
 	Data     []byte
 	children []NetlinkRequestData
 	children []NetlinkRequestData
 }
 }
@@ -262,7 +263,7 @@ type RtAttr struct {
 // Create a new Extended RtAttr object
 // Create a new Extended RtAttr object
 func NewRtAttr(attrType int, data []byte) *RtAttr {
 func NewRtAttr(attrType int, data []byte) *RtAttr {
 	return &RtAttr{
 	return &RtAttr{
-		RtAttr: syscall.RtAttr{
+		RtAttr: unix.RtAttr{
 			Type: uint16(attrType),
 			Type: uint16(attrType),
 		},
 		},
 		children: []NetlinkRequestData{},
 		children: []NetlinkRequestData{},
@@ -277,16 +278,21 @@ func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
 	return attr
 	return attr
 }
 }
 
 
+// AddChild adds an existing RtAttr as a child.
+func (a *RtAttr) AddChild(attr *RtAttr) {
+	a.children = append(a.children, attr)
+}
+
 func (a *RtAttr) Len() int {
 func (a *RtAttr) Len() int {
 	if len(a.children) == 0 {
 	if len(a.children) == 0 {
-		return (syscall.SizeofRtAttr + len(a.Data))
+		return (unix.SizeofRtAttr + len(a.Data))
 	}
 	}
 
 
 	l := 0
 	l := 0
 	for _, child := range a.children {
 	for _, child := range a.children {
 		l += rtaAlignOf(child.Len())
 		l += rtaAlignOf(child.Len())
 	}
 	}
-	l += syscall.SizeofRtAttr
+	l += unix.SizeofRtAttr
 	return rtaAlignOf(l + len(a.Data))
 	return rtaAlignOf(l + len(a.Data))
 }
 }
 
 
@@ -319,7 +325,7 @@ func (a *RtAttr) Serialize() []byte {
 }
 }
 
 
 type NetlinkRequest struct {
 type NetlinkRequest struct {
-	syscall.NlMsghdr
+	unix.NlMsghdr
 	Data    []NetlinkRequestData
 	Data    []NetlinkRequestData
 	RawData []byte
 	RawData []byte
 	Sockets map[int]*SocketHandle
 	Sockets map[int]*SocketHandle
@@ -327,7 +333,7 @@ type NetlinkRequest struct {
 
 
 // Serialize the Netlink Request into a byte array
 // Serialize the Netlink Request into a byte array
 func (req *NetlinkRequest) Serialize() []byte {
 func (req *NetlinkRequest) Serialize() []byte {
-	length := syscall.SizeofNlMsghdr
+	length := unix.SizeofNlMsghdr
 	dataBytes := make([][]byte, len(req.Data))
 	dataBytes := make([][]byte, len(req.Data))
 	for i, data := range req.Data {
 	for i, data := range req.Data {
 		dataBytes[i] = data.Serialize()
 		dataBytes[i] = data.Serialize()
@@ -337,8 +343,8 @@ func (req *NetlinkRequest) Serialize() []byte {
 
 
 	req.Len = uint32(length)
 	req.Len = uint32(length)
 	b := make([]byte, length)
 	b := make([]byte, length)
-	hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
-	next := syscall.SizeofNlMsghdr
+	hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
+	next := unix.SizeofNlMsghdr
 	copy(b[0:next], hdr)
 	copy(b[0:next], hdr)
 	for _, data := range dataBytes {
 	for _, data := range dataBytes {
 		for _, dataByte := range data {
 		for _, dataByte := range data {
@@ -421,10 +427,10 @@ done:
 			if m.Header.Pid != pid {
 			if m.Header.Pid != pid {
 				return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
 				return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
 			}
 			}
-			if m.Header.Type == syscall.NLMSG_DONE {
+			if m.Header.Type == unix.NLMSG_DONE {
 				break done
 				break done
 			}
 			}
-			if m.Header.Type == syscall.NLMSG_ERROR {
+			if m.Header.Type == unix.NLMSG_ERROR {
 				native := NativeEndian()
 				native := NativeEndian()
 				error := int32(native.Uint32(m.Data[0:4]))
 				error := int32(native.Uint32(m.Data[0:4]))
 				if error == 0 {
 				if error == 0 {
@@ -436,7 +442,7 @@ done:
 				continue
 				continue
 			}
 			}
 			res = append(res, m.Data)
 			res = append(res, m.Data)
-			if m.Header.Flags&syscall.NLM_F_MULTI == 0 {
+			if m.Header.Flags&unix.NLM_F_MULTI == 0 {
 				break done
 				break done
 			}
 			}
 		}
 		}
@@ -449,10 +455,10 @@ done:
 // the message is serialized
 // the message is serialized
 func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
 func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
 	return &NetlinkRequest{
 	return &NetlinkRequest{
-		NlMsghdr: syscall.NlMsghdr{
-			Len:   uint32(syscall.SizeofNlMsghdr),
+		NlMsghdr: unix.NlMsghdr{
+			Len:   uint32(unix.SizeofNlMsghdr),
 			Type:  uint16(proto),
 			Type:  uint16(proto),
-			Flags: syscall.NLM_F_REQUEST | uint16(flags),
+			Flags: unix.NLM_F_REQUEST | uint16(flags),
 			Seq:   atomic.AddUint32(&nextSeqNr, 1),
 			Seq:   atomic.AddUint32(&nextSeqNr, 1),
 		},
 		},
 	}
 	}
@@ -460,21 +466,21 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
 
 
 type NetlinkSocket struct {
 type NetlinkSocket struct {
 	fd  int32
 	fd  int32
-	lsa syscall.SockaddrNetlink
+	lsa unix.SockaddrNetlink
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
 func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
 func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
-	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, protocol)
+	fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	s := &NetlinkSocket{
 	s := &NetlinkSocket{
 		fd: int32(fd),
 		fd: int32(fd),
 	}
 	}
-	s.lsa.Family = syscall.AF_NETLINK
-	if err := syscall.Bind(fd, &s.lsa); err != nil {
-		syscall.Close(fd)
+	s.lsa.Family = unix.AF_NETLINK
+	if err := unix.Bind(fd, &s.lsa); err != nil {
+		unix.Close(fd)
 		return nil, err
 		return nil, err
 	}
 	}
 
 
@@ -551,21 +557,21 @@ func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
 // Returns the netlink socket on which Receive() method can be called
 // Returns the netlink socket on which Receive() method can be called
 // to retrieve the messages from the kernel.
 // to retrieve the messages from the kernel.
 func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
-	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
+	fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	s := &NetlinkSocket{
 	s := &NetlinkSocket{
 		fd: int32(fd),
 		fd: int32(fd),
 	}
 	}
-	s.lsa.Family = syscall.AF_NETLINK
+	s.lsa.Family = unix.AF_NETLINK
 
 
 	for _, g := range groups {
 	for _, g := range groups {
 		s.lsa.Groups |= (1 << (g - 1))
 		s.lsa.Groups |= (1 << (g - 1))
 	}
 	}
 
 
-	if err := syscall.Bind(fd, &s.lsa); err != nil {
-		syscall.Close(fd)
+	if err := unix.Bind(fd, &s.lsa); err != nil {
+		unix.Close(fd)
 		return nil, err
 		return nil, err
 	}
 	}
 
 
@@ -586,7 +592,7 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
 
 
 func (s *NetlinkSocket) Close() {
 func (s *NetlinkSocket) Close() {
 	fd := int(atomic.SwapInt32(&s.fd, -1))
 	fd := int(atomic.SwapInt32(&s.fd, -1))
-	syscall.Close(fd)
+	unix.Close(fd)
 }
 }
 
 
 func (s *NetlinkSocket) GetFd() int {
 func (s *NetlinkSocket) GetFd() int {
@@ -598,7 +604,7 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
 	if fd < 0 {
 	if fd < 0 {
 		return fmt.Errorf("Send called on a closed socket")
 		return fmt.Errorf("Send called on a closed socket")
 	}
 	}
-	if err := syscall.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
+	if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
 		return err
 		return err
 	}
 	}
 	return nil
 	return nil
@@ -609,12 +615,12 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
 	if fd < 0 {
 	if fd < 0 {
 		return nil, fmt.Errorf("Receive called on a closed socket")
 		return nil, fmt.Errorf("Receive called on a closed socket")
 	}
 	}
-	rb := make([]byte, syscall.Getpagesize())
-	nr, _, err := syscall.Recvfrom(fd, rb, 0)
+	rb := make([]byte, unix.Getpagesize())
+	nr, _, err := unix.Recvfrom(fd, rb, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	if nr < syscall.NLMSG_HDRLEN {
+	if nr < unix.NLMSG_HDRLEN {
 		return nil, fmt.Errorf("Got short response from netlink")
 		return nil, fmt.Errorf("Got short response from netlink")
 	}
 	}
 	rb = rb[:nr]
 	rb = rb[:nr]
@@ -622,27 +628,27 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
 }
 }
 
 
 // SetSendTimeout allows to set a send timeout on the socket
 // SetSendTimeout allows to set a send timeout on the socket
-func (s *NetlinkSocket) SetSendTimeout(timeout *syscall.Timeval) error {
+func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error {
 	// Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine
 	// Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine
 	// remains stuck on a send on a closed fd
 	// remains stuck on a send on a closed fd
-	return syscall.SetsockoptTimeval(int(s.fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, timeout)
+	return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout)
 }
 }
 
 
 // SetReceiveTimeout allows to set a receive timeout on the socket
 // SetReceiveTimeout allows to set a receive timeout on the socket
-func (s *NetlinkSocket) SetReceiveTimeout(timeout *syscall.Timeval) error {
+func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
 	// Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine
 	// Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine
 	// remains stuck on a recvmsg on a closed fd
 	// remains stuck on a recvmsg on a closed fd
-	return syscall.SetsockoptTimeval(int(s.fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, timeout)
+	return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
 }
 }
 
 
 func (s *NetlinkSocket) GetPid() (uint32, error) {
 func (s *NetlinkSocket) GetPid() (uint32, error) {
 	fd := int(atomic.LoadInt32(&s.fd))
 	fd := int(atomic.LoadInt32(&s.fd))
-	lsa, err := syscall.Getsockname(fd)
+	lsa, err := unix.Getsockname(fd)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
 	switch v := lsa.(type) {
 	switch v := lsa.(type) {
-	case *syscall.SockaddrNetlink:
+	case *unix.SockaddrNetlink:
 		return v.Pid, nil
 		return v.Pid, nil
 	}
 	}
 	return 0, fmt.Errorf("Wrong socket type")
 	return 0, fmt.Errorf("Wrong socket type")
@@ -697,24 +703,24 @@ func Uint64Attr(v uint64) []byte {
 
 
 func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
 func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
 	var attrs []syscall.NetlinkRouteAttr
 	var attrs []syscall.NetlinkRouteAttr
-	for len(b) >= syscall.SizeofRtAttr {
+	for len(b) >= unix.SizeofRtAttr {
 		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
 		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-		ra := syscall.NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
+		ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]}
 		attrs = append(attrs, ra)
 		attrs = append(attrs, ra)
 		b = b[alen:]
 		b = b[alen:]
 	}
 	}
 	return attrs, nil
 	return attrs, nil
 }
 }
 
 
-func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
-	a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
-	if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
-		return nil, nil, 0, syscall.EINVAL
+func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
+	a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
+	if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {
+		return nil, nil, 0, unix.EINVAL
 	}
 	}
-	return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
+	return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
 }
 }
 
 
 // SocketHandle contains the netlink socket and the associated
 // SocketHandle contains the netlink socket and the associated

+ 20 - 19
vendor/github.com/vishvananda/netlink/nl/route_linux.go

@@ -1,65 +1,66 @@
 package nl
 package nl
 
 
 import (
 import (
-	"syscall"
 	"unsafe"
 	"unsafe"
+
+	"golang.org/x/sys/unix"
 )
 )
 
 
 type RtMsg struct {
 type RtMsg struct {
-	syscall.RtMsg
+	unix.RtMsg
 }
 }
 
 
 func NewRtMsg() *RtMsg {
 func NewRtMsg() *RtMsg {
 	return &RtMsg{
 	return &RtMsg{
-		RtMsg: syscall.RtMsg{
-			Table:    syscall.RT_TABLE_MAIN,
-			Scope:    syscall.RT_SCOPE_UNIVERSE,
-			Protocol: syscall.RTPROT_BOOT,
-			Type:     syscall.RTN_UNICAST,
+		RtMsg: unix.RtMsg{
+			Table:    unix.RT_TABLE_MAIN,
+			Scope:    unix.RT_SCOPE_UNIVERSE,
+			Protocol: unix.RTPROT_BOOT,
+			Type:     unix.RTN_UNICAST,
 		},
 		},
 	}
 	}
 }
 }
 
 
 func NewRtDelMsg() *RtMsg {
 func NewRtDelMsg() *RtMsg {
 	return &RtMsg{
 	return &RtMsg{
-		RtMsg: syscall.RtMsg{
-			Table: syscall.RT_TABLE_MAIN,
-			Scope: syscall.RT_SCOPE_NOWHERE,
+		RtMsg: unix.RtMsg{
+			Table: unix.RT_TABLE_MAIN,
+			Scope: unix.RT_SCOPE_NOWHERE,
 		},
 		},
 	}
 	}
 }
 }
 
 
 func (msg *RtMsg) Len() int {
 func (msg *RtMsg) Len() int {
-	return syscall.SizeofRtMsg
+	return unix.SizeofRtMsg
 }
 }
 
 
 func DeserializeRtMsg(b []byte) *RtMsg {
 func DeserializeRtMsg(b []byte) *RtMsg {
-	return (*RtMsg)(unsafe.Pointer(&b[0:syscall.SizeofRtMsg][0]))
+	return (*RtMsg)(unsafe.Pointer(&b[0:unix.SizeofRtMsg][0]))
 }
 }
 
 
 func (msg *RtMsg) Serialize() []byte {
 func (msg *RtMsg) Serialize() []byte {
-	return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
+	return (*(*[unix.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
 }
 }
 
 
 type RtNexthop struct {
 type RtNexthop struct {
-	syscall.RtNexthop
+	unix.RtNexthop
 	Children []NetlinkRequestData
 	Children []NetlinkRequestData
 }
 }
 
 
 func DeserializeRtNexthop(b []byte) *RtNexthop {
 func DeserializeRtNexthop(b []byte) *RtNexthop {
-	return (*RtNexthop)(unsafe.Pointer(&b[0:syscall.SizeofRtNexthop][0]))
+	return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))
 }
 }
 
 
 func (msg *RtNexthop) Len() int {
 func (msg *RtNexthop) Len() int {
 	if len(msg.Children) == 0 {
 	if len(msg.Children) == 0 {
-		return syscall.SizeofRtNexthop
+		return unix.SizeofRtNexthop
 	}
 	}
 
 
 	l := 0
 	l := 0
 	for _, child := range msg.Children {
 	for _, child := range msg.Children {
 		l += rtaAlignOf(child.Len())
 		l += rtaAlignOf(child.Len())
 	}
 	}
-	l += syscall.SizeofRtNexthop
+	l += unix.SizeofRtNexthop
 	return rtaAlignOf(l)
 	return rtaAlignOf(l)
 }
 }
 
 
@@ -67,8 +68,8 @@ func (msg *RtNexthop) Serialize() []byte {
 	length := msg.Len()
 	length := msg.Len()
 	msg.RtNexthop.Len = uint16(length)
 	msg.RtNexthop.Len = uint16(length)
 	buf := make([]byte, length)
 	buf := make([]byte, length)
-	copy(buf, (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:])
-	next := rtaAlignOf(syscall.SizeofRtNexthop)
+	copy(buf, (*(*[unix.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:])
+	next := rtaAlignOf(unix.SizeofRtNexthop)
 	if len(msg.Children) > 0 {
 	if len(msg.Children) > 0 {
 		for _, child := range msg.Children {
 		for _, child := range msg.Children {
 			childBuf := child.Serialize()
 			childBuf := child.Serialize()

+ 111 - 0
vendor/github.com/vishvananda/netlink/nl/seg6_linux.go

@@ -0,0 +1,111 @@
+package nl
+
+import (
+	"errors"
+	"fmt"
+	"net"
+)
+
+type IPv6SrHdr struct {
+	nextHdr      uint8
+	hdrLen       uint8
+	routingType  uint8
+	segmentsLeft uint8
+	firstSegment uint8
+	flags        uint8
+	reserved     uint16
+
+	Segments []net.IP
+}
+
+func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool {
+	if len(s1.Segments) != len(s2.Segments) {
+		return false
+	}
+	for i := range s1.Segments {
+		if s1.Segments[i].Equal(s2.Segments[i]) != true {
+			return false
+		}
+	}
+	return s1.nextHdr == s2.nextHdr &&
+		s1.hdrLen == s2.hdrLen &&
+		s1.routingType == s2.routingType &&
+		s1.segmentsLeft == s2.segmentsLeft &&
+		s1.firstSegment == s2.firstSegment &&
+		s1.flags == s2.flags
+	// reserved doesn't need to be identical.
+}
+
+// seg6 encap mode
+const (
+	SEG6_IPTUN_MODE_INLINE = iota
+	SEG6_IPTUN_MODE_ENCAP
+)
+
+// number of nested RTATTR
+// from include/uapi/linux/seg6_iptunnel.h
+const (
+	SEG6_IPTUNNEL_UNSPEC = iota
+	SEG6_IPTUNNEL_SRH
+	__SEG6_IPTUNNEL_MAX
+)
+const (
+	SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1
+)
+
+func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) {
+	nsegs := len(segments) // nsegs: number of segments
+	if nsegs == 0 {
+		return nil, errors.New("EncodeSEG6Encap: No Segment in srh")
+	}
+	b := make([]byte, 12, 12+len(segments)*16)
+	native := NativeEndian()
+	native.PutUint32(b, uint32(mode))
+	b[4] = 0                      // srh.nextHdr (0 when calling netlink)
+	b[5] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit)
+	b[6] = IPV6_SRCRT_TYPE_4      // srh.routingType (assigned by IANA)
+	b[7] = uint8(nsegs - 1)       // srh.segmentsLeft
+	b[8] = uint8(nsegs - 1)       // srh.firstSegment
+	b[9] = 0                      // srh.flags (SR6_FLAG1_HMAC for srh_hmac)
+	// srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07
+	native.PutUint16(b[10:], 0) // srh.reserved
+	for _, netIP := range segments {
+		b = append(b, netIP...) // srh.Segments
+	}
+	return b, nil
+}
+
+func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
+	native := NativeEndian()
+	mode := int(native.Uint32(buf))
+	srh := IPv6SrHdr{
+		nextHdr:      buf[4],
+		hdrLen:       buf[5],
+		routingType:  buf[6],
+		segmentsLeft: buf[7],
+		firstSegment: buf[8],
+		flags:        buf[9],
+		reserved:     native.Uint16(buf[10:12]),
+	}
+	buf = buf[12:]
+	if len(buf)%16 != 0 {
+		err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf))
+		return mode, nil, err
+	}
+	for len(buf) > 0 {
+		srh.Segments = append(srh.Segments, net.IP(buf[:16]))
+		buf = buf[16:]
+	}
+	return mode, srh.Segments, nil
+}
+
+// Helper functions
+func SEG6EncapModeString(mode int) string {
+	switch mode {
+	case SEG6_IPTUN_MODE_INLINE:
+		return "inline"
+	case SEG6_IPTUN_MODE_ENCAP:
+		return "encap"
+	}
+	return "unknown"
+}

+ 10 - 0
vendor/github.com/vishvananda/netlink/nl/syscall.go

@@ -65,4 +65,14 @@ const (
 	LWTUNNEL_ENCAP_IP
 	LWTUNNEL_ENCAP_IP
 	LWTUNNEL_ENCAP_ILA
 	LWTUNNEL_ENCAP_ILA
 	LWTUNNEL_ENCAP_IP6
 	LWTUNNEL_ENCAP_IP6
+	LWTUNNEL_ENCAP_SEG6
+	LWTUNNEL_ENCAP_BPF
+)
+
+// routing header types
+const (
+	IPV6_SRCRT_STRICT = 0x01 // Deprecated; will be removed
+	IPV6_SRCRT_TYPE_0 = 0    // Deprecated; will be removed
+	IPV6_SRCRT_TYPE_2 = 2    // IPv6 type 2 Routing Header
+	IPV6_SRCRT_TYPE_4 = 4    // Segment Routing with IPv6
 )
 )

+ 35 - 0
vendor/github.com/vishvananda/netlink/nl/tc_linux.go

@@ -673,3 +673,38 @@ const (
 	TCA_FW_MASK
 	TCA_FW_MASK
 	TCA_FW_MAX = TCA_FW_MASK
 	TCA_FW_MAX = TCA_FW_MASK
 )
 )
+
+const (
+	TCA_MATCHALL_UNSPEC = iota
+	TCA_MATCHALL_CLASSID
+	TCA_MATCHALL_ACT
+	TCA_MATCHALL_FLAGS
+)
+
+const (
+	TCA_FQ_UNSPEC             = iota
+	TCA_FQ_PLIMIT             // limit of total number of packets in queue
+	TCA_FQ_FLOW_PLIMIT        // limit of packets per flow
+	TCA_FQ_QUANTUM            // RR quantum
+	TCA_FQ_INITIAL_QUANTUM    // RR quantum for new flow
+	TCA_FQ_RATE_ENABLE        // enable/disable rate limiting
+	TCA_FQ_FLOW_DEFAULT_RATE  // obsolete do not use
+	TCA_FQ_FLOW_MAX_RATE      // per flow max rate
+	TCA_FQ_BUCKETS_LOG        // log2(number of buckets)
+	TCA_FQ_FLOW_REFILL_DELAY  // flow credit refill delay in usec
+	TCA_FQ_ORPHAN_MASK        // mask applied to orphaned skb hashes
+	TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate
+)
+
+const (
+	TCA_FQ_CODEL_UNSPEC = iota
+	TCA_FQ_CODEL_TARGET
+	TCA_FQ_CODEL_LIMIT
+	TCA_FQ_CODEL_INTERVAL
+	TCA_FQ_CODEL_ECN
+	TCA_FQ_CODEL_FLOWS
+	TCA_FQ_CODEL_QUANTUM
+	TCA_FQ_CODEL_CE_THRESHOLD
+	TCA_FQ_CODEL_DROP_BATCH_SIZE
+	TCA_FQ_CODEL_MEMORY_LIMIT
+)

+ 5 - 4
vendor/github.com/vishvananda/netlink/protinfo_linux.go

@@ -5,6 +5,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 func LinkGetProtinfo(link Link) (Protinfo, error) {
 func LinkGetProtinfo(link Link) (Protinfo, error) {
@@ -15,10 +16,10 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
 	base := link.Attrs()
 	base := link.Attrs()
 	h.ensureIndex(base)
 	h.ensureIndex(base)
 	var pi Protinfo
 	var pi Protinfo
-	req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
-	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
+	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
+	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
 	req.AddData(msg)
 	req.AddData(msg)
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	if err != nil {
 	if err != nil {
 		return pi, err
 		return pi, err
 	}
 	}
@@ -33,7 +34,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
 			return pi, err
 			return pi, err
 		}
 		}
 		for _, attr := range attrs {
 		for _, attr := range attrs {
-			if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED {
+			if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED {
 				continue
 				continue
 			}
 			}
 			infos, err := nl.ParseRouteAttr(attr.Value)
 			infos, err := nl.ParseRouteAttr(attr.Value)

+ 60 - 0
vendor/github.com/vishvananda/netlink/qdisc.go

@@ -230,3 +230,63 @@ func (qdisc *GenericQdisc) Attrs() *QdiscAttrs {
 func (qdisc *GenericQdisc) Type() string {
 func (qdisc *GenericQdisc) Type() string {
 	return qdisc.QdiscType
 	return qdisc.QdiscType
 }
 }
+
+// Fq is a classless packet scheduler meant to be mostly used for locally generated traffic.
+type Fq struct {
+	QdiscAttrs
+	PacketLimit     uint32
+	FlowPacketLimit uint32
+	// In bytes
+	Quantum        uint32
+	InitialQuantum uint32
+	// called RateEnable under the hood
+	Pacing          uint32
+	FlowDefaultRate uint32
+	FlowMaxRate     uint32
+	// called BucketsLog under the hood
+	Buckets          uint32
+	FlowRefillDelay  uint32
+	LowRateThreshold uint32
+}
+
+func NewFq(attrs QdiscAttrs) *Fq {
+	return &Fq{
+		QdiscAttrs: attrs,
+		Pacing:     1,
+	}
+}
+
+func (qdisc *Fq) Attrs() *QdiscAttrs {
+	return &qdisc.QdiscAttrs
+}
+
+func (qdisc *Fq) Type() string {
+	return "fq"
+}
+
+// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme.
+type FqCodel struct {
+	QdiscAttrs
+	Target   uint32
+	Limit    uint32
+	Interval uint32
+	ECN      uint32
+	Flows    uint32
+	Quantum  uint32
+	// There are some more attributes here, but support for them seems not ubiquitous
+}
+
+func NewFqCodel(attrs QdiscAttrs) *FqCodel {
+	return &FqCodel{
+		QdiscAttrs: attrs,
+		ECN:        1,
+	}
+}
+
+func (qdisc *FqCodel) Attrs() *QdiscAttrs {
+	return &qdisc.QdiscAttrs
+}
+
+func (qdisc *FqCodel) Type() string {
+	return "fq_codel"
+}

+ 129 - 11
vendor/github.com/vishvananda/netlink/qdisc_linux.go

@@ -8,6 +8,7 @@ import (
 	"syscall"
 	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // NOTE function is here because it uses other linux functions
 // NOTE function is here because it uses other linux functions
@@ -84,7 +85,7 @@ func QdiscDel(qdisc Qdisc) error {
 // QdiscDel will delete a qdisc from the system.
 // QdiscDel will delete a qdisc from the system.
 // Equivalent to: `tc qdisc del $qdisc`
 // Equivalent to: `tc qdisc del $qdisc`
 func (h *Handle) QdiscDel(qdisc Qdisc) error {
 func (h *Handle) QdiscDel(qdisc Qdisc) error {
-	return h.qdiscModify(syscall.RTM_DELQDISC, 0, qdisc)
+	return h.qdiscModify(unix.RTM_DELQDISC, 0, qdisc)
 }
 }
 
 
 // QdiscChange will change a qdisc in place
 // QdiscChange will change a qdisc in place
@@ -98,7 +99,7 @@ func QdiscChange(qdisc Qdisc) error {
 // Equivalent to: `tc qdisc change $qdisc`
 // Equivalent to: `tc qdisc change $qdisc`
 // The parent and handle MUST NOT be changed.
 // The parent and handle MUST NOT be changed.
 func (h *Handle) QdiscChange(qdisc Qdisc) error {
 func (h *Handle) QdiscChange(qdisc Qdisc) error {
-	return h.qdiscModify(syscall.RTM_NEWQDISC, 0, qdisc)
+	return h.qdiscModify(unix.RTM_NEWQDISC, 0, qdisc)
 }
 }
 
 
 // QdiscReplace will replace a qdisc to the system.
 // QdiscReplace will replace a qdisc to the system.
@@ -113,8 +114,8 @@ func QdiscReplace(qdisc Qdisc) error {
 // The handle MUST change.
 // The handle MUST change.
 func (h *Handle) QdiscReplace(qdisc Qdisc) error {
 func (h *Handle) QdiscReplace(qdisc Qdisc) error {
 	return h.qdiscModify(
 	return h.qdiscModify(
-		syscall.RTM_NEWQDISC,
-		syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE,
+		unix.RTM_NEWQDISC,
+		unix.NLM_F_CREATE|unix.NLM_F_REPLACE,
 		qdisc)
 		qdisc)
 }
 }
 
 
@@ -128,13 +129,13 @@ func QdiscAdd(qdisc Qdisc) error {
 // Equivalent to: `tc qdisc add $qdisc`
 // Equivalent to: `tc qdisc add $qdisc`
 func (h *Handle) QdiscAdd(qdisc Qdisc) error {
 func (h *Handle) QdiscAdd(qdisc Qdisc) error {
 	return h.qdiscModify(
 	return h.qdiscModify(
-		syscall.RTM_NEWQDISC,
-		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
+		unix.RTM_NEWQDISC,
+		unix.NLM_F_CREATE|unix.NLM_F_EXCL,
 		qdisc)
 		qdisc)
 }
 }
 
 
 func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
 func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
-	req := h.newNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
 	base := qdisc.Attrs()
 	base := qdisc.Attrs()
 	msg := &nl.TcMsg{
 	msg := &nl.TcMsg{
 		Family:  nl.FAMILY_ALL,
 		Family:  nl.FAMILY_ALL,
@@ -145,13 +146,13 @@ func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
 	req.AddData(msg)
 	req.AddData(msg)
 
 
 	// When deleting don't bother building the rest of the netlink payload
 	// When deleting don't bother building the rest of the netlink payload
-	if cmd != syscall.RTM_DELQDISC {
+	if cmd != unix.RTM_DELQDISC {
 		if err := qdiscPayload(req, qdisc); err != nil {
 		if err := qdiscPayload(req, qdisc); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -231,6 +232,48 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
 		if qdisc.Attrs().Parent != HANDLE_INGRESS {
 		if qdisc.Attrs().Parent != HANDLE_INGRESS {
 			return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
 			return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
 		}
 		}
+	case *FqCodel:
+		nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN))))
+		if qdisc.Limit > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit))))
+		}
+		if qdisc.Interval > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval))))
+		}
+		if qdisc.Flows > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows))))
+		}
+		if qdisc.Quantum > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
+		}
+
+	case *Fq:
+		nl.NewRtAttrChild(options, nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
+
+		if qdisc.Buckets > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
+		}
+		if qdisc.LowRateThreshold > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
+		}
+		if qdisc.Quantum > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
+		}
+		if qdisc.InitialQuantum > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum))))
+		}
+		if qdisc.FlowRefillDelay > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay))))
+		}
+		if qdisc.FlowPacketLimit > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit))))
+		}
+		if qdisc.FlowMaxRate > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate))))
+		}
+		if qdisc.FlowDefaultRate > 0 {
+			nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
+		}
 	}
 	}
 
 
 	req.AddData(options)
 	req.AddData(options)
@@ -248,7 +291,7 @@ func QdiscList(link Link) ([]Qdisc, error) {
 // Equivalent to: `tc qdisc show`.
 // Equivalent to: `tc qdisc show`.
 // The list can be filtered by link.
 // The list can be filtered by link.
 func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
 func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETQDISC, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP)
 	index := int32(0)
 	index := int32(0)
 	if link != nil {
 	if link != nil {
 		base := link.Attrs()
 		base := link.Attrs()
@@ -261,7 +304,7 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
 	}
 	}
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWQDISC)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -303,6 +346,10 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
 					qdisc = &Ingress{}
 					qdisc = &Ingress{}
 				case "htb":
 				case "htb":
 					qdisc = &Htb{}
 					qdisc = &Htb{}
+				case "fq":
+					qdisc = &Fq{}
+				case "fq_codel":
+					qdisc = &FqCodel{}
 				case "netem":
 				case "netem":
 					qdisc = &Netem{}
 					qdisc = &Netem{}
 				default:
 				default:
@@ -336,6 +383,22 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
 					if err := parseHtbData(qdisc, data); err != nil {
 					if err := parseHtbData(qdisc, data); err != nil {
 						return nil, err
 						return nil, err
 					}
 					}
+				case "fq":
+					data, err := nl.ParseRouteAttr(attr.Value)
+					if err != nil {
+						return nil, err
+					}
+					if err := parseFqData(qdisc, data); err != nil {
+						return nil, err
+					}
+				case "fq_codel":
+					data, err := nl.ParseRouteAttr(attr.Value)
+					if err != nil {
+						return nil, err
+					}
+					if err := parseFqCodelData(qdisc, data); err != nil {
+						return nil, err
+					}
 				case "netem":
 				case "netem":
 					if err := parseNetemData(qdisc, attr.Value); err != nil {
 					if err := parseNetemData(qdisc, attr.Value); err != nil {
 						return nil, err
 						return nil, err
@@ -388,6 +451,61 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
 	return nil
 	return nil
 }
 }
 
 
+func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
+	native = nl.NativeEndian()
+	fqCodel := qdisc.(*FqCodel)
+	for _, datum := range data {
+
+		switch datum.Attr.Type {
+		case nl.TCA_FQ_CODEL_TARGET:
+			fqCodel.Target = native.Uint32(datum.Value)
+		case nl.TCA_FQ_CODEL_LIMIT:
+			fqCodel.Limit = native.Uint32(datum.Value)
+		case nl.TCA_FQ_CODEL_INTERVAL:
+			fqCodel.Interval = native.Uint32(datum.Value)
+		case nl.TCA_FQ_CODEL_ECN:
+			fqCodel.ECN = native.Uint32(datum.Value)
+		case nl.TCA_FQ_CODEL_FLOWS:
+			fqCodel.Flows = native.Uint32(datum.Value)
+		case nl.TCA_FQ_CODEL_QUANTUM:
+			fqCodel.Quantum = native.Uint32(datum.Value)
+		}
+	}
+	return nil
+}
+
+func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
+	native = nl.NativeEndian()
+	fq := qdisc.(*Fq)
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.TCA_FQ_BUCKETS_LOG:
+			fq.Buckets = native.Uint32(datum.Value)
+		case nl.TCA_FQ_LOW_RATE_THRESHOLD:
+			fq.LowRateThreshold = native.Uint32(datum.Value)
+		case nl.TCA_FQ_QUANTUM:
+			fq.Quantum = native.Uint32(datum.Value)
+		case nl.TCA_FQ_RATE_ENABLE:
+			fq.Pacing = native.Uint32(datum.Value)
+		case nl.TCA_FQ_INITIAL_QUANTUM:
+			fq.InitialQuantum = native.Uint32(datum.Value)
+		case nl.TCA_FQ_ORPHAN_MASK:
+			// TODO
+		case nl.TCA_FQ_FLOW_REFILL_DELAY:
+			fq.FlowRefillDelay = native.Uint32(datum.Value)
+		case nl.TCA_FQ_FLOW_PLIMIT:
+			fq.FlowPacketLimit = native.Uint32(datum.Value)
+		case nl.TCA_FQ_PLIMIT:
+			fq.PacketLimit = native.Uint32(datum.Value)
+		case nl.TCA_FQ_FLOW_MAX_RATE:
+			fq.FlowMaxRate = native.Uint32(datum.Value)
+		case nl.TCA_FQ_FLOW_DEFAULT_RATE:
+			fq.FlowDefaultRate = native.Uint32(datum.Value)
+		}
+	}
+	return nil
+}
+
 func parseNetemData(qdisc Qdisc, value []byte) error {
 func parseNetemData(qdisc Qdisc, value []byte) error {
 	netem := qdisc.(*Netem)
 	netem := qdisc.(*Netem)
 	opt := nl.DeserializeTcNetemQopt(value)
 	opt := nl.DeserializeTcNetemQopt(value)

+ 2 - 0
vendor/github.com/vishvananda/netlink/route.go

@@ -45,6 +45,8 @@ type Route struct {
 	MPLSDst    *int
 	MPLSDst    *int
 	NewDst     Destination
 	NewDst     Destination
 	Encap      Encap
 	Encap      Encap
+	MTU        int
+	AdvMSS     int
 }
 }
 
 
 func (r Route) String() string {
 func (r Route) String() string {

+ 190 - 55
vendor/github.com/vishvananda/netlink/route_linux.go

@@ -8,16 +8,17 @@ import (
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // RtAttr is shared so it is in netlink_linux.go
 // RtAttr is shared so it is in netlink_linux.go
 
 
 const (
 const (
-	SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE
-	SCOPE_SITE     Scope = syscall.RT_SCOPE_SITE
-	SCOPE_LINK     Scope = syscall.RT_SCOPE_LINK
-	SCOPE_HOST     Scope = syscall.RT_SCOPE_HOST
-	SCOPE_NOWHERE  Scope = syscall.RT_SCOPE_NOWHERE
+	SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE
+	SCOPE_SITE     Scope = unix.RT_SCOPE_SITE
+	SCOPE_LINK     Scope = unix.RT_SCOPE_LINK
+	SCOPE_HOST     Scope = unix.RT_SCOPE_HOST
+	SCOPE_NOWHERE  Scope = unix.RT_SCOPE_NOWHERE
 )
 )
 
 
 const (
 const (
@@ -34,8 +35,8 @@ const (
 )
 )
 
 
 const (
 const (
-	FLAG_ONLINK    NextHopFlag = syscall.RTNH_F_ONLINK
-	FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
+	FLAG_ONLINK    NextHopFlag = unix.RTNH_F_ONLINK
+	FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
 )
 )
 
 
 var testFlags = []flagString{
 var testFlags = []flagString{
@@ -124,17 +125,17 @@ func (e *MPLSEncap) Type() int {
 
 
 func (e *MPLSEncap) Decode(buf []byte) error {
 func (e *MPLSEncap) Decode(buf []byte) error {
 	if len(buf) < 4 {
 	if len(buf) < 4 {
-		return fmt.Errorf("Lack of bytes")
+		return fmt.Errorf("lack of bytes")
 	}
 	}
 	native := nl.NativeEndian()
 	native := nl.NativeEndian()
 	l := native.Uint16(buf)
 	l := native.Uint16(buf)
 	if len(buf) < int(l) {
 	if len(buf) < int(l) {
-		return fmt.Errorf("Lack of bytes")
+		return fmt.Errorf("lack of bytes")
 	}
 	}
 	buf = buf[:l]
 	buf = buf[:l]
 	typ := native.Uint16(buf[2:])
 	typ := native.Uint16(buf[2:])
 	if typ != nl.MPLS_IPTUNNEL_DST {
 	if typ != nl.MPLS_IPTUNNEL_DST {
-		return fmt.Errorf("Unknown MPLS Encap Type: %d", typ)
+		return fmt.Errorf("unknown MPLS Encap Type: %d", typ)
 	}
 	}
 	e.Labels = nl.DecodeMPLSStack(buf[4:])
 	e.Labels = nl.DecodeMPLSStack(buf[4:])
 	return nil
 	return nil
@@ -185,6 +186,79 @@ func (e *MPLSEncap) Equal(x Encap) bool {
 	return true
 	return true
 }
 }
 
 
+// SEG6 definitions
+type SEG6Encap struct {
+	Mode     int
+	Segments []net.IP
+}
+
+func (e *SEG6Encap) Type() int {
+	return nl.LWTUNNEL_ENCAP_SEG6
+}
+func (e *SEG6Encap) Decode(buf []byte) error {
+	if len(buf) < 4 {
+		return fmt.Errorf("lack of bytes")
+	}
+	native := nl.NativeEndian()
+	// Get Length(l) & Type(typ) : 2 + 2 bytes
+	l := native.Uint16(buf)
+	if len(buf) < int(l) {
+		return fmt.Errorf("lack of bytes")
+	}
+	buf = buf[:l] // make sure buf size upper limit is Length
+	typ := native.Uint16(buf[2:])
+	if typ != nl.SEG6_IPTUNNEL_SRH {
+		return fmt.Errorf("unknown SEG6 Type: %d", typ)
+	}
+
+	var err error
+	e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:])
+
+	return err
+}
+func (e *SEG6Encap) Encode() ([]byte, error) {
+	s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments)
+	native := nl.NativeEndian()
+	hdr := make([]byte, 4)
+	native.PutUint16(hdr, uint16(len(s)+4))
+	native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH)
+	return append(hdr, s...), err
+}
+func (e *SEG6Encap) String() string {
+	segs := make([]string, 0, len(e.Segments))
+	// append segment backwards (from n to 0) since seg#0 is the last segment.
+	for i := len(e.Segments); i > 0; i-- {
+		segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
+	}
+	str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode),
+		len(e.Segments), strings.Join(segs, " "))
+	return str
+}
+func (e *SEG6Encap) Equal(x Encap) bool {
+	o, ok := x.(*SEG6Encap)
+	if !ok {
+		return false
+	}
+	if e == o {
+		return true
+	}
+	if e == nil || o == nil {
+		return false
+	}
+	if e.Mode != o.Mode {
+		return false
+	}
+	if len(e.Segments) != len(o.Segments) {
+		return false
+	}
+	for i := range e.Segments {
+		if !e.Segments[i].Equal(o.Segments[i]) {
+			return false
+		}
+	}
+	return true
+}
+
 // RouteAdd will add a route to the system.
 // RouteAdd will add a route to the system.
 // Equivalent to: `ip route add $route`
 // Equivalent to: `ip route add $route`
 func RouteAdd(route *Route) error {
 func RouteAdd(route *Route) error {
@@ -194,8 +268,8 @@ func RouteAdd(route *Route) error {
 // RouteAdd will add a route to the system.
 // RouteAdd will add a route to the system.
 // Equivalent to: `ip route add $route`
 // Equivalent to: `ip route add $route`
 func (h *Handle) RouteAdd(route *Route) error {
 func (h *Handle) RouteAdd(route *Route) error {
-	flags := syscall.NLM_F_CREATE | syscall.NLM_F_EXCL | syscall.NLM_F_ACK
-	req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
+	flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK
+	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 	return h.routeHandle(route, req, nl.NewRtMsg())
 	return h.routeHandle(route, req, nl.NewRtMsg())
 }
 }
 
 
@@ -208,8 +282,8 @@ func RouteReplace(route *Route) error {
 // RouteReplace will add a route to the system.
 // RouteReplace will add a route to the system.
 // Equivalent to: `ip route replace $route`
 // Equivalent to: `ip route replace $route`
 func (h *Handle) RouteReplace(route *Route) error {
 func (h *Handle) RouteReplace(route *Route) error {
-	flags := syscall.NLM_F_CREATE | syscall.NLM_F_REPLACE | syscall.NLM_F_ACK
-	req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
+	flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK
+	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 	return h.routeHandle(route, req, nl.NewRtMsg())
 	return h.routeHandle(route, req, nl.NewRtMsg())
 }
 }
 
 
@@ -222,7 +296,7 @@ func RouteDel(route *Route) error {
 // RouteDel will delete a route from the system.
 // RouteDel will delete a route from the system.
 // Equivalent to: `ip route del $route`
 // Equivalent to: `ip route del $route`
 func (h *Handle) RouteDel(route *Route) error {
 func (h *Handle) RouteDel(route *Route) error {
-	req := h.newNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK)
 	return h.routeHandle(route, req, nl.NewRtDelMsg())
 	return h.routeHandle(route, req, nl.NewRtDelMsg())
 }
 }
 
 
@@ -245,12 +319,12 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 		} else {
 		} else {
 			dstData = route.Dst.IP.To16()
 			dstData = route.Dst.IP.To16()
 		}
 		}
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
 	} else if route.MPLSDst != nil {
 	} else if route.MPLSDst != nil {
 		family = nl.FAMILY_MPLS
 		family = nl.FAMILY_MPLS
 		msg.Dst_len = uint8(20)
 		msg.Dst_len = uint8(20)
-		msg.Type = syscall.RTN_UNICAST
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
+		msg.Type = unix.RTN_UNICAST
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
 	}
 	}
 
 
 	if route.NewDst != nil {
 	if route.NewDst != nil {
@@ -288,7 +362,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 			srcData = route.Src.To16()
 			srcData = route.Src.To16()
 		}
 		}
 		// The commonly used src ip for routes is actually PREFSRC
 		// The commonly used src ip for routes is actually PREFSRC
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PREFSRC, srcData))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData))
 	}
 	}
 
 
 	if route.Gw != nil {
 	if route.Gw != nil {
@@ -303,14 +377,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 		} else {
 		} else {
 			gwData = route.Gw.To16()
 			gwData = route.Gw.To16()
 		}
 		}
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData))
 	}
 	}
 
 
 	if len(route.MultiPath) > 0 {
 	if len(route.MultiPath) > 0 {
 		buf := []byte{}
 		buf := []byte{}
 		for _, nh := range route.MultiPath {
 		for _, nh := range route.MultiPath {
 			rtnh := &nl.RtNexthop{
 			rtnh := &nl.RtNexthop{
-				RtNexthop: syscall.RtNexthop{
+				RtNexthop: unix.RtNexthop{
 					Hops:    uint8(nh.Hops),
 					Hops:    uint8(nh.Hops),
 					Ifindex: int32(nh.LinkIndex),
 					Ifindex: int32(nh.LinkIndex),
 					Flags:   uint8(nh.Flags),
 					Flags:   uint8(nh.Flags),
@@ -323,9 +397,9 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 					return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
 					return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
 				}
 				}
 				if gwFamily == FAMILY_V4 {
 				if gwFamily == FAMILY_V4 {
-					children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4())))
+					children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4())))
 				} else {
 				} else {
-					children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())))
+					children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16())))
 				}
 				}
 			}
 			}
 			if nh.NewDst != nil {
 			if nh.NewDst != nil {
@@ -351,15 +425,15 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 			rtnh.Children = children
 			rtnh.Children = children
 			buf = append(buf, rtnh.Serialize()...)
 			buf = append(buf, rtnh.Serialize()...)
 		}
 		}
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_MULTIPATH, buf))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf))
 	}
 	}
 
 
 	if route.Table > 0 {
 	if route.Table > 0 {
 		if route.Table >= 256 {
 		if route.Table >= 256 {
-			msg.Table = syscall.RT_TABLE_UNSPEC
+			msg.Table = unix.RT_TABLE_UNSPEC
 			b := make([]byte, 4)
 			b := make([]byte, 4)
 			native.PutUint32(b, uint32(route.Table))
 			native.PutUint32(b, uint32(route.Table))
-			rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
+			rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b))
 		} else {
 		} else {
 			msg.Table = uint8(route.Table)
 			msg.Table = uint8(route.Table)
 		}
 		}
@@ -368,7 +442,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 	if route.Priority > 0 {
 	if route.Priority > 0 {
 		b := make([]byte, 4)
 		b := make([]byte, 4)
 		native.PutUint32(b, uint32(route.Priority))
 		native.PutUint32(b, uint32(route.Priority))
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b))
 	}
 	}
 	if route.Tos > 0 {
 	if route.Tos > 0 {
 		msg.Tos = uint8(route.Tos)
 		msg.Tos = uint8(route.Tos)
@@ -380,6 +454,25 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 		msg.Type = uint8(route.Type)
 		msg.Type = uint8(route.Type)
 	}
 	}
 
 
+	var metrics []*nl.RtAttr
+	// TODO: support other rta_metric values
+	if route.MTU > 0 {
+		b := nl.Uint32Attr(uint32(route.MTU))
+		metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
+	}
+	if route.AdvMSS > 0 {
+		b := nl.Uint32Attr(uint32(route.AdvMSS))
+		metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
+	}
+
+	if metrics != nil {
+		attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
+		for _, metric := range metrics {
+			attr.AddChild(metric)
+		}
+		rtAttrs = append(rtAttrs, attr)
+	}
+
 	msg.Flags = uint32(route.Flags)
 	msg.Flags = uint32(route.Flags)
 	msg.Scope = uint8(route.Scope)
 	msg.Scope = uint8(route.Scope)
 	msg.Family = uint8(family)
 	msg.Family = uint8(family)
@@ -394,9 +487,9 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 	)
 	)
 	native.PutUint32(b, uint32(route.LinkIndex))
 	native.PutUint32(b, uint32(route.LinkIndex))
 
 
-	req.AddData(nl.NewRtAttr(syscall.RTA_OIF, b))
+	req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -429,11 +522,11 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
 // RouteListFiltered gets a list of routes in the system filtered with specified rules.
 // RouteListFiltered gets a list of routes in the system filtered with specified rules.
 // All rules must be defined in RouteFilter struct
 // All rules must be defined in RouteFilter struct
 func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
 func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
 	infmsg := nl.NewIfInfomsg(family)
 	infmsg := nl.NewIfInfomsg(family)
 	req.AddData(infmsg)
 	req.AddData(infmsg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -441,11 +534,11 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
 	var res []Route
 	var res []Route
 	for _, m := range msgs {
 	for _, m := range msgs {
 		msg := nl.DeserializeRtMsg(m)
 		msg := nl.DeserializeRtMsg(m)
-		if msg.Flags&syscall.RTM_F_CLONED != 0 {
+		if msg.Flags&unix.RTM_F_CLONED != 0 {
 			// Ignore cloned routes
 			// Ignore cloned routes
 			continue
 			continue
 		}
 		}
-		if msg.Table != syscall.RT_TABLE_MAIN {
+		if msg.Table != unix.RT_TABLE_MAIN {
 			if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
 			if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
 				// Ignore non-main tables
 				// Ignore non-main tables
 				continue
 				continue
@@ -457,7 +550,7 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
 		}
 		}
 		if filter != nil {
 		if filter != nil {
 			switch {
 			switch {
-			case filterMask&RT_FILTER_TABLE != 0 && filter.Table != syscall.RT_TABLE_UNSPEC && route.Table != filter.Table:
+			case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
 				continue
 				continue
 			case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
 			case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
 				continue
 				continue
@@ -508,11 +601,11 @@ func deserializeRoute(m []byte) (Route, error) {
 	var encap, encapType syscall.NetlinkRouteAttr
 	var encap, encapType syscall.NetlinkRouteAttr
 	for _, attr := range attrs {
 	for _, attr := range attrs {
 		switch attr.Attr.Type {
 		switch attr.Attr.Type {
-		case syscall.RTA_GATEWAY:
+		case unix.RTA_GATEWAY:
 			route.Gw = net.IP(attr.Value)
 			route.Gw = net.IP(attr.Value)
-		case syscall.RTA_PREFSRC:
+		case unix.RTA_PREFSRC:
 			route.Src = net.IP(attr.Value)
 			route.Src = net.IP(attr.Value)
-		case syscall.RTA_DST:
+		case unix.RTA_DST:
 			if msg.Family == nl.FAMILY_MPLS {
 			if msg.Family == nl.FAMILY_MPLS {
 				stack := nl.DecodeMPLSStack(attr.Value)
 				stack := nl.DecodeMPLSStack(attr.Value)
 				if len(stack) == 0 || len(stack) > 1 {
 				if len(stack) == 0 || len(stack) > 1 {
@@ -525,36 +618,36 @@ func deserializeRoute(m []byte) (Route, error) {
 					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
 					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
 				}
 				}
 			}
 			}
-		case syscall.RTA_OIF:
+		case unix.RTA_OIF:
 			route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
 			route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
-		case syscall.RTA_IIF:
+		case unix.RTA_IIF:
 			route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
 			route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
-		case syscall.RTA_PRIORITY:
+		case unix.RTA_PRIORITY:
 			route.Priority = int(native.Uint32(attr.Value[0:4]))
 			route.Priority = int(native.Uint32(attr.Value[0:4]))
-		case syscall.RTA_TABLE:
+		case unix.RTA_TABLE:
 			route.Table = int(native.Uint32(attr.Value[0:4]))
 			route.Table = int(native.Uint32(attr.Value[0:4]))
-		case syscall.RTA_MULTIPATH:
+		case unix.RTA_MULTIPATH:
 			parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
 			parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
-				if len(value) < syscall.SizeofRtNexthop {
-					return nil, nil, fmt.Errorf("Lack of bytes")
+				if len(value) < unix.SizeofRtNexthop {
+					return nil, nil, fmt.Errorf("lack of bytes")
 				}
 				}
 				nh := nl.DeserializeRtNexthop(value)
 				nh := nl.DeserializeRtNexthop(value)
 				if len(value) < int(nh.RtNexthop.Len) {
 				if len(value) < int(nh.RtNexthop.Len) {
-					return nil, nil, fmt.Errorf("Lack of bytes")
+					return nil, nil, fmt.Errorf("lack of bytes")
 				}
 				}
 				info := &NexthopInfo{
 				info := &NexthopInfo{
 					LinkIndex: int(nh.RtNexthop.Ifindex),
 					LinkIndex: int(nh.RtNexthop.Ifindex),
 					Hops:      int(nh.RtNexthop.Hops),
 					Hops:      int(nh.RtNexthop.Hops),
 					Flags:     int(nh.RtNexthop.Flags),
 					Flags:     int(nh.RtNexthop.Flags),
 				}
 				}
-				attrs, err := nl.ParseRouteAttr(value[syscall.SizeofRtNexthop:int(nh.RtNexthop.Len)])
+				attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)])
 				if err != nil {
 				if err != nil {
 					return nil, nil, err
 					return nil, nil, err
 				}
 				}
 				var encap, encapType syscall.NetlinkRouteAttr
 				var encap, encapType syscall.NetlinkRouteAttr
 				for _, attr := range attrs {
 				for _, attr := range attrs {
 					switch attr.Attr.Type {
 					switch attr.Attr.Type {
-					case syscall.RTA_GATEWAY:
+					case unix.RTA_GATEWAY:
 						info.Gw = net.IP(attr.Value)
 						info.Gw = net.IP(attr.Value)
 					case nl.RTA_NEWDST:
 					case nl.RTA_NEWDST:
 						var d Destination
 						var d Destination
@@ -611,6 +704,19 @@ func deserializeRoute(m []byte) (Route, error) {
 			encapType = attr
 			encapType = attr
 		case nl.RTA_ENCAP:
 		case nl.RTA_ENCAP:
 			encap = attr
 			encap = attr
+		case unix.RTA_METRICS:
+			metrics, err := nl.ParseRouteAttr(attr.Value)
+			if err != nil {
+				return route, err
+			}
+			for _, metric := range metrics {
+				switch metric.Attr.Type {
+				case unix.RTAX_MTU:
+					route.MTU = int(native.Uint32(metric.Value[0:4]))
+				case unix.RTAX_ADVMSS:
+					route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
+				}
+			}
 		}
 		}
 	}
 	}
 
 
@@ -623,6 +729,11 @@ func deserializeRoute(m []byte) (Route, error) {
 			if err := e.Decode(encap.Value); err != nil {
 			if err := e.Decode(encap.Value); err != nil {
 				return route, err
 				return route, err
 			}
 			}
+		case nl.LWTUNNEL_ENCAP_SEG6:
+			e = &SEG6Encap{}
+			if err := e.Decode(encap.Value); err != nil {
+				return route, err
+			}
 		}
 		}
 		route.Encap = e
 		route.Encap = e
 	}
 	}
@@ -639,7 +750,7 @@ func RouteGet(destination net.IP) ([]Route, error) {
 // RouteGet gets a route to a specific destination from the host system.
 // RouteGet gets a route to a specific destination from the host system.
 // Equivalent to: 'ip route get'.
 // Equivalent to: 'ip route get'.
 func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
 func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_REQUEST)
+	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST)
 	family := nl.GetIPFamily(destination)
 	family := nl.GetIPFamily(destination)
 	var destinationData []byte
 	var destinationData []byte
 	var bitlen uint8
 	var bitlen uint8
@@ -655,10 +766,10 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
 	msg.Dst_len = bitlen
 	msg.Dst_len = bitlen
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	rtaDst := nl.NewRtAttr(syscall.RTA_DST, destinationData)
+	rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
 	req.AddData(rtaDst)
 	req.AddData(rtaDst)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -678,13 +789,13 @@ 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 {
-	return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil)
+	return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
 }
 }
 
 
 // RouteSubscribeAt works like RouteSubscribe plus it allows the caller
 // RouteSubscribeAt works like RouteSubscribe plus it allows the caller
 // to choose the network namespace in which to subscribe (ns).
 // to choose the network namespace in which to subscribe (ns).
 func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
 func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
-	return routeSubscribeAt(ns, netns.None(), ch, done, nil)
+	return routeSubscribeAt(ns, netns.None(), ch, done, nil, false)
 }
 }
 
 
 // RouteSubscribeOptions contains a set of options to use with
 // RouteSubscribeOptions contains a set of options to use with
@@ -692,6 +803,7 @@ func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan stru
 type RouteSubscribeOptions struct {
 type RouteSubscribeOptions struct {
 	Namespace     *netns.NsHandle
 	Namespace     *netns.NsHandle
 	ErrorCallback func(error)
 	ErrorCallback func(error)
+	ListExisting  bool
 }
 }
 
 
 // RouteSubscribeWithOptions work like RouteSubscribe but enable to
 // RouteSubscribeWithOptions work like RouteSubscribe but enable to
@@ -702,11 +814,11 @@ func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, opti
 		none := netns.None()
 		none := netns.None()
 		options.Namespace = &none
 		options.Namespace = &none
 	}
 	}
-	return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback)
+	return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
 }
 }
 
 
-func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error)) error {
-	s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
+func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
+	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -716,6 +828,15 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
 			s.Close()
 			s.Close()
 		}()
 		}()
 	}
 	}
+	if listExisting {
+		req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE,
+			unix.NLM_F_DUMP)
+		infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+		req.AddData(infmsg)
+		if err := s.Send(req); err != nil {
+			return err
+		}
+	}
 	go func() {
 	go func() {
 		defer close(ch)
 		defer close(ch)
 		for {
 		for {
@@ -727,6 +848,20 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
 				return
 				return
 			}
 			}
 			for _, m := range msgs {
 			for _, m := range msgs {
+				if m.Header.Type == unix.NLMSG_DONE {
+					continue
+				}
+				if m.Header.Type == unix.NLMSG_ERROR {
+					native := nl.NativeEndian()
+					error := int32(native.Uint32(m.Data[0:4]))
+					if error == 0 {
+						continue
+					}
+					if cberr != nil {
+						cberr(syscall.Errno(-error))
+					}
+					return
+				}
 				route, err := deserializeRoute(m.Data)
 				route, err := deserializeRoute(m.Data)
 				if err != nil {
 				if err != nil {
 					if cberr != nil {
 					if cberr != nil {

+ 1 - 0
vendor/github.com/vishvananda/netlink/rule.go

@@ -21,6 +21,7 @@ type Rule struct {
 	OifName           string
 	OifName           string
 	SuppressIfgroup   int
 	SuppressIfgroup   int
 	SuppressPrefixlen int
 	SuppressPrefixlen int
+	Invert            bool
 }
 }
 
 
 func (r Rule) String() string {
 func (r Rule) String() string {

+ 30 - 20
vendor/github.com/vishvananda/netlink/rule_linux.go

@@ -3,11 +3,13 @@ package netlink
 import (
 import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
-	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
+const FibRuleInvert = 0x2
+
 // RuleAdd adds a rule to the system.
 // RuleAdd adds a rule to the system.
 // Equivalent to: ip rule add
 // Equivalent to: ip rule add
 func RuleAdd(rule *Rule) error {
 func RuleAdd(rule *Rule) error {
@@ -17,7 +19,7 @@ func RuleAdd(rule *Rule) error {
 // RuleAdd adds a rule to the system.
 // RuleAdd adds a rule to the system.
 // Equivalent to: ip rule add
 // Equivalent to: ip rule add
 func (h *Handle) RuleAdd(rule *Rule) error {
 func (h *Handle) RuleAdd(rule *Rule) error {
-	req := h.newNetlinkRequest(syscall.RTM_NEWRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 	return ruleHandle(rule, req)
 	return ruleHandle(rule, req)
 }
 }
 
 
@@ -30,18 +32,31 @@ func RuleDel(rule *Rule) error {
 // RuleDel deletes a rule from the system.
 // RuleDel deletes a rule from the system.
 // Equivalent to: ip rule del
 // Equivalent to: ip rule del
 func (h *Handle) RuleDel(rule *Rule) error {
 func (h *Handle) RuleDel(rule *Rule) error {
-	req := h.newNetlinkRequest(syscall.RTM_DELRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK)
 	return ruleHandle(rule, req)
 	return ruleHandle(rule, req)
 }
 }
 
 
 func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 	msg := nl.NewRtMsg()
 	msg := nl.NewRtMsg()
-	msg.Family = syscall.AF_INET
+	msg.Family = unix.AF_INET
+	msg.Protocol = unix.RTPROT_BOOT
+	msg.Scope = unix.RT_SCOPE_UNIVERSE
+	msg.Table = unix.RT_TABLE_UNSPEC
+	msg.Type = unix.RTN_UNSPEC
+	if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
+		msg.Type = unix.RTN_UNICAST
+	}
+	if rule.Invert {
+		msg.Flags |= FibRuleInvert
+	}
 	if rule.Family != 0 {
 	if rule.Family != 0 {
 		msg.Family = uint8(rule.Family)
 		msg.Family = uint8(rule.Family)
 	}
 	}
-	var dstFamily uint8
+	if rule.Table >= 0 && rule.Table < 256 {
+		msg.Table = uint8(rule.Table)
+	}
 
 
+	var dstFamily uint8
 	var rtAttrs []*nl.RtAttr
 	var rtAttrs []*nl.RtAttr
 	if rule.Dst != nil && rule.Dst.IP != nil {
 	if rule.Dst != nil && rule.Dst.IP != nil {
 		dstLen, _ := rule.Dst.Mask.Size()
 		dstLen, _ := rule.Dst.Mask.Size()
@@ -49,12 +64,12 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 		msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
 		msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
 		dstFamily = msg.Family
 		dstFamily = msg.Family
 		var dstData []byte
 		var dstData []byte
-		if msg.Family == syscall.AF_INET {
+		if msg.Family == unix.AF_INET {
 			dstData = rule.Dst.IP.To4()
 			dstData = rule.Dst.IP.To4()
 		} else {
 		} else {
 			dstData = rule.Dst.IP.To16()
 			dstData = rule.Dst.IP.To16()
 		}
 		}
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
 	}
 	}
 
 
 	if rule.Src != nil && rule.Src.IP != nil {
 	if rule.Src != nil && rule.Src.IP != nil {
@@ -65,19 +80,12 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 		srcLen, _ := rule.Src.Mask.Size()
 		srcLen, _ := rule.Src.Mask.Size()
 		msg.Src_len = uint8(srcLen)
 		msg.Src_len = uint8(srcLen)
 		var srcData []byte
 		var srcData []byte
-		if msg.Family == syscall.AF_INET {
+		if msg.Family == unix.AF_INET {
 			srcData = rule.Src.IP.To4()
 			srcData = rule.Src.IP.To4()
 		} else {
 		} else {
 			srcData = rule.Src.IP.To16()
 			srcData = rule.Src.IP.To16()
 		}
 		}
-		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_SRC, srcData))
-	}
-
-	if rule.Table >= 0 {
-		msg.Table = uint8(rule.Table)
-		if rule.Table >= 256 {
-			msg.Table = syscall.RT_TABLE_UNSPEC
-		}
+		rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData))
 	}
 	}
 
 
 	req.AddData(msg)
 	req.AddData(msg)
@@ -142,7 +150,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
 		req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
 		req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 	return err
 	return err
 }
 }
 
 
@@ -155,11 +163,11 @@ func RuleList(family int) ([]Rule, error) {
 // RuleList lists rules in the system.
 // RuleList lists rules in the system.
 // Equivalent to: ip rule list
 // Equivalent to: ip rule list
 func (h *Handle) RuleList(family int) ([]Rule, error) {
 func (h *Handle) RuleList(family int) ([]Rule, error) {
-	req := h.newNetlinkRequest(syscall.RTM_GETRULE, syscall.NLM_F_DUMP|syscall.NLM_F_REQUEST)
+	req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST)
 	msg := nl.NewIfInfomsg(family)
 	msg := nl.NewIfInfomsg(family)
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWRULE)
+	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -175,9 +183,11 @@ func (h *Handle) RuleList(family int) ([]Rule, error) {
 
 
 		rule := NewRule()
 		rule := NewRule()
 
 
+		rule.Invert = msg.Flags&FibRuleInvert > 0
+
 		for j := range attrs {
 		for j := range attrs {
 			switch attrs[j].Attr.Type {
 			switch attrs[j].Attr.Type {
-			case syscall.RTA_TABLE:
+			case unix.RTA_TABLE:
 				rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
 				rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
 			case nl.FRA_SRC:
 			case nl.FRA_SRC:
 				rule.Src = &net.IPNet{
 				rule.Src = &net.IPNet{

+ 4 - 4
vendor/github.com/vishvananda/netlink/socket_linux.go

@@ -4,9 +4,9 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
-	"syscall"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 const (
 const (
@@ -123,15 +123,15 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
 		return nil, ErrNotImplemented
 		return nil, ErrNotImplemented
 	}
 	}
 
 
-	s, err := nl.Subscribe(syscall.NETLINK_INET_DIAG)
+	s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	defer s.Close()
 	defer s.Close()
 	req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
 	req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
 	req.AddData(&socketRequest{
 	req.AddData(&socketRequest{
-		Family:   syscall.AF_INET,
-		Protocol: syscall.IPPROTO_TCP,
+		Family:   unix.AF_INET,
+		Protocol: unix.IPPROTO_TCP,
 		ID: SocketID{
 		ID: SocketID{
 			SourcePort:      uint16(localTCP.Port),
 			SourcePort:      uint16(localTCP.Port),
 			DestinationPort: uint16(remoteTCP.Port),
 			DestinationPort: uint16(remoteTCP.Port),

+ 7 - 6
vendor/github.com/vishvananda/netlink/xfrm.go

@@ -2,19 +2,20 @@ package netlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"syscall"
+
+	"golang.org/x/sys/unix"
 )
 )
 
 
 // Proto is an enum representing an ipsec protocol.
 // Proto is an enum representing an ipsec protocol.
 type Proto uint8
 type Proto uint8
 
 
 const (
 const (
-	XFRM_PROTO_ROUTE2    Proto = syscall.IPPROTO_ROUTING
-	XFRM_PROTO_ESP       Proto = syscall.IPPROTO_ESP
-	XFRM_PROTO_AH        Proto = syscall.IPPROTO_AH
-	XFRM_PROTO_HAO       Proto = syscall.IPPROTO_DSTOPTS
+	XFRM_PROTO_ROUTE2    Proto = unix.IPPROTO_ROUTING
+	XFRM_PROTO_ESP       Proto = unix.IPPROTO_ESP
+	XFRM_PROTO_AH        Proto = unix.IPPROTO_AH
+	XFRM_PROTO_HAO       Proto = unix.IPPROTO_DSTOPTS
 	XFRM_PROTO_COMP      Proto = 0x6c // NOTE not defined on darwin
 	XFRM_PROTO_COMP      Proto = 0x6c // NOTE not defined on darwin
-	XFRM_PROTO_IPSEC_ANY Proto = syscall.IPPROTO_RAW
+	XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW
 )
 )
 
 
 func (p Proto) String() string {
 func (p Proto) String() string {

+ 3 - 4
vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go

@@ -2,11 +2,10 @@ package netlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"syscall"
-
-	"github.com/vishvananda/netns"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"github.com/vishvananda/netns"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 type XfrmMsg interface {
 type XfrmMsg interface {
@@ -39,7 +38,7 @@ func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error
 	if err != nil {
 	if err != nil {
 		return nil
 		return nil
 	}
 	}
-	s, err := nl.SubscribeAt(netns.None(), netns.None(), syscall.NETLINK_XFRM, groups...)
+	s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 9 - 10
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go

@@ -1,9 +1,8 @@
 package netlink
 package netlink
 
 
 import (
 import (
-	"syscall"
-
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
 func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
@@ -55,7 +54,7 @@ func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error {
 }
 }
 
 
 func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
 func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
-	req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 
 
 	msg := &nl.XfrmUserpolicyInfo{}
 	msg := &nl.XfrmUserpolicyInfo{}
 	selFromPolicy(&msg.Sel, policy)
 	selFromPolicy(&msg.Sel, policy)
@@ -91,7 +90,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
 		req.AddData(out)
 		req.AddData(out)
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_XFRM, 0)
+	_, err := req.Execute(unix.NETLINK_XFRM, 0)
 	return err
 	return err
 }
 }
 
 
@@ -121,12 +120,12 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
 // Equivalent to: `ip xfrm policy show`.
 // Equivalent to: `ip xfrm policy show`.
 // The list can be filtered by ip family.
 // The list can be filtered by ip family.
 func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
 func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
-	req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP)
 
 
 	msg := nl.NewIfInfomsg(family)
 	msg := nl.NewIfInfomsg(family)
 	req.AddData(msg)
 	req.AddData(msg)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
+	msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -165,13 +164,13 @@ func XfrmPolicyFlush() error {
 // XfrmPolicyFlush will flush the policies on the system.
 // XfrmPolicyFlush will flush the policies on the system.
 // Equivalent to: `ip xfrm policy flush`
 // Equivalent to: `ip xfrm policy flush`
 func (h *Handle) XfrmPolicyFlush() error {
 func (h *Handle) XfrmPolicyFlush() error {
-	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, syscall.NLM_F_ACK)
-	_, err := req.Execute(syscall.NETLINK_XFRM, 0)
+	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK)
+	_, err := req.Execute(unix.NETLINK_XFRM, 0)
 	return err
 	return err
 }
 }
 
 
 func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
 func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
-	req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
 
 
 	msg := &nl.XfrmUserpolicyId{}
 	msg := &nl.XfrmUserpolicyId{}
 	selFromPolicy(&msg.Sel, policy)
 	selFromPolicy(&msg.Sel, policy)
@@ -189,7 +188,7 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
 		resType = 0
 		resType = 0
 	}
 	}
 
 
-	msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
+	msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

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

@@ -3,6 +3,7 @@ package netlink
 import (
 import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
+	"time"
 )
 )
 
 
 // XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
 // XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
@@ -67,6 +68,19 @@ type XfrmStateLimits struct {
 	TimeUseHard uint64
 	TimeUseHard uint64
 }
 }
 
 
+// XfrmStateStats represents the current number of bytes/packets
+// processed by this State, the State's installation and first use
+// time and the replay window counters.
+type XfrmStateStats struct {
+	ReplayWindow uint32
+	Replay       uint32
+	Failed       uint32
+	Bytes        uint64
+	Packets      uint64
+	AddTime      uint64
+	UseTime      uint64
+}
+
 // XfrmState represents the state of an ipsec policy. It optionally
 // XfrmState represents the state of an ipsec policy. It optionally
 // contains an XfrmStateAlgo for encryption and one for authentication.
 // contains an XfrmStateAlgo for encryption and one for authentication.
 type XfrmState struct {
 type XfrmState struct {
@@ -78,6 +92,7 @@ type XfrmState struct {
 	Reqid        int
 	Reqid        int
 	ReplayWindow int
 	ReplayWindow int
 	Limits       XfrmStateLimits
 	Limits       XfrmStateLimits
+	Statistics   XfrmStateStats
 	Mark         *XfrmMark
 	Mark         *XfrmMark
 	Auth         *XfrmStateAlgo
 	Auth         *XfrmStateAlgo
 	Crypt        *XfrmStateAlgo
 	Crypt        *XfrmStateAlgo
@@ -94,10 +109,16 @@ func (sa XfrmState) Print(stats bool) string {
 	if !stats {
 	if !stats {
 		return sa.String()
 		return sa.String()
 	}
 	}
-
-	return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d",
+	at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate)
+	ut := "-"
+	if sa.Statistics.UseTime > 0 {
+		ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate)
+	}
+	return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+
+		"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d",
 		sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
 		sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
-		sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard)
+		sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut,
+		sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed)
 }
 }
 
 
 func printLimit(lmt uint64) string {
 func printLimit(lmt uint64) string {

+ 26 - 13
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go

@@ -2,10 +2,10 @@ package netlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"syscall"
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netlink/nl"
+	"golang.org/x/sys/unix"
 )
 )
 
 
 func writeStateAlgo(a *XfrmStateAlgo) []byte {
 func writeStateAlgo(a *XfrmStateAlgo) []byte {
@@ -69,8 +69,10 @@ func writeReplayEsn(replayWindow int) []byte {
 		ReplayWindow: uint32(replayWindow),
 		ReplayWindow: uint32(replayWindow),
 	}
 	}
 
 
-	// taken from iproute2/ip/xfrm_state.c:
-	replayEsn.BmpLen = uint32((replayWindow + (4 * 8) - 1) / (4 * 8))
+	// Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements.
+	// Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation.
+	bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this
+	replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8))
 
 
 	return replayEsn.Serialize()
 	return replayEsn.Serialize()
 }
 }
@@ -111,7 +113,7 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
 	if state.Spi == 0 {
 	if state.Spi == 0 {
 		return fmt.Errorf("Spi must be set when adding xfrm state.")
 		return fmt.Errorf("Spi must be set when adding xfrm state.")
 	}
 	}
-	req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 
 
 	msg := xfrmUsersaInfoFromXfrmState(state)
 	msg := xfrmUsersaInfoFromXfrmState(state)
 
 
@@ -157,13 +159,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
 		req.AddData(out)
 		req.AddData(out)
 	}
 	}
 
 
-	_, err := req.Execute(syscall.NETLINK_XFRM, 0)
+	_, err := req.Execute(unix.NETLINK_XFRM, 0)
 	return err
 	return err
 }
 }
 
 
 func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
 func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
 	req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI,
 	req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI,
-		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+		unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
 
 
 	msg := &nl.XfrmUserSpiInfo{}
 	msg := &nl.XfrmUserSpiInfo{}
 	msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state))
 	msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state))
@@ -177,7 +179,7 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
 		req.AddData(out)
 		req.AddData(out)
 	}
 	}
 
 
-	msgs, err := req.Execute(syscall.NETLINK_XFRM, 0)
+	msgs, err := req.Execute(unix.NETLINK_XFRM, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -216,9 +218,9 @@ func XfrmStateList(family int) ([]XfrmState, error) {
 // Equivalent to: `ip xfrm state show`.
 // Equivalent to: `ip xfrm state show`.
 // The list can be filtered by ip family.
 // The list can be filtered by ip family.
 func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) {
 func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) {
-	req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)
+	req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP)
 
 
-	msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
+	msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -255,7 +257,7 @@ func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) {
 }
 }
 
 
 func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) {
 func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) {
-	req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
 
 
 	msg := &nl.XfrmUsersaId{}
 	msg := &nl.XfrmUsersaId{}
 	msg.Family = uint16(nl.GetIPFamily(state.Dst))
 	msg.Family = uint16(nl.GetIPFamily(state.Dst))
@@ -278,7 +280,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
 		resType = 0
 		resType = 0
 	}
 	}
 
 
-	msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
+	msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -308,6 +310,7 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
 	state.Reqid = int(msg.Reqid)
 	state.Reqid = int(msg.Reqid)
 	state.ReplayWindow = int(msg.ReplayWindow)
 	state.ReplayWindow = int(msg.ReplayWindow)
 	lftToLimits(&msg.Lft, &state.Limits)
 	lftToLimits(&msg.Lft, &state.Limits)
+	curToStats(&msg.Curlft, &msg.Stats, &state.Statistics)
 
 
 	return &state
 	return &state
 }
 }
@@ -386,11 +389,11 @@ func XfrmStateFlush(proto Proto) error {
 // proto = 0 means any transformation protocols
 // proto = 0 means any transformation protocols
 // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
 // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
 func (h *Handle) XfrmStateFlush(proto Proto) error {
 func (h *Handle) XfrmStateFlush(proto Proto) error {
-	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, syscall.NLM_F_ACK)
+	req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK)
 
 
 	req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
 	req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
 
 
-	_, err := req.Execute(syscall.NETLINK_XFRM, 0)
+	_, err := req.Execute(unix.NETLINK_XFRM, 0)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -429,6 +432,16 @@ func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) {
 	*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
 	*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
 }
 }
 
 
+func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) {
+	stats.Bytes = cur.Bytes
+	stats.Packets = cur.Packets
+	stats.AddTime = cur.AddTime
+	stats.UseTime = cur.UseTime
+	stats.ReplayWindow = wstats.ReplayWindow
+	stats.Replay = wstats.Replay
+	stats.Failed = wstats.IntegrityFailed
+}
+
 func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
 func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
 	msg := &nl.XfrmUsersaInfo{}
 	msg := &nl.XfrmUsersaInfo{}
 	msg.Family = uint16(nl.GetIPFamily(state.Dst))
 	msg.Family = uint16(nl.GetIPFamily(state.Dst))

+ 4 - 2
vendor/github.com/vishvananda/netns/README.md

@@ -20,9 +20,10 @@ Testing (requires root):
 package main
 package main
 
 
 import (
 import (
+    "fmt"
     "net"
     "net"
     "runtime"
     "runtime"
-    "github.com/vishvananada/netns"
+    "github.com/vishvananda/netns"
 )
 )
 
 
 func main() {
 func main() {
@@ -36,9 +37,10 @@ func main() {
 
 
     // Create a new network namespace
     // Create a new network namespace
     newns, _ := netns.New()
     newns, _ := netns.New()
+    netns.Set(newns)
     defer newns.Close()
     defer newns.Close()
 
 
-    // Do something with tne network namespace
+    // Do something with the network namespace
     ifaces, _ := net.Interfaces()
     ifaces, _ := net.Interfaces()
     fmt.Printf("Interfaces: %v\n", ifaces)
     fmt.Printf("Interfaces: %v\n", ifaces)
 
 

+ 15 - 2
vendor/github.com/vishvananda/netns/netns.go

@@ -19,7 +19,7 @@ type NsHandle int
 
 
 // Equal determines if two network handles refer to the same network
 // Equal determines if two network handles refer to the same network
 // namespace. This is done by comparing the device and inode that the
 // namespace. This is done by comparing the device and inode that the
-// file descripors point to.
+// file descriptors point to.
 func (ns NsHandle) Equal(other NsHandle) bool {
 func (ns NsHandle) Equal(other NsHandle) bool {
 	if ns == other {
 	if ns == other {
 		return true
 		return true
@@ -46,6 +46,19 @@ func (ns NsHandle) String() string {
 	return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
 	return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
 }
 }
 
 
+// UniqueId returns a string which uniquely identifies the namespace
+// associated with the network handle.
+func (ns NsHandle) UniqueId() string {
+	var s syscall.Stat_t
+	if ns == -1 {
+		return "NS(none)"
+	}
+	if err := syscall.Fstat(int(ns), &s); err != nil {
+		return "NS(unknown)"
+	}
+	return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino)
+}
+
 // IsOpen returns true if Close() has not been called.
 // IsOpen returns true if Close() has not been called.
 func (ns NsHandle) IsOpen() bool {
 func (ns NsHandle) IsOpen() bool {
 	return ns != -1
 	return ns != -1
@@ -61,7 +74,7 @@ func (ns *NsHandle) Close() error {
 	return nil
 	return nil
 }
 }
 
 
-// Get an empty (closed) NsHandle
+// None gets an empty (closed) NsHandle.
 func None() NsHandle {
 func None() NsHandle {
 	return NsHandle(-1)
 	return NsHandle(-1)
 }
 }

+ 29 - 4
vendor/github.com/vishvananda/netns/netns_linux.go

@@ -7,14 +7,27 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
+	"runtime"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
 )
 )
 
 
+// SYS_SETNS syscall allows changing the namespace of the current process.
+var SYS_SETNS = map[string]uintptr{
+	"386":     346,
+	"amd64":   308,
+	"arm64":   268,
+	"arm":     375,
+	"mips":    4344,
+	"mipsle":  4344,
+	"ppc64":   350,
+	"ppc64le": 350,
+	"s390x":   339,
+}[runtime.GOARCH]
+
+// Deprecated: use syscall pkg instead (go >= 1.5 needed).
 const (
 const (
-	// These constants belong in the syscall library but have not been
-	// added yet.
 	CLONE_NEWUTS  = 0x04000000 /* New utsname group? */
 	CLONE_NEWUTS  = 0x04000000 /* New utsname group? */
 	CLONE_NEWIPC  = 0x08000000 /* New ipcs */
 	CLONE_NEWIPC  = 0x08000000 /* New ipcs */
 	CLONE_NEWUSER = 0x10000000 /* New user namespace */
 	CLONE_NEWUSER = 0x10000000 /* New user namespace */
@@ -125,7 +138,9 @@ func getThisCgroup(cgroupType string) (string, error) {
 		return "", fmt.Errorf("docker pid not found in /var/run/docker.pid")
 		return "", fmt.Errorf("docker pid not found in /var/run/docker.pid")
 	}
 	}
 	pid, err := strconv.Atoi(result[0])
 	pid, err := strconv.Atoi(result[0])
-
+	if err != nil {
+		return "", err
+	}
 	output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
 	output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
@@ -167,8 +182,18 @@ func getPidForContainer(id string) (int, error) {
 		filepath.Join(cgroupRoot, cgroupThis, id, "tasks"),
 		filepath.Join(cgroupRoot, cgroupThis, id, "tasks"),
 		// With more recent lxc versions use, cgroup will be in lxc/
 		// With more recent lxc versions use, cgroup will be in lxc/
 		filepath.Join(cgroupRoot, cgroupThis, "lxc", id, "tasks"),
 		filepath.Join(cgroupRoot, cgroupThis, "lxc", id, "tasks"),
-		// With more recent dockee, cgroup will be in docker/
+		// With more recent docker, cgroup will be in docker/
 		filepath.Join(cgroupRoot, cgroupThis, "docker", id, "tasks"),
 		filepath.Join(cgroupRoot, cgroupThis, "docker", id, "tasks"),
+		// Even more recent docker versions under systemd use docker-<id>.scope/
+		filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"),
+		// Even more recent docker versions under cgroup/systemd/docker/<id>/
+		filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"),
+		// Kubernetes with docker and CNI is even more different
+		filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, "tasks"),
+		// Another flavor of containers location in recent kubernetes 1.11+
+		filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
+		// When runs inside of a container with recent kubernetes 1.11+
+		filepath.Join(cgroupRoot, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
 	}
 	}
 
 
 	var filename string
 	var filename string

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_386.go

@@ -1,7 +0,0 @@
-// +build linux,386
-
-package netns
-
-const (
-	SYS_SETNS = 346
-)

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_amd64.go

@@ -1,7 +0,0 @@
-// +build linux,amd64
-
-package netns
-
-const (
-	SYS_SETNS = 308
-)

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_arm.go

@@ -1,7 +0,0 @@
-// +build linux,arm
-
-package netns
-
-const (
-	SYS_SETNS = 375
-)

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_arm64.go

@@ -1,7 +0,0 @@
-// +build linux,arm64
-
-package netns
-
-const (
-	SYS_SETNS = 268
-)

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_ppc64le.go

@@ -1,7 +0,0 @@
-// +build linux,ppc64le
-
-package netns
-
-const (
-	SYS_SETNS = 350
-)

+ 0 - 7
vendor/github.com/vishvananda/netns/netns_linux_s390x.go

@@ -1,7 +0,0 @@
-// +build linux,s390x
-
-package netns
-
-const (
-	SYS_SETNS = 339
-)

+ 8 - 0
vendor/github.com/vishvananda/netns/netns_unspecified.go

@@ -22,6 +22,10 @@ func Get() (NsHandle, error) {
 	return -1, ErrNotImplemented
 	return -1, ErrNotImplemented
 }
 }
 
 
+func GetFromPath(path string) (NsHandle, error) {
+	return -1, ErrNotImplemented
+}
+
 func GetFromName(name string) (NsHandle, error) {
 func GetFromName(name string) (NsHandle, error) {
 	return -1, ErrNotImplemented
 	return -1, ErrNotImplemented
 }
 }
@@ -30,6 +34,10 @@ func GetFromPid(pid int) (NsHandle, error) {
 	return -1, ErrNotImplemented
 	return -1, ErrNotImplemented
 }
 }
 
 
+func GetFromThread(pid, tid int) (NsHandle, error) {
+	return -1, ErrNotImplemented
+}
+
 func GetFromDocker(id string) (NsHandle, error) {
 func GetFromDocker(id string) (NsHandle, error) {
 	return -1, ErrNotImplemented
 	return -1, ErrNotImplemented
 }
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов