summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--go.sum5
-rw-r--r--vendor/github.com/vishvananda/netlink/.gitignore1
-rw-r--r--vendor/github.com/vishvananda/netlink/.travis.yml6
-rw-r--r--vendor/github.com/vishvananda/netlink/addr_linux.go105
-rw-r--r--vendor/github.com/vishvananda/netlink/bridge_linux.go9
-rw-r--r--vendor/github.com/vishvananda/netlink/class.go141
-rw-r--r--vendor/github.com/vishvananda/netlink/class_linux.go145
-rw-r--r--vendor/github.com/vishvananda/netlink/conntrack_linux.go119
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go272
-rw-r--r--vendor/github.com/vishvananda/netlink/filter.go110
-rw-r--r--vendor/github.com/vishvananda/netlink/filter_linux.go240
-rw-r--r--vendor/github.com/vishvananda/netlink/fou_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/genetlink_linux.go3
-rw-r--r--vendor/github.com/vishvananda/netlink/go.mod8
-rw-r--r--vendor/github.com/vishvananda/netlink/go.sum4
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_linux.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_unspecified.go12
-rw-r--r--vendor/github.com/vishvananda/netlink/ioctl_linux.go10
-rw-r--r--vendor/github.com/vishvananda/netlink/link.go242
-rw-r--r--vendor/github.com/vishvananda/netlink/link_linux.go1120
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh.go7
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh_linux.go189
-rw-r--r--vendor/github.com/vishvananda/netlink/netlink.go3
-rw-r--r--vendor/github.com/vishvananda/netlink/netlink_unspecified.go12
-rw-r--r--vendor/github.com/vishvananda/netlink/netns_linux.go141
-rw-r--r--vendor/github.com/vishvananda/netlink/netns_unspecified.go19
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/bridge_linux.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go40
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/devlink_linux.go40
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/link_linux.go72
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/nl_linux.go66
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go35
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/route_linux.go26
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/seg6_linux.go43
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go76
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/syscall.go11
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/tc_linux.go166
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go62
-rw-r--r--vendor/github.com/vishvananda/netlink/protinfo.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/protinfo_linux.go7
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc.go48
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc_linux.go69
-rw-r--r--vendor/github.com/vishvananda/netlink/rdma_link_linux.go264
-rw-r--r--vendor/github.com/vishvananda/netlink/route.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/route_linux.go229
-rw-r--r--vendor/github.com/vishvananda/netlink/rule_linux.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/socket_linux.go5
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy.go26
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go19
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go27
-rw-r--r--vendor/github.com/vishvananda/netns/go.mod3
-rw-r--r--vendor/github.com/vishvananda/netns/go.sum0
-rw-r--r--vendor/modules.txt4
56 files changed, 3711 insertions, 584 deletions
diff --git a/go.mod b/go.mod
index 54af7fda4..8498c0ad2 100644
--- a/go.mod
+++ b/go.mod
@@ -64,7 +64,7 @@ require (
github.com/uber/jaeger-client-go v2.20.1+incompatible
github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 // indirect
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b
- github.com/vishvananda/netlink v1.0.0
+ github.com/vishvananda/netlink v1.1.0
go.uber.org/atomic v1.4.0 // indirect
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
diff --git a/go.sum b/go.sum
index de7791f47..ff3c585e1 100644
--- a/go.sum
+++ b/go.sum
@@ -507,10 +507,14 @@ github.com/vbauerster/mpb/v4 v4.11.1/go.mod h1:vMLa1J/ZKC83G2lB/52XpqT+ZZtFG4aZO
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
+github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
+github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I=
github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
@@ -595,6 +599,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/vishvananda/netlink/.gitignore b/vendor/github.com/vishvananda/netlink/.gitignore
new file mode 100644
index 000000000..9f11b755a
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/.gitignore
@@ -0,0 +1 @@
+.idea/
diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml
index f5c0b3eb5..7d14af4d6 100644
--- a/vendor/github.com/vishvananda/netlink/.travis.yml
+++ b/vendor/github.com/vishvananda/netlink/.travis.yml
@@ -1,4 +1,8 @@
language: go
+go:
+ - "1.10.x"
+ - "1.11.x"
+ - "1.12.x"
before_script:
# make sure we keep path in tact when we sudo
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
@@ -9,5 +13,7 @@ before_script:
- sudo modprobe nf_conntrack_netlink
- sudo modprobe nf_conntrack_ipv4
- sudo modprobe nf_conntrack_ipv6
+ - sudo modprobe sch_hfsc
install:
- go get github.com/vishvananda/netns
+go_import_path: github.com/vishvananda/netlink
diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go
index d59c3281e..28746d5af 100644
--- a/vendor/github.com/vishvananda/netlink/addr_linux.go
+++ b/vendor/github.com/vishvananda/netlink/addr_linux.go
@@ -15,39 +15,62 @@ import (
const IFA_FLAGS = 0x8
// AddrAdd will add an IP address to a link device.
+//
// Equivalent to: `ip addr add $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrAdd(link Link, addr *Addr) error {
return pkgHandle.AddrAdd(link, addr)
}
// AddrAdd will add an IP address to a link device.
+//
// Equivalent to: `ip addr add $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
}
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
+//
// Equivalent to: `ip addr replace $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrReplace(link Link, addr *Addr) error {
return pkgHandle.AddrReplace(link, addr)
}
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
+//
// Equivalent to: `ip addr replace $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrReplace(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
}
// AddrDel will delete an IP address from a link device.
+//
// Equivalent to: `ip addr del $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrDel(link Link, addr *Addr) error {
return pkgHandle.AddrDel(link, addr)
}
// AddrDel will delete an IP address from a link device.
// Equivalent to: `ip addr del $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrDel(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
@@ -65,7 +88,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
msg := nl.NewIfAddrmsg(family)
msg.Index = uint32(base.Index)
msg.Scope = uint8(addr.Scope)
- prefixlen, masklen := addr.Mask.Size()
+ mask := addr.Mask
+ if addr.Peer != nil {
+ mask = addr.Peer.Mask
+ }
+ prefixlen, masklen := mask.Size()
msg.Prefixlen = uint8(prefixlen)
req.AddData(msg)
@@ -104,14 +131,20 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
}
if family == FAMILY_V4 {
- if addr.Broadcast == nil {
+ // Automatically set the broadcast address if it is unset and the
+ // subnet is large enough to sensibly have one (/30 or larger).
+ // See: RFC 3021
+ if addr.Broadcast == nil && prefixlen < 31 {
calcBroadcast := make(net.IP, masklen/8)
for i := range localAddrData {
- calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
+ calcBroadcast[i] = localAddrData[i] | ^mask[i]
}
addr.Broadcast = calcBroadcast
}
- req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
+
+ if addr.Broadcast != nil {
+ req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
+ }
if addr.Label != "" {
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
@@ -206,13 +239,17 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
- addr.Peer = dst
case unix.IFA_LOCAL:
+ // iproute2 manual:
+ // If a peer address is specified, the local address
+ // cannot have a prefix length. The network prefix is
+ // associated with the peer rather than with the local
+ // address.
+ n := 8 * len(attr.Value)
local = &net.IPNet{
IP: attr.Value,
- Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
+ Mask: net.CIDRMask(n, n),
}
- addr.IPNet = local
case unix.IFA_BROADCAST:
addr.Broadcast = attr.Value
case unix.IFA_LABEL:
@@ -226,12 +263,24 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
}
}
- // IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
+ // libnl addr.c comment:
+ // IPv6 sends the local address as IFA_ADDRESS with no
+ // IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
+ // with IFA_ADDRESS being the peer address if they differ
+ //
+ // But obviously, as there are IPv6 PtP addresses, too,
+ // IFA_LOCAL should also be handled for IPv6.
if local != nil {
- addr.IPNet = local
+ if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
+ addr.IPNet = dst
+ } else {
+ addr.IPNet = local
+ addr.Peer = dst
+ }
} else {
addr.IPNet = dst
}
+
addr.Scope = int(msg.Scope)
return
@@ -250,21 +299,22 @@ type AddrUpdate struct {
// AddrSubscribe takes a chan down which notifications will be sent
// when addresses change. Close the 'done' chan to stop subscription.
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
- return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
+ return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0)
}
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
// to choose the network namespace in which to subscribe (ns).
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
- return addrSubscribeAt(ns, netns.None(), ch, done, nil, false)
+ return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0)
}
// AddrSubscribeOptions contains a set of options to use with
// AddrSubscribeWithOptions.
type AddrSubscribeOptions struct {
- Namespace *netns.NsHandle
- ErrorCallback func(error)
- ListExisting bool
+ Namespace *netns.NsHandle
+ ErrorCallback func(error)
+ ListExisting bool
+ ReceiveBufferSize int
}
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
@@ -275,10 +325,10 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
none := netns.None()
options.Namespace = &none
}
- return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
+ return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize)
}
-func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
+func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error {
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
if err != nil {
return err
@@ -289,6 +339,12 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
s.Close()
}()
}
+ if rcvbuf != 0 {
+ err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false)
+ if err != nil {
+ return err
+ }
+ }
if listExisting {
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
unix.NLM_F_DUMP)
@@ -301,13 +357,19 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
go func() {
defer close(ch)
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
cberr(err)
}
return
}
+ if from.Pid != nl.PidKernel {
+ if cberr != nil {
+ cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
+ }
+ continue
+ }
for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE {
continue
@@ -319,16 +381,17 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
msgType := m.Header.Type
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
if cberr != nil {
cberr(fmt.Errorf("bad message type: %d", msgType))
}
- return
+ continue
}
addr, _, ifindex, err := parseAddr(m.Data)
@@ -336,7 +399,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
if cberr != nil {
cberr(fmt.Errorf("could not parse address: %v", err))
}
- return
+ continue
}
ch <- AddrUpdate{LinkAddress: *addr.IPNet,
diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go
index 350ab0db4..6e1224c47 100644
--- a/vendor/github.com/vishvananda/netlink/bridge_linux.go
+++ b/vendor/github.com/vishvananda/netlink/bridge_linux.go
@@ -96,7 +96,7 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
flags |= nl.BRIDGE_FLAGS_MASTER
}
if flags > 0 {
- nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
+ br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
}
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
if pvid {
@@ -105,11 +105,8 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
if untagged {
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
}
- nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
+ br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
req.AddData(br)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
- if err != nil {
- return err
- }
- return nil
+ return err
}
diff --git a/vendor/github.com/vishvananda/netlink/class.go b/vendor/github.com/vishvananda/netlink/class.go
index 8ee13af48..dcc22d9e9 100644
--- a/vendor/github.com/vishvananda/netlink/class.go
+++ b/vendor/github.com/vishvananda/netlink/class.go
@@ -4,25 +4,76 @@ import (
"fmt"
)
+// Class interfaces for all classes
type Class interface {
Attrs() *ClassAttrs
Type() string
}
+// Generic networking statistics for netlink users.
+// This file contains "gnet_" prefixed structs and relevant functions.
+// See Documentation/networking/getn_stats.txt in Linux source code for more details.
+
+// GnetStatsBasic Ref: struct gnet_stats_basic { ... }
+type GnetStatsBasic struct {
+ Bytes uint64 // number of seen bytes
+ Packets uint32 // number of seen packets
+}
+
+// GnetStatsRateEst Ref: struct gnet_stats_rate_est { ... }
+type GnetStatsRateEst struct {
+ Bps uint32 // current byte rate
+ Pps uint32 // current packet rate
+}
+
+// GnetStatsRateEst64 Ref: struct gnet_stats_rate_est64 { ... }
+type GnetStatsRateEst64 struct {
+ Bps uint64 // current byte rate
+ Pps uint64 // current packet rate
+}
+
+// GnetStatsQueue Ref: struct gnet_stats_queue { ... }
+type GnetStatsQueue struct {
+ Qlen uint32 // queue length
+ Backlog uint32 // backlog size of queue
+ Drops uint32 // number of dropped packets
+ Requeues uint32 // number of requues
+ Overlimits uint32 // number of enqueues over the limit
+}
+
+// ClassStatistics representation based on generic networking statistics for netlink.
+// See Documentation/networking/gen_stats.txt in Linux source code for more details.
+type ClassStatistics struct {
+ Basic *GnetStatsBasic
+ Queue *GnetStatsQueue
+ RateEst *GnetStatsRateEst
+}
+
+// NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0.
+func NewClassStatistics() *ClassStatistics {
+ return &ClassStatistics{
+ Basic: &GnetStatsBasic{},
+ Queue: &GnetStatsQueue{},
+ RateEst: &GnetStatsRateEst{},
+ }
+}
+
// ClassAttrs represents a netlink class. A filter is associated with a link,
// has a handle and a parent. The root filter of a device should have a
// parent == HANDLE_ROOT.
type ClassAttrs struct {
- LinkIndex int
- Handle uint32
- Parent uint32
- Leaf uint32
+ LinkIndex int
+ Handle uint32
+ Parent uint32
+ Leaf uint32
+ Statistics *ClassStatistics
}
func (q ClassAttrs) String() string {
return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf)
}
+// HtbClassAttrs stores the attributes of HTB class
type HtbClassAttrs struct {
// TODO handle all attributes
Rate uint64
@@ -54,10 +105,12 @@ func (q HtbClass) String() string {
return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer)
}
+// Attrs returns the class attributes
func (q *HtbClass) Attrs() *ClassAttrs {
return &q.ClassAttrs
}
+// Type return the class type
func (q *HtbClass) Type() string {
return "htb"
}
@@ -69,10 +122,90 @@ type GenericClass struct {
ClassType string
}
+// Attrs return the class attributes
func (class *GenericClass) Attrs() *ClassAttrs {
return &class.ClassAttrs
}
+// Type return the class type
func (class *GenericClass) Type() string {
return class.ClassType
}
+
+// ServiceCurve is the way the HFSC curve are represented
+type ServiceCurve struct {
+ m1 uint32
+ d uint32
+ m2 uint32
+}
+
+// Attrs return the parameters of the service curve
+func (c *ServiceCurve) Attrs() (uint32, uint32, uint32) {
+ return c.m1, c.d, c.m2
+}
+
+// HfscClass is a representation of the HFSC class
+type HfscClass struct {
+ ClassAttrs
+ Rsc ServiceCurve
+ Fsc ServiceCurve
+ Usc ServiceCurve
+}
+
+// SetUsc sets the Usc curve
+func (hfsc *HfscClass) SetUsc(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// SetFsc sets the Fsc curve
+func (hfsc *HfscClass) SetFsc(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// SetRsc sets the Rsc curve
+func (hfsc *HfscClass) SetRsc(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// SetSC implements the SC from the tc CLI
+func (hfsc *HfscClass) SetSC(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+ hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// SetUL implements the UL from the tc CLI
+func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// SetLS implements the LS from the tc CLI
+func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) {
+ hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8}
+}
+
+// NewHfscClass returns a new HFSC struct with the set parameters
+func NewHfscClass(attrs ClassAttrs) *HfscClass {
+ return &HfscClass{
+ ClassAttrs: attrs,
+ Rsc: ServiceCurve{},
+ Fsc: ServiceCurve{},
+ Usc: ServiceCurve{},
+ }
+}
+
+func (hfsc *HfscClass) String() string {
+ return fmt.Sprintf(
+ "{%s -- {RSC: {m1=%d d=%d m2=%d}} {FSC: {m1=%d d=%d m2=%d}} {USC: {m1=%d d=%d m2=%d}}}",
+ hfsc.Attrs(), hfsc.Rsc.m1*8, hfsc.Rsc.d, hfsc.Rsc.m2*8, hfsc.Fsc.m1*8, hfsc.Fsc.d, hfsc.Fsc.m2*8, hfsc.Usc.m1*8, hfsc.Usc.d, hfsc.Usc.m2*8,
+ )
+}
+
+// Attrs return the Hfsc parameters
+func (hfsc *HfscClass) Attrs() *ClassAttrs {
+ return &hfsc.ClassAttrs
+}
+
+// Type return the type of the class
+func (hfsc *HfscClass) Type() string {
+ return "hfsc"
+}
diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go
index a4997740e..31091e501 100644
--- a/vendor/github.com/vishvananda/netlink/class_linux.go
+++ b/vendor/github.com/vishvananda/netlink/class_linux.go
@@ -1,14 +1,34 @@
package netlink
import (
+ "bytes"
+ "encoding/binary"
+ "encoding/hex"
"errors"
+ "fmt"
"syscall"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
-// NOTE: function is in here because it uses other linux functions
+// Internal tc_stats representation in Go struct.
+// This is for internal uses only to deserialize the payload of rtattr.
+// After the deserialization, this should be converted into the canonical stats
+// struct, ClassStatistics, in case of statistics of a class.
+// Ref: struct tc_stats { ... }
+type tcStats struct {
+ Bytes uint64 // Number of enqueued bytes
+ Packets uint32 // Number of enqueued packets
+ Drops uint32 // Packets dropped because of lack of resources
+ Overlimits uint32 // Number of throttle events when this flow goes out of allocated bandwidth
+ Bps uint32 // Current flow byte rate
+ Pps uint32 // Current flow packet rate
+ Qlen uint32
+ Backlog uint32
+}
+
+// NewHtbClass NOTE: function is in here because it uses other linux functions
func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
mtu := 1600
rate := cattrs.Rate / 8
@@ -126,7 +146,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
- if htb, ok := class.(*HtbClass); ok {
+ switch class.Type() {
+ case "htb":
+ htb := class.(*HtbClass)
opt := nl.TcHtbCopt{}
opt.Buffer = htb.Buffer
opt.Cbuffer = htb.Cbuffer
@@ -151,9 +173,18 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
return errors.New("HTB: failed to calculate ceil rate table")
}
opt.Ceil = tcceil
- nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
- nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab))
- nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab))
+ options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize())
+ options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab))
+ options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab))
+ case "hfsc":
+ hfsc := class.(*HfscClass)
+ opt := nl.HfscCopt{}
+ opt.Rsc.Set(hfsc.Rsc.Attrs())
+ opt.Fsc.Set(hfsc.Fsc.Attrs())
+ opt.Usc.Set(hfsc.Usc.Attrs())
+ options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
+ options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
+ options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
}
req.AddData(options)
return nil
@@ -197,9 +228,10 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
}
base := ClassAttrs{
- LinkIndex: int(msg.Ifindex),
- Handle: msg.Handle,
- Parent: msg.Parent,
+ LinkIndex: int(msg.Ifindex),
+ Handle: msg.Handle,
+ Parent: msg.Parent,
+ Statistics: nil,
}
var class Class
@@ -211,6 +243,8 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
switch classType {
case "htb":
class = &HtbClass{}
+ case "hfsc":
+ class = &HfscClass{}
default:
class = &GenericClass{ClassType: classType}
}
@@ -225,6 +259,26 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
if err != nil {
return nil, err
}
+ case "hfsc":
+ data, err := nl.ParseRouteAttr(attr.Value)
+ if err != nil {
+ return nil, err
+ }
+ _, err = parseHfscClassData(class, data)
+ if err != nil {
+ return nil, err
+ }
+ }
+ // For backward compatibility.
+ case nl.TCA_STATS:
+ base.Statistics, err = parseTcStats(attr.Value)
+ if err != nil {
+ return nil, err
+ }
+ case nl.TCA_STATS2:
+ base.Statistics, err = parseTcStats2(attr.Value)
+ if err != nil {
+ return nil, err
}
}
}
@@ -253,3 +307,78 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro
}
return detailed, nil
}
+
+func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) {
+ hfsc := class.(*HfscClass)
+ detailed := false
+ for _, datum := range data {
+ m1, d, m2 := nl.DeserializeHfscCurve(datum.Value).Attrs()
+ switch datum.Attr.Type {
+ case nl.TCA_HFSC_RSC:
+ hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2}
+ case nl.TCA_HFSC_FSC:
+ hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2}
+ case nl.TCA_HFSC_USC:
+ hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2}
+ }
+ }
+ return detailed, nil
+}
+
+func parseTcStats(data []byte) (*ClassStatistics, error) {
+ buf := &bytes.Buffer{}
+ buf.Write(data)
+ native := nl.NativeEndian()
+ tcStats := &tcStats{}
+ if err := binary.Read(buf, native, tcStats); err != nil {
+ return nil, err
+ }
+
+ stats := NewClassStatistics()
+ stats.Basic.Bytes = tcStats.Bytes
+ stats.Basic.Packets = tcStats.Packets
+ stats.Queue.Qlen = tcStats.Qlen
+ stats.Queue.Backlog = tcStats.Backlog
+ stats.Queue.Drops = tcStats.Drops
+ stats.Queue.Overlimits = tcStats.Overlimits
+ stats.RateEst.Bps = tcStats.Bps
+ stats.RateEst.Pps = tcStats.Pps
+
+ return stats, nil
+}
+
+func parseGnetStats(data []byte, gnetStats interface{}) error {
+ buf := &bytes.Buffer{}
+ buf.Write(data)
+ native := nl.NativeEndian()
+ return binary.Read(buf, native, gnetStats)
+}
+
+func parseTcStats2(data []byte) (*ClassStatistics, error) {
+ rtAttrs, err := nl.ParseRouteAttr(data)
+ if err != nil {
+ return nil, err
+ }
+ stats := NewClassStatistics()
+ for _, datum := range rtAttrs {
+ switch datum.Attr.Type {
+ case nl.TCA_STATS_BASIC:
+ if err := parseGnetStats(datum.Value, stats.Basic); err != nil {
+ return nil, fmt.Errorf("Failed to parse ClassStatistics.Basic with: %v\n%s",
+ err, hex.Dump(datum.Value))
+ }
+ case nl.TCA_STATS_QUEUE:
+ if err := parseGnetStats(datum.Value, stats.Queue); err != nil {
+ return nil, fmt.Errorf("Failed to parse ClassStatistics.Queue with: %v\n%s",
+ err, hex.Dump(datum.Value))
+ }
+ case nl.TCA_STATS_RATE_EST:
+ if err := parseGnetStats(datum.Value, stats.RateEst); err != nil {
+ return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s",
+ err, hex.Dump(datum.Value))
+ }
+ }
+ }
+
+ return stats, nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
index a0fc74a37..4bff0dcba 100644
--- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
@@ -22,11 +22,7 @@ const (
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
ConntrackExpectTable = 2
)
-const (
- // For Parsing Mark
- TCP_PROTO = 6
- UDP_PROTO = 17
-)
+
const (
// backward compatibility with golang 1.6 which does not have io.SeekCurrent
seekCurrent = 1
@@ -135,11 +131,13 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h
// For the time being, the structure below allows to parse and extract the base information of a flow
type ipTuple struct {
- SrcIP net.IP
+ Bytes uint64
DstIP net.IP
+ DstPort uint16
+ Packets uint64
Protocol uint8
+ SrcIP net.IP
SrcPort uint16
- DstPort uint16
}
type ConntrackFlow struct {
@@ -151,11 +149,12 @@ type ConntrackFlow struct {
func (s *ConntrackFlow) String() string {
// conntrack cmd output:
- // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 mark=0
- return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d\tsrc=%s dst=%s sport=%d dport=%d mark=%d",
+ // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
+ return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d",
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
- s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort,
- s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Mark)
+ s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
+ s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
+ s.Mark)
}
// This method parse the ip tuple structure
@@ -220,9 +219,35 @@ func parseBERaw16(r *bytes.Reader, v *uint16) {
binary.Read(r, binary.BigEndian, v)
}
+func parseBERaw32(r *bytes.Reader, v *uint32) {
+ binary.Read(r, binary.BigEndian, v)
+}
+
+func parseBERaw64(r *bytes.Reader, v *uint64) {
+ binary.Read(r, binary.BigEndian, v)
+}
+
+func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
+ for i := 0; i < 2; i++ {
+ switch _, t, _ := parseNfAttrTL(r); t {
+ case nl.CTA_COUNTERS_BYTES:
+ parseBERaw64(r, &bytes)
+ case nl.CTA_COUNTERS_PACKETS:
+ parseBERaw64(r, &packets)
+ default:
+ return
+ }
+ }
+ return
+}
+
+func parseConnectionMark(r *bytes.Reader) (mark uint32) {
+ parseBERaw32(r, &mark)
+ return
+}
+
func parseRawData(data []byte) *ConntrackFlow {
s := &ConntrackFlow{}
- var proto uint8
// First there is the Nfgenmsg header
// consume only the family field
reader := bytes.NewReader(data)
@@ -238,36 +263,31 @@ func parseRawData(data []byte) *ConntrackFlow {
// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes
// flow information of the reverse flow
for reader.Len() > 0 {
- nested, t, l := parseNfAttrTL(reader)
- if nested && t == nl.CTA_TUPLE_ORIG {
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
- proto = parseIpTuple(reader, &s.Forward)
+ if nested, t, l := parseNfAttrTL(reader); nested {
+ switch t {
+ case nl.CTA_TUPLE_ORIG:
+ if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ parseIpTuple(reader, &s.Forward)
+ }
+ case nl.CTA_TUPLE_REPLY:
+ if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ parseIpTuple(reader, &s.Reverse)
+ } else {
+ // Header not recognized skip it
+ reader.Seek(int64(l), seekCurrent)
+ }
+ case nl.CTA_COUNTERS_ORIG:
+ s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader)
+ case nl.CTA_COUNTERS_REPLY:
+ s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
}
- } else if nested && t == nl.CTA_TUPLE_REPLY {
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
- parseIpTuple(reader, &s.Reverse)
-
- // Got all the useful information stop parsing
- break
- } else {
- // Header not recognized skip it
- reader.Seek(int64(l), seekCurrent)
+ } else {
+ switch t {
+ case nl.CTA_MARK:
+ s.Mark = parseConnectionMark(reader)
}
}
}
- if proto == TCP_PROTO {
- reader.Seek(64, seekCurrent)
- _, t, _, v := parseNfAttrTLV(reader)
- if t == nl.CTA_MARK {
- s.Mark = uint32(v[3])
- }
- } else if proto == UDP_PROTO {
- reader.Seek(16, seekCurrent)
- _, t, _, v := parseNfAttrTLV(reader)
- if t == nl.CTA_MARK {
- s.Mark = uint32(v[3])
- }
- }
return s
}
@@ -285,7 +305,7 @@ func parseRawData(data []byte) *ConntrackFlow {
// Common parameters and options:
// -s, --src, --orig-src ip Source address from original direction
// -d, --dst, --orig-dst ip Destination address from original direction
-// -r, --reply-src ip Source addres from reply direction
+// -r, --reply-src ip Source address from reply direction
// -q, --reply-dst ip Destination address from reply direction
// -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
// -f, --family proto Layer 3 Protocol, eg. 'ipv6'
@@ -302,11 +322,14 @@ func parseRawData(data []byte) *ConntrackFlow {
type ConntrackFilterType uint8
const (
- ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
- ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
- ConntrackNatSrcIP // -src-nat ip Source NAT ip
- ConntrackNatDstIP // -dst-nat ip Destination NAT ip
- ConntrackNatAnyIP // -any-nat ip Source or destination NAT ip
+ ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
+ ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
+ ConntrackReplySrcIP // --reply-src ip Reply Source IP
+ ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
+ ConntrackReplyAnyIP // Match source or destination reply IP
+ ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
+ ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
+ ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instaed ConntrackReplyAnyIP
)
type CustomConntrackFilter interface {
@@ -351,17 +374,17 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
}
// -src-nat ip Source NAT ip
- if elem, found := f.ipFilter[ConntrackNatSrcIP]; match && found {
+ if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found {
match = match && elem.Equal(flow.Reverse.SrcIP)
}
// -dst-nat ip Destination NAT ip
- if elem, found := f.ipFilter[ConntrackNatDstIP]; match && found {
+ if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found {
match = match && elem.Equal(flow.Reverse.DstIP)
}
- // -any-nat ip Source or destination NAT ip
- if elem, found := f.ipFilter[ConntrackNatAnyIP]; match && found {
+ // Match source or destination reply IP
+ if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
}
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
new file mode 100644
index 000000000..29b3f8ec1
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -0,0 +1,272 @@
+package netlink
+
+import (
+ "syscall"
+
+ "fmt"
+ "github.com/vishvananda/netlink/nl"
+ "golang.org/x/sys/unix"
+)
+
+// DevlinkDevEswitchAttr represents device's eswitch attributes
+type DevlinkDevEswitchAttr struct {
+ Mode string
+ InlineMode string
+ EncapMode string
+}
+
+// DevlinkDevAttrs represents device attributes
+type DevlinkDevAttrs struct {
+ Eswitch DevlinkDevEswitchAttr
+}
+
+// DevlinkDevice represents device and its attributes
+type DevlinkDevice struct {
+ BusName string
+ DeviceName string
+ Attrs DevlinkDevAttrs
+}
+
+func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
+ devices := make([]*DevlinkDevice, 0, len(msgs))
+ for _, m := range msgs {
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ dev := &DevlinkDevice{}
+ if err = dev.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ devices = append(devices, dev)
+ }
+ return devices, nil
+}
+
+func eswitchStringToMode(modeName string) (uint16, error) {
+ if modeName == "legacy" {
+ return nl.DEVLINK_ESWITCH_MODE_LEGACY, nil
+ } else if modeName == "switchdev" {
+ return nl.DEVLINK_ESWITCH_MODE_SWITCHDEV, nil
+ } else {
+ return 0xffff, fmt.Errorf("invalid switchdev mode")
+ }
+}
+
+func parseEswitchMode(mode uint16) string {
+ var eswitchMode = map[uint16]string{
+ nl.DEVLINK_ESWITCH_MODE_LEGACY: "legacy",
+ nl.DEVLINK_ESWITCH_MODE_SWITCHDEV: "switchdev",
+ }
+ if eswitchMode[mode] == "" {
+ return "unknown"
+ } else {
+ return eswitchMode[mode]
+ }
+}
+
+func parseEswitchInlineMode(inlinemode uint8) string {
+ var eswitchInlineMode = map[uint8]string{
+ nl.DEVLINK_ESWITCH_INLINE_MODE_NONE: "none",
+ nl.DEVLINK_ESWITCH_INLINE_MODE_LINK: "link",
+ nl.DEVLINK_ESWITCH_INLINE_MODE_NETWORK: "network",
+ nl.DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT: "transport",
+ }
+ if eswitchInlineMode[inlinemode] == "" {
+ return "unknown"
+ } else {
+ return eswitchInlineMode[inlinemode]
+ }
+}
+
+func parseEswitchEncapMode(encapmode uint8) string {
+ var eswitchEncapMode = map[uint8]string{
+ nl.DEVLINK_ESWITCH_ENCAP_MODE_NONE: "disable",
+ nl.DEVLINK_ESWITCH_ENCAP_MODE_BASIC: "enable",
+ }
+ if eswitchEncapMode[encapmode] == "" {
+ return "unknown"
+ } else {
+ return eswitchEncapMode[encapmode]
+ }
+}
+
+func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
+ for _, a := range attrs {
+ switch a.Attr.Type {
+ case nl.DEVLINK_ATTR_BUS_NAME:
+ d.BusName = string(a.Value)
+ case nl.DEVLINK_ATTR_DEV_NAME:
+ d.DeviceName = string(a.Value)
+ case nl.DEVLINK_ATTR_ESWITCH_MODE:
+ d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
+ case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
+ d.Attrs.Eswitch.InlineMode = parseEswitchInlineMode(uint8(a.Value[0]))
+ case nl.DEVLINK_ATTR_ESWITCH_ENCAP_MODE:
+ d.Attrs.Eswitch.EncapMode = parseEswitchEncapMode(uint8(a.Value[0]))
+ }
+ }
+ return nil
+}
+
+func (dev *DevlinkDevice) parseEswitchAttrs(msgs [][]byte) {
+ m := msgs[0]
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return
+ }
+ dev.parseAttributes(attrs)
+}
+
+func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
+ msg := &nl.Genlmsg{
+ Command: nl.DEVLINK_CMD_ESWITCH_GET,
+ Version: nl.GENL_DEVLINK_VERSION,
+ }
+ req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
+ req.AddData(msg)
+
+ b := make([]byte, len(dev.BusName))
+ copy(b, dev.BusName)
+ data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
+ req.AddData(data)
+
+ b = make([]byte, len(dev.DeviceName))
+ copy(b, dev.DeviceName)
+ data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
+ req.AddData(data)
+
+ msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return
+ }
+ dev.parseEswitchAttrs(msgs)
+}
+
+// DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
+ f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
+ if err != nil {
+ return nil, err
+ }
+ msg := &nl.Genlmsg{
+ Command: nl.DEVLINK_CMD_GET,
+ Version: nl.GENL_DEVLINK_VERSION,
+ }
+ req := h.newNetlinkRequest(int(f.ID),
+ unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
+ req.AddData(msg)
+ msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ devices, err := parseDevLinkDeviceList(msgs)
+ if err != nil {
+ return nil, err
+ }
+ for _, d := range devices {
+ h.getEswitchAttrs(f, d)
+ }
+ return devices, nil
+}
+
+// DevLinkGetDeviceList provides a pointer to devlink devices and nil error,
+// otherwise returns an error code.
+func DevLinkGetDeviceList() ([]*DevlinkDevice, error) {
+ return pkgHandle.DevLinkGetDeviceList()
+}
+
+func parseDevlinkDevice(msgs [][]byte) (*DevlinkDevice, error) {
+ m := msgs[0]
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ dev := &DevlinkDevice{}
+ if err = dev.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ return dev, nil
+}
+
+func (h *Handle) createCmdReq(cmd uint8, bus string, device string) (*GenlFamily, *nl.NetlinkRequest, error) {
+ f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ msg := &nl.Genlmsg{
+ Command: cmd,
+ Version: nl.GENL_DEVLINK_VERSION,
+ }
+ req := h.newNetlinkRequest(int(f.ID),
+ unix.NLM_F_REQUEST|unix.NLM_F_ACK)
+ req.AddData(msg)
+
+ b := make([]byte, len(bus)+1)
+ copy(b, bus)
+ data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
+ req.AddData(data)
+
+ b = make([]byte, len(device)+1)
+ copy(b, device)
+ data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
+ req.AddData(data)
+
+ return f, req, nil
+}
+
+// DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
+ f, req, err := h.createCmdReq(nl.DEVLINK_CMD_GET, Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ dev, err := parseDevlinkDevice(respmsg)
+ if err == nil {
+ h.getEswitchAttrs(f, dev)
+ }
+ return dev, err
+}
+
+// DevlinkGetDeviceByName provides a pointer to devlink device and nil error,
+// otherwise returns an error code.
+func DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) {
+ return pkgHandle.DevLinkGetDeviceByName(Bus, Device)
+}
+
+// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
+// returns an error code.
+// Equivalent to: `devlink dev eswitch set $dev mode switchdev`
+// Equivalent to: `devlink dev eswitch set $dev mode legacy`
+func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
+ mode, err := eswitchStringToMode(NewMode)
+ if err != nil {
+ return err
+ }
+
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_ESWITCH_SET, Dev.BusName, Dev.DeviceName)
+ if err != nil {
+ return err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_ESWITCH_MODE, nl.Uint16Attr(mode)))
+
+ _, err = req.Execute(unix.NETLINK_GENERIC, 0)
+ return err
+}
+
+// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or
+// returns an error code.
+// Equivalent to: `devlink dev eswitch set $dev mode switchdev`
+// Equivalent to: `devlink dev eswitch set $dev mode legacy`
+func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
+ return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode)
+}
diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go
index c2cf8e4dc..88792eab0 100644
--- a/vendor/github.com/vishvananda/netlink/filter.go
+++ b/vendor/github.com/vishvananda/netlink/filter.go
@@ -2,6 +2,7 @@ package netlink
import (
"fmt"
+ "net"
)
type Filter interface {
@@ -135,6 +136,27 @@ func (action *BpfAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
+type ConnmarkAction struct {
+ ActionAttrs
+ Zone uint16
+}
+
+func (action *ConnmarkAction) Type() string {
+ return "connmark"
+}
+
+func (action *ConnmarkAction) Attrs() *ActionAttrs {
+ return &action.ActionAttrs
+}
+
+func NewConnmarkAction() *ConnmarkAction {
+ return &ConnmarkAction{
+ ActionAttrs: ActionAttrs{
+ Action: TC_ACT_PIPE,
+ },
+ }
+}
+
type MirredAct uint8
func (a MirredAct) String() string {
@@ -182,47 +204,59 @@ func NewMirredAction(redirIndex int) *MirredAction {
}
}
-// Sel of the U32 filters that contains multiple TcU32Key. This is the copy
-// and the frontend representation of nl.TcU32Sel. It is serialized into canonical
-// nl.TcU32Sel with the appropriate endianness.
-type TcU32Sel struct {
- Flags uint8
- Offshift uint8
- Nkeys uint8
- Pad uint8
- Offmask uint16
- Off uint16
- Offoff int16
- Hoff int16
- Hmask uint32
- Keys []TcU32Key
-}
-
-// TcU32Key contained of Sel in the U32 filters. This is the copy and the frontend
-// representation of nl.TcU32Key. It is serialized into chanonical nl.TcU32Sel
-// with the appropriate endianness.
-type TcU32Key struct {
- Mask uint32
- Val uint32
- Off int32
- OffMask int32
-}
-
-// U32 filters on many packet related properties
-type U32 struct {
- FilterAttrs
- ClassId uint32
- RedirIndex int
- Sel *TcU32Sel
- Actions []Action
+type TunnelKeyAct int8
+
+const (
+ TCA_TUNNEL_KEY_SET TunnelKeyAct = 1 // set tunnel key
+ TCA_TUNNEL_KEY_UNSET TunnelKeyAct = 2 // unset tunnel key
+)
+
+type TunnelKeyAction struct {
+ ActionAttrs
+ Action TunnelKeyAct
+ SrcAddr net.IP
+ DstAddr net.IP
+ KeyID uint32
}
-func (filter *U32) Attrs() *FilterAttrs {
- return &filter.FilterAttrs
+func (action *TunnelKeyAction) Type() string {
+ return "tunnel_key"
}
-func (filter *U32) Type() string {
- return "u32"
+func (action *TunnelKeyAction) Attrs() *ActionAttrs {
+ return &action.ActionAttrs
+}
+
+func NewTunnelKeyAction() *TunnelKeyAction {
+ return &TunnelKeyAction{
+ ActionAttrs: ActionAttrs{
+ Action: TC_ACT_PIPE,
+ },
+ }
+}
+
+type SkbEditAction struct {
+ ActionAttrs
+ QueueMapping *uint16
+ PType *uint16
+ Priority *uint32
+ Mark *uint32
+}
+
+func (action *SkbEditAction) Type() string {
+ return "skbedit"
+}
+
+func (action *SkbEditAction) Attrs() *ActionAttrs {
+ return &action.ActionAttrs
+}
+
+func NewSkbEditAction() *SkbEditAction {
+ return &SkbEditAction{
+ ActionAttrs: ActionAttrs{
+ Action: TC_ACT_PIPE,
+ },
+ }
}
// MatchAll filters match all packets
@@ -262,6 +296,8 @@ type BpfFilter struct {
Fd int
Name string
DirectAction bool
+ Id int
+ Tag string
}
func (filter *BpfFilter) Type() string {
diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go
index f0eac6b78..c56f314cd 100644
--- a/vendor/github.com/vishvananda/netlink/filter_linux.go
+++ b/vendor/github.com/vishvananda/netlink/filter_linux.go
@@ -3,10 +3,11 @@ package netlink
import (
"bytes"
"encoding/binary"
+ "encoding/hex"
"errors"
"fmt"
+ "net"
"syscall"
- "unsafe"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
@@ -20,6 +21,35 @@ const (
TC_U32_EAT = nl.TC_U32_EAT
)
+// Sel of the U32 filters that contains multiple TcU32Key. This is the type
+// alias and the frontend representation of nl.TcU32Sel. It is serialized into
+// canonical nl.TcU32Sel with the appropriate endianness.
+type TcU32Sel = nl.TcU32Sel
+
+// TcU32Key contained of Sel in the U32 filters. This is the type alias and the
+// frontend representation of nl.TcU32Key. It is serialized into chanonical
+// nl.TcU32Sel with the appropriate endianness.
+type TcU32Key = nl.TcU32Key
+
+// U32 filters on many packet related properties
+type U32 struct {
+ FilterAttrs
+ ClassId uint32
+ Divisor uint32 // Divisor MUST be power of 2.
+ Hash uint32
+ RedirIndex int
+ Sel *TcU32Sel
+ Actions []Action
+}
+
+func (filter *U32) Attrs() *FilterAttrs {
+ return &filter.FilterAttrs
+}
+
+func (filter *U32) Type() string {
+ return "u32"
+}
+
// Fw filter filters on firewall marks
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
// is defined in nl/tc_linux.go
@@ -123,8 +153,24 @@ func FilterAdd(filter Filter) error {
// FilterAdd will add a filter to the system.
// Equivalent to: `tc filter add $filter`
func (h *Handle) FilterAdd(filter Filter) error {
+ return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
+}
+
+// FilterReplace will replace a filter.
+// Equivalent to: `tc filter replace $filter`
+func FilterReplace(filter Filter) error {
+ return pkgHandle.FilterReplace(filter)
+}
+
+// FilterReplace will replace a filter.
+// Equivalent to: `tc filter replace $filter`
+func (h *Handle) FilterReplace(filter Filter) error {
+ return h.filterModify(filter, unix.NLM_F_CREATE)
+}
+
+func (h *Handle) filterModify(filter Filter, flags int) error {
native = nl.NativeEndian()
- req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
+ req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
@@ -140,8 +186,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
switch filter := filter.(type) {
case *U32:
- // Convert TcU32Sel into nl.TcU32Sel as it is without copy.
- sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel))
+ sel := filter.Sel
if sel == nil {
// match all
sel = &nl.TcU32Sel{
@@ -168,11 +213,20 @@ func (h *Handle) FilterAdd(filter Filter) error {
}
}
sel.Nkeys = uint8(len(sel.Keys))
- nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
+ options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
if filter.ClassId != 0 {
- nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
+ options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
+ }
+ if filter.Divisor != 0 {
+ if (filter.Divisor-1)&filter.Divisor != 0 {
+ return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor)
+ }
+ options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor))
}
- actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
+ if filter.Hash != 0 {
+ options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
+ }
+ actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
// backwards compatibility
if filter.RedirIndex != 0 {
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
@@ -184,51 +238,51 @@ func (h *Handle) FilterAdd(filter Filter) error {
if filter.Mask != 0 {
b := make([]byte, 4)
native.PutUint32(b, filter.Mask)
- nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
+ options.AddRtAttr(nl.TCA_FW_MASK, b)
}
if filter.InDev != "" {
- nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
+ options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
}
if (filter.Police != nl.TcPolice{}) {
- police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
- nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, filter.Police.Serialize())
+ police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
+ police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
if (filter.Police.Rate != nl.TcRateSpec{}) {
payload := SerializeRtab(filter.Rtab)
- nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
+ police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
}
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
payload := SerializeRtab(filter.Ptab)
- nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
+ police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
}
}
if filter.ClassId != 0 {
b := make([]byte, 4)
native.PutUint32(b, filter.ClassId)
- nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
+ options.AddRtAttr(nl.TCA_FW_CLASSID, b)
}
case *BpfFilter:
var bpfFlags uint32
if filter.ClassId != 0 {
- nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
+ options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
}
if filter.Fd >= 0 {
- nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
+ options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
}
if filter.Name != "" {
- nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
+ options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
}
if filter.DirectAction {
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
}
- nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
+ options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
case *MatchAll:
- actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil)
+ actionsAttr := options.AddRtAttr(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))
+ options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
}
}
@@ -366,34 +420,91 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
default:
return fmt.Errorf("unknown action type %s", action.Type())
case *MirredAction:
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
+ table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
mirred := nl.TcMirred{
Eaction: int32(action.MirredAction),
Ifindex: uint32(action.Ifindex),
}
toTcGen(action.Attrs(), &mirred.TcGen)
- nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize())
+ aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
+ case *TunnelKeyAction:
+ table := attr.AddRtAttr(tabIndex, nil)
+ tabIndex++
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
+ tun := nl.TcTunnelKey{
+ Action: int32(action.Action),
+ }
+ toTcGen(action.Attrs(), &tun.TcGen)
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize())
+ if action.Action == TCA_TUNNEL_KEY_SET {
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID))
+ if v4 := action.SrcAddr.To4(); v4 != nil {
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:])
+ } else if v6 := action.SrcAddr.To16(); v6 != nil {
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:])
+ } else {
+ return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr)
+ }
+ if v4 := action.DstAddr.To4(); v4 != nil {
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:])
+ } else if v6 := action.DstAddr.To16(); v6 != nil {
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:])
+ } else {
+ return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr)
+ }
+ }
+ case *SkbEditAction:
+ table := attr.AddRtAttr(tabIndex, nil)
+ tabIndex++
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
+ skbedit := nl.TcSkbEdit{}
+ toTcGen(action.Attrs(), &skbedit.TcGen)
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize())
+ if action.QueueMapping != nil {
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping))
+ }
+ if action.Priority != nil {
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority))
+ }
+ if action.PType != nil {
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType))
+ }
+ if action.Mark != nil {
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
+ }
+ case *ConnmarkAction:
+ table := attr.AddRtAttr(tabIndex, nil)
+ tabIndex++
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
+ connmark := nl.TcConnmark{
+ Zone: action.Zone,
+ }
+ toTcGen(action.Attrs(), &connmark.TcGen)
+ aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
case *BpfAction:
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
+ table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
gen := nl.TcGen{}
toTcGen(action.Attrs(), &gen)
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize())
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
+ aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
+ aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
+ aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
case *GenericAction:
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
+ table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
gen := nl.TcGen{}
toTcGen(action.Attrs(), &gen)
- nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize())
+ aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
}
}
return nil
@@ -419,8 +530,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &MirredAction{}
case "bpf":
action = &BpfAction{}
+ case "connmark":
+ action = &ConnmarkAction{}
case "gact":
action = &GenericAction{}
+ case "tunnel_key":
+ action = &TunnelKeyAction{}
+ case "skbedit":
+ action = &SkbEditAction{}
default:
break nextattr
}
@@ -435,11 +552,46 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
switch adatum.Attr.Type {
case nl.TCA_MIRRED_PARMS:
mirred := *nl.DeserializeTcMirred(adatum.Value)
- toAttrs(&mirred.TcGen, action.Attrs())
action.(*MirredAction).ActionAttrs = ActionAttrs{}
+ toAttrs(&mirred.TcGen, action.Attrs())
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
}
+ case "tunnel_key":
+ switch adatum.Attr.Type {
+ case nl.TCA_TUNNEL_KEY_PARMS:
+ tun := *nl.DeserializeTunnelKey(adatum.Value)
+ action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{}
+ toAttrs(&tun.TcGen, action.Attrs())
+ action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action)
+ case nl.TCA_TUNNEL_KEY_ENC_KEY_ID:
+ action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4])
+ case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC:
+ case nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC:
+ action.(*TunnelKeyAction).SrcAddr = net.IP(adatum.Value[:])
+ case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST:
+ case nl.TCA_TUNNEL_KEY_ENC_IPV4_DST:
+ action.(*TunnelKeyAction).DstAddr = net.IP(adatum.Value[:])
+ }
+ case "skbedit":
+ switch adatum.Attr.Type {
+ case nl.TCA_SKBEDIT_PARMS:
+ skbedit := *nl.DeserializeSkbEdit(adatum.Value)
+ action.(*SkbEditAction).ActionAttrs = ActionAttrs{}
+ toAttrs(&skbedit.TcGen, action.Attrs())
+ case nl.TCA_SKBEDIT_MARK:
+ mark := native.Uint32(adatum.Value[0:4])
+ action.(*SkbEditAction).Mark = &mark
+ case nl.TCA_SKBEDIT_PRIORITY:
+ priority := native.Uint32(adatum.Value[0:4])
+ action.(*SkbEditAction).Priority = &priority
+ case nl.TCA_SKBEDIT_PTYPE:
+ ptype := native.Uint16(adatum.Value[0:2])
+ action.(*SkbEditAction).PType = &ptype
+ case nl.TCA_SKBEDIT_QUEUE_MAPPING:
+ mapping := native.Uint16(adatum.Value[0:2])
+ action.(*SkbEditAction).QueueMapping = &mapping
+ }
case "bpf":
switch adatum.Attr.Type {
case nl.TCA_ACT_BPF_PARMS:
@@ -450,6 +602,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
case nl.TCA_ACT_BPF_NAME:
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
}
+ case "connmark":
+ switch adatum.Attr.Type {
+ case nl.TCA_CONNMARK_PARMS:
+ connmark := *nl.DeserializeTcConnmark(adatum.Value)
+ action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
+ toAttrs(&connmark.TcGen, action.Attrs())
+ action.(*ConnmarkAction).Zone = connmark.Zone
+ }
case "gact":
switch adatum.Attr.Type {
case nl.TCA_GACT_PARMS:
@@ -474,7 +634,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
case nl.TCA_U32_SEL:
detailed = true
sel := nl.DeserializeTcU32Sel(datum.Value)
- u32.Sel = (*TcU32Sel)(unsafe.Pointer(sel))
+ u32.Sel = sel
if native != networkOrder {
// Handle the endianness of attributes
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
@@ -500,6 +660,10 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
}
case nl.TCA_U32_CLASSID:
u32.ClassId = native.Uint32(datum.Value)
+ case nl.TCA_U32_DIVISOR:
+ u32.Divisor = native.Uint32(datum.Value)
+ case nl.TCA_U32_HASH:
+ u32.Hash = native.Uint32(datum.Value)
}
}
return detailed, nil
@@ -551,6 +715,10 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
bpf.DirectAction = true
}
+ case nl.TCA_BPF_ID:
+ bpf.Id = int(native.Uint32(datum.Value[0:4]))
+ case nl.TCA_BPF_TAG:
+ bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1])
}
}
return detailed, nil
diff --git a/vendor/github.com/vishvananda/netlink/fou_linux.go b/vendor/github.com/vishvananda/netlink/fou_linux.go
index 62d59bd2d..ed55b2b79 100644
--- a/vendor/github.com/vishvananda/netlink/fou_linux.go
+++ b/vendor/github.com/vishvananda/netlink/fou_linux.go
@@ -90,11 +90,7 @@ func (h *Handle) FouAdd(f Fou) error {
req.AddRawData(raw)
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
- if err != nil {
- return err
- }
-
- return nil
+ return err
}
func FouDel(f Fou) error {
diff --git a/vendor/github.com/vishvananda/netlink/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/genetlink_linux.go
index ce7969907..772e5834a 100644
--- a/vendor/github.com/vishvananda/netlink/genetlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/genetlink_linux.go
@@ -157,6 +157,9 @@ func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
return nil, err
}
families, err := parseFamilies(msgs)
+ if err != nil {
+ return nil, err
+ }
if len(families) != 1 {
return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
}
diff --git a/vendor/github.com/vishvananda/netlink/go.mod b/vendor/github.com/vishvananda/netlink/go.mod
new file mode 100644
index 000000000..09ee60e77
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/go.mod
@@ -0,0 +1,8 @@
+module github.com/vishvananda/netlink
+
+go 1.12
+
+require (
+ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
+ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444
+)
diff --git a/vendor/github.com/vishvananda/netlink/go.sum b/vendor/github.com/vishvananda/netlink/go.sum
new file mode 100644
index 000000000..402d14ec5
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/go.sum
@@ -0,0 +1,4 @@
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
+golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
+golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go
index 9f6d7fe0f..26887b759 100644
--- a/vendor/github.com/vishvananda/netlink/handle_linux.go
+++ b/vendor/github.com/vishvananda/netlink/handle_linux.go
@@ -91,7 +91,7 @@ func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
return results, nil
}
-// NewHandle returns a netlink handle on the network namespace
+// NewHandleAt returns a netlink handle on the network namespace
// specified by ns. If ns=netns.None(), current network namespace
// will be assumed
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
index 915b765de..ef914dcb8 100644
--- a/vendor/github.com/vishvananda/netlink/handle_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
@@ -73,10 +73,18 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented
}
+func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
+ return ErrNotImplemented
+}
+
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
+func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
+ return ErrNotImplemented
+}
+
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
return ErrNotImplemented
}
@@ -149,6 +157,10 @@ func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
return ErrNotImplemented
}
+func (h *Handle) LinkSetGroup(link Link, group int) error {
+ return ErrNotImplemented
+}
+
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/ioctl_linux.go b/vendor/github.com/vishvananda/netlink/ioctl_linux.go
index a8503126d..4d33db5da 100644
--- a/vendor/github.com/vishvananda/netlink/ioctl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/ioctl_linux.go
@@ -56,18 +56,10 @@ type ethtoolSset struct {
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
+ // Followed by nStats * []uint64.
}
// newIocltSlaveReq returns filled IfreqSlave with proper interface names
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index fe74ffab9..886d88d1b 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -4,6 +4,7 @@ import (
"fmt"
"net"
"os"
+ "strconv"
)
// Link represents a link device from netlink. Shared link attributes
@@ -41,6 +42,29 @@ type LinkAttrs struct {
NetNsID int
NumTxQueues int
NumRxQueues int
+ GSOMaxSize uint32
+ GSOMaxSegs uint32
+ Vfs []VfInfo // virtual functions available on link
+ Group uint32
+ Slave LinkSlave
+}
+
+// LinkSlave represents a slave device.
+type LinkSlave interface {
+ SlaveType() string
+}
+
+// VfInfo represents configuration of virtual function
+type VfInfo struct {
+ ID int
+ Mac net.HardwareAddr
+ Vlan int
+ Qos int
+ TxRate int // IFLA_VF_TX_RATE Max TxRate
+ Spoofchk bool
+ LinkState uint32
+ MaxTxRate uint32 // IFLA_VF_RATE Max TxRate
+ MinTxRate uint32 // IFLA_VF_RATE Min TxRate
}
// LinkOperState represents the values of the IFLA_OPERSTATE link
@@ -223,6 +247,7 @@ type Bridge struct {
LinkAttrs
MulticastSnooping *bool
HelloTime *uint32
+ VlanFiltering *bool
}
func (bridge *Bridge) Attrs() *LinkAttrs {
@@ -236,7 +261,8 @@ func (bridge *Bridge) Type() string {
// Vlan links have ParentIndex set in their Attrs()
type Vlan struct {
LinkAttrs
- VlanId int
+ VlanId int
+ VlanProtocol VlanProtocol
}
func (vlan *Vlan) Attrs() *LinkAttrs {
@@ -290,10 +316,13 @@ type TuntapFlag uint16
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
type Tuntap struct {
LinkAttrs
- Mode TuntapMode
- Flags TuntapFlag
- Queues int
- Fds []*os.File
+ Mode TuntapMode
+ Flags TuntapFlag
+ NonPersist bool
+ Queues int
+ Fds []*os.File
+ Owner uint32
+ Group uint32
}
func (tuntap *Tuntap) Attrs() *LinkAttrs {
@@ -307,7 +336,8 @@ func (tuntap *Tuntap) Type() string {
// Veth devices must specify PeerName on create
type Veth struct {
LinkAttrs
- PeerName string // veth on create only
+ PeerName string // veth on create only
+ PeerHardwareAddr net.HardwareAddr
}
func (veth *Veth) Attrs() *LinkAttrs {
@@ -376,9 +406,18 @@ const (
IPVLAN_MODE_MAX
)
+type IPVlanFlag uint16
+
+const (
+ IPVLAN_FLAG_BRIDGE IPVlanFlag = iota
+ IPVLAN_FLAG_PRIVATE
+ IPVLAN_FLAG_VEPA
+)
+
type IPVlan struct {
LinkAttrs
Mode IPVlanMode
+ Flag IPVlanFlag
}
func (ipvlan *IPVlan) Attrs() *LinkAttrs {
@@ -389,6 +428,43 @@ func (ipvlan *IPVlan) Type() string {
return "ipvlan"
}
+// VlanProtocol type
+type VlanProtocol int
+
+func (p VlanProtocol) String() string {
+ s, ok := VlanProtocolToString[p]
+ if !ok {
+ return fmt.Sprintf("VlanProtocol(%d)", p)
+ }
+ return s
+}
+
+// StringToVlanProtocol returns vlan protocol, or unknown is the s is invalid.
+func StringToVlanProtocol(s string) VlanProtocol {
+ mode, ok := StringToVlanProtocolMap[s]
+ if !ok {
+ return VLAN_PROTOCOL_UNKNOWN
+ }
+ return mode
+}
+
+// VlanProtocol possible values
+const (
+ VLAN_PROTOCOL_UNKNOWN VlanProtocol = 0
+ VLAN_PROTOCOL_8021Q VlanProtocol = 0x8100
+ VLAN_PROTOCOL_8021AD VlanProtocol = 0x88A8
+)
+
+var VlanProtocolToString = map[VlanProtocol]string{
+ VLAN_PROTOCOL_8021Q: "802.1q",
+ VLAN_PROTOCOL_8021AD: "802.1ad",
+}
+
+var StringToVlanProtocolMap = map[string]VlanProtocol{
+ "802.1q": VLAN_PROTOCOL_8021Q,
+ "802.1ad": VLAN_PROTOCOL_8021AD,
+}
+
// BondMode type
type BondMode int
@@ -400,7 +476,7 @@ func (b BondMode) String() string {
return s
}
-// StringToBondMode returns bond mode, or uknonw is the s is invalid.
+// StringToBondMode returns bond mode, or unknown is the s is invalid.
func StringToBondMode(s string) BondMode {
mode, ok := StringToBondModeMap[s]
if !ok {
@@ -491,7 +567,7 @@ func (b BondXmitHashPolicy) String() string {
return s
}
-// StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid.
+// StringToBondXmitHashPolicy returns bond lacp arte, or unknown is the s is invalid.
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
lacp, ok := StringToBondXmitHashPolicyMap[s]
if !ok {
@@ -536,7 +612,7 @@ func (b BondLacpRate) String() string {
return s
}
-// StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid.
+// StringToBondLacpRate returns bond lacp arte, or unknown is the s is invalid.
func StringToBondLacpRate(s string) BondLacpRate {
lacp, ok := StringToBondLacpRateMap[s]
if !ok {
@@ -680,6 +756,67 @@ func (bond *Bond) Type() string {
return "bond"
}
+// BondSlaveState represents the values of the IFLA_BOND_SLAVE_STATE bond slave
+// attribute, which contains the state of the bond slave.
+type BondSlaveState uint8
+
+const (
+ BondStateActive = iota // Link is active.
+ BondStateBackup // Link is backup.
+)
+
+func (s BondSlaveState) String() string {
+ switch s {
+ case BondStateActive:
+ return "ACTIVE"
+ case BondStateBackup:
+ return "BACKUP"
+ default:
+ return strconv.Itoa(int(s))
+ }
+}
+
+// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
+// attribute, which contains the status of MII link monitoring
+type BondSlaveMiiStatus uint8
+
+const (
+ BondLinkUp = iota // link is up and running.
+ BondLinkFail // link has just gone down.
+ BondLinkDown // link has been down for too long time.
+ BondLinkBack // link is going back.
+)
+
+func (s BondSlaveMiiStatus) String() string {
+ switch s {
+ case BondLinkUp:
+ return "UP"
+ case BondLinkFail:
+ return "GOING_DOWN"
+ case BondLinkDown:
+ return "DOWN"
+ case BondLinkBack:
+ return "GOING_BACK"
+ default:
+ return strconv.Itoa(int(s))
+ }
+}
+
+type BondSlave struct {
+ State BondSlaveState
+ MiiStatus BondSlaveMiiStatus
+ LinkFailureCount uint32
+ PermHardwareAddr net.HardwareAddr
+ QueueId uint16
+ AggregatorId uint16
+ AdActorOperPortState uint8
+ AdPartnerOperPortState uint16
+}
+
+func (b *BondSlave) SlaveType() string {
+ return "bond"
+}
+
// Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct {
LinkAttrs
@@ -734,6 +871,27 @@ func (iptun *Iptun) Type() string {
return "ipip"
}
+type Ip6tnl struct {
+ LinkAttrs
+ Link uint32
+ Local net.IP
+ Remote net.IP
+ Ttl uint8
+ Tos uint8
+ EncapLimit uint8
+ Flags uint32
+ Proto uint8
+ FlowInfo uint32
+}
+
+func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs {
+ return &ip6tnl.LinkAttrs
+}
+
+func (ip6tnl *Ip6tnl) Type() string {
+ return "ip6tnl"
+}
+
type Sittun struct {
LinkAttrs
Link uint32
@@ -769,7 +927,10 @@ func (vti *Vti) Attrs() *LinkAttrs {
return &vti.LinkAttrs
}
-func (iptun *Vti) Type() string {
+func (vti *Vti) Type() string {
+ if vti.Local.To4() == nil {
+ return "vti6"
+ }
return "vti"
}
@@ -831,11 +992,68 @@ func (gtp *GTP) Type() string {
return "gtp"
}
+// Virtual XFRM Interfaces
+// Named "xfrmi" to prevent confusion with XFRM objects
+type Xfrmi struct {
+ LinkAttrs
+ Ifid uint32
+}
+
+func (xfrm *Xfrmi) Attrs() *LinkAttrs {
+ return &xfrm.LinkAttrs
+}
+
+func (xfrm *Xfrmi) Type() string {
+ return "xfrm"
+}
+
+// IPoIB interface
+
+type IPoIBMode uint16
+
+func (m *IPoIBMode) String() string {
+ str, ok := iPoIBModeToString[*m]
+ if !ok {
+ return fmt.Sprintf("mode(%d)", *m)
+ }
+ return str
+}
+
+const (
+ IPOIB_MODE_DATAGRAM = iota
+ IPOIB_MODE_CONNECTED
+)
+
+var iPoIBModeToString = map[IPoIBMode]string{
+ IPOIB_MODE_DATAGRAM: "datagram",
+ IPOIB_MODE_CONNECTED: "connected",
+}
+
+var StringToIPoIBMode = map[string]IPoIBMode{
+ "datagram": IPOIB_MODE_DATAGRAM,
+ "connected": IPOIB_MODE_CONNECTED,
+}
+
+type IPoIB struct {
+ LinkAttrs
+ Pkey uint16
+ Mode IPoIBMode
+ Umcast uint16
+}
+
+func (ipoib *IPoIB) Attrs() *LinkAttrs {
+ return &ipoib.LinkAttrs
+}
+
+func (ipoib *IPoIB) Type() string {
+ return "ipoib"
+}
+
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
-// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
-// bond_slave | ipvlan
+// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
+// bond_slave | ipvlan | xfrm
// LinkNotFoundError wraps the various not found errors when
// getting/reading links. This is intended for better error
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index 540191ed8..ec915a0b9 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -4,8 +4,11 @@ import (
"bytes"
"encoding/binary"
"fmt"
+ "io/ioutil"
"net"
"os"
+ "strconv"
+ "strings"
"syscall"
"unsafe"
@@ -16,7 +19,7 @@ import (
const (
SizeofLinkStats32 = 0x5c
- SizeofLinkStats64 = 0xd8
+ SizeofLinkStats64 = 0xb8
)
const (
@@ -31,6 +34,12 @@ const (
TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
)
+const (
+ VF_LINK_STATE_AUTO uint32 = 0
+ VF_LINK_STATE_ENABLE uint32 = 1
+ VF_LINK_STATE_DISABLE uint32 = 2
+)
+
var lookupByDump = false
var macvlanModes = [...]uint32{
@@ -113,6 +122,52 @@ func (h *Handle) SetPromiscOn(link Link) error {
return err
}
+// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
+// Equivalent to: `ip link set $link allmulticast on`
+func LinkSetAllmulticastOn(link Link) error {
+ return pkgHandle.LinkSetAllmulticastOn(link)
+}
+
+// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
+// Equivalent to: `ip link set $link allmulticast on`
+func (h *Handle) LinkSetAllmulticastOn(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_ALLMULTI
+ msg.Flags = unix.IFF_ALLMULTI
+
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
+// Equivalent to: `ip link set $link allmulticast off`
+func LinkSetAllmulticastOff(link Link) error {
+ return pkgHandle.LinkSetAllmulticastOff(link)
+}
+
+// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
+// Equivalent to: `ip link set $link allmulticast off`
+func (h *Handle) LinkSetAllmulticastOff(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_ALLMULTI
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
return pkgHandle.MacvlanMACAddrAdd(link, addr)
}
@@ -155,24 +210,24 @@ func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode
req.AddData(msg)
linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
- inner := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
+ inner := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
// IFLA_MACVLAN_MACADDR_MODE = mode
b := make([]byte, 4)
native.PutUint32(b, mode)
- nl.NewRtAttrChild(inner, nl.IFLA_MACVLAN_MACADDR_MODE, b)
+ inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b)
// populate message with MAC addrs, if necessary
switch mode {
case nl.MACVLAN_MACADDR_ADD, nl.MACVLAN_MACADDR_DEL:
if len(addrs) == 1 {
- nl.NewRtAttrChild(inner, nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0]))
+ inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0]))
}
case nl.MACVLAN_MACADDR_SET:
- mad := nl.NewRtAttrChild(inner, nl.IFLA_MACVLAN_MACADDR_DATA, nil)
+ mad := inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_DATA, nil)
for _, addr := range addrs {
- nl.NewRtAttrChild(mad, nl.IFLA_MACVLAN_MACADDR, []byte(addr))
+ mad.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addr))
}
}
@@ -203,7 +258,6 @@ func (h *Handle) SetPromiscOff(link Link) error {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Change = unix.IFF_PROMISC
- msg.Flags = 0 & ^unix.IFF_PROMISC
msg.Index = int32(base.Index)
req.AddData(msg)
@@ -253,7 +307,6 @@ func (h *Handle) LinkSetDown(link Link) error {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Change = unix.IFF_UP
- msg.Flags = 0 & ^unix.IFF_UP
msg.Index = int32(base.Index)
req.AddData(msg)
@@ -378,12 +431,12 @@ func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAdd
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfMac{
Vf: uint32(vf),
}
copy(vfmsg.Mac[:], []byte(hwaddr))
- nl.NewRtAttrChild(info, nl.IFLA_VF_MAC, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_MAC, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
@@ -408,10 +461,41 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
+ vfmsg := nl.VfVlan{
+ Vf: uint32(vf),
+ Vlan: uint32(vlan),
+ }
+ info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
+ req.AddData(data)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
+func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
+ return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos)
+}
+
+// LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
+func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfVlan{
Vf: uint32(vf),
Vlan: uint32(vlan),
+ Qos: uint32(qos),
}
nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
req.AddData(data)
@@ -438,12 +522,73 @@ func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfTxRate{
Vf: uint32(vf),
Rate: uint32(rate),
}
- nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
+ req.AddData(data)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetVfRate sets the min and max tx rate of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
+func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
+ return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate)
+}
+
+// LinkSetVfRate sets the min and max tx rate of a vf for the link.
+// Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
+func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
+ vfmsg := nl.VfRate{
+ Vf: uint32(vf),
+ MinTxRate: uint32(minRate),
+ MaxTxRate: uint32(maxRate),
+ }
+ info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize())
+ req.AddData(data)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetVfState enables/disables virtual link state on a vf.
+// Equivalent to: `ip link set $link vf $vf state $state`
+func LinkSetVfState(link Link, vf int, state uint32) error {
+ return pkgHandle.LinkSetVfState(link, vf, state)
+}
+
+// LinkSetVfState enables/disables virtual link state on a vf.
+// Equivalent to: `ip link set $link vf $vf state $state`
+func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
+ vfmsg := nl.VfLinkState{
+ Vf: uint32(vf),
+ LinkState: state,
+ }
+ info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
@@ -456,7 +601,7 @@ func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
}
-// LinkSetVfSpookfchk enables/disables spoof check on a vf for the link.
+// LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
// Equivalent to: `ip link set $link vf $vf spoofchk $check`
func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
var setting uint32
@@ -469,7 +614,7 @@ func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
if check {
setting = 1
}
@@ -477,7 +622,7 @@ func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
Vf: uint32(vf),
Setting: setting,
}
- nl.NewRtAttrChild(info, nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
@@ -503,7 +648,7 @@ func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
if state {
setting = 1
}
@@ -511,22 +656,66 @@ func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error {
Vf: uint32(vf),
Setting: setting,
}
- nl.NewRtAttrChild(info, nl.IFLA_VF_TRUST, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_TRUST, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
+// LinkSetVfNodeGUID sets the node GUID of a vf for the link.
+// Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid`
+func LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error {
+ return pkgHandle.LinkSetVfGUID(link, vf, nodeguid, nl.IFLA_VF_IB_NODE_GUID)
+}
+
+// LinkSetVfPortGUID sets the port GUID of a vf for the link.
+// Equivalent to: `ip link set dev $link vf $vf port_guid $portguid`
+func LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error {
+ return pkgHandle.LinkSetVfGUID(link, vf, portguid, nl.IFLA_VF_IB_PORT_GUID)
+}
+
+// LinkSetVfGUID sets the node or port GUID of a vf for the link.
+func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidType int) error {
+ var err error
+ var guid uint64
+
+ buf := bytes.NewBuffer(vfGuid)
+ err = binary.Read(buf, binary.BigEndian, &guid)
+ if err != nil {
+ return err
+ }
+
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
+ vfmsg := nl.VfGUID{
+ Vf: uint32(vf),
+ GUID: guid,
+ }
+ info.AddRtAttr(guidType, vfmsg.Serialize())
+ req.AddData(data)
+
+ _, err = req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
// LinkSetMaster sets the master of the link device.
// Equivalent to: `ip link set $link master $master`
-func LinkSetMaster(link Link, master *Bridge) error {
+func LinkSetMaster(link Link, master Link) error {
return pkgHandle.LinkSetMaster(link, master)
}
// LinkSetMaster sets the master of the link device.
// Equivalent to: `ip link set $link master $master`
-func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
+func (h *Handle) LinkSetMaster(link Link, master Link) error {
index := 0
if master != nil {
masterBase := master.Attrs()
@@ -672,69 +861,69 @@ type vxlanPortRange struct {
}
func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if vxlan.FlowBased {
vxlan.VxlanId = 0
}
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
+ data.AddRtAttr(nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
if vxlan.VtepDevIndex != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
+ data.AddRtAttr(nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
}
if vxlan.SrcAddr != nil {
ip := vxlan.SrcAddr.To4()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_VXLAN_LOCAL, []byte(ip))
} else {
ip = vxlan.SrcAddr.To16()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LOCAL6, []byte(ip))
+ data.AddRtAttr(nl.IFLA_VXLAN_LOCAL6, []byte(ip))
}
}
}
if vxlan.Group != nil {
group := vxlan.Group.To4()
if group != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GROUP, []byte(group))
+ data.AddRtAttr(nl.IFLA_VXLAN_GROUP, []byte(group))
} else {
group = vxlan.Group.To16()
if group != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GROUP6, []byte(group))
+ data.AddRtAttr(nl.IFLA_VXLAN_GROUP6, []byte(group))
}
}
}
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL)))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS)))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx))
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx))
+ data.AddRtAttr(nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL)))
+ data.AddRtAttr(nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS)))
+ data.AddRtAttr(nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning))
+ data.AddRtAttr(nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy))
+ data.AddRtAttr(nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC))
+ data.AddRtAttr(nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
+ data.AddRtAttr(nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
+ data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx))
+ data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx))
if vxlan.UDPCSum {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
+ data.AddRtAttr(nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
}
if vxlan.GBP {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, []byte{})
+ data.AddRtAttr(nl.IFLA_VXLAN_GBP, []byte{})
}
if vxlan.FlowBased {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased))
+ data.AddRtAttr(nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased))
}
if vxlan.NoAge {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
+ data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
} else if vxlan.Age > 0 {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age)))
+ data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age)))
}
if vxlan.Limit > 0 {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit)))
+ data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit)))
}
if vxlan.Port > 0 {
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port)))
+ data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port)))
}
if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)}
@@ -742,100 +931,100 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, &pr)
- nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes())
+ data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes())
}
}
func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if bond.Mode >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode)))
+ data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode)))
}
if bond.ActiveSlave >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave)))
+ data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave)))
}
if bond.Miimon >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon)))
+ data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon)))
}
if bond.UpDelay >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay)))
+ data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay)))
}
if bond.DownDelay >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay)))
+ data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay)))
}
if bond.UseCarrier >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier)))
+ data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier)))
}
if bond.ArpInterval >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval)))
+ data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval)))
}
if bond.ArpIpTargets != nil {
- msg := nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_IP_TARGET, nil)
+ msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil)
for i := range bond.ArpIpTargets {
ip := bond.ArpIpTargets[i].To4()
if ip != nil {
- nl.NewRtAttrChild(msg, i, []byte(ip))
+ msg.AddRtAttr(i, []byte(ip))
continue
}
ip = bond.ArpIpTargets[i].To16()
if ip != nil {
- nl.NewRtAttrChild(msg, i, []byte(ip))
+ msg.AddRtAttr(i, []byte(ip))
}
}
}
if bond.ArpValidate >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate)))
+ data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate)))
}
if bond.ArpAllTargets >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets)))
+ data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets)))
}
if bond.Primary >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary)))
+ data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary)))
}
if bond.PrimaryReselect >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect)))
+ data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect)))
}
if bond.FailOverMac >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac)))
+ data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac)))
}
if bond.XmitHashPolicy >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy)))
+ data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy)))
}
if bond.ResendIgmp >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp)))
+ data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp)))
}
if bond.NumPeerNotif >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif)))
+ data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif)))
}
if bond.AllSlavesActive >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive)))
+ data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive)))
}
if bond.MinLinks >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks)))
+ data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks)))
}
if bond.LpInterval >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
+ data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
}
if bond.PackersPerSlave >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave)))
+ data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave)))
}
if bond.LacpRate >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
+ data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
}
if bond.AdSelect >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
+ data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
}
if bond.AdActorSysPrio >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
+ data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
}
if bond.AdUserPortKey >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
+ data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
}
if bond.AdActorSystem != nil {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
+ data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
}
if bond.TlbDynamicLb >= 0 {
- nl.NewRtAttrChild(data, nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
+ data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
}
}
@@ -853,7 +1042,7 @@ func LinkAdd(link Link) error {
}
// LinkAdd adds a new link device. The type and features of the device
-// are taken fromt the parameters in the link object.
+// are taken from the parameters in the link object.
// Equivalent to: `ip link add $link`
func (h *Handle) LinkAdd(link Link) error {
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
@@ -863,16 +1052,18 @@ func (h *Handle) linkModify(link Link, flags int) error {
// TODO: support extra data for macvlan
base := link.Attrs()
- if base.Name == "" {
- return fmt.Errorf("LinkAttrs.Name cannot be empty!")
+ // if tuntap, then the name can be empty, OS will provide a name
+ tuntap, isTuntap := link.(*Tuntap)
+
+ if base.Name == "" && !isTuntap {
+ return fmt.Errorf("LinkAttrs.Name cannot be empty")
}
- if tuntap, ok := link.(*Tuntap); ok {
+ if isTuntap {
// TODO: support user
// TODO: support group
- // TODO: support non- persistent
if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP {
- return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
+ return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode)
}
queues := tuntap.Queues
@@ -913,12 +1104,25 @@ func (h *Handle) linkModify(link Link, flags int) error {
cleanupFds(fds)
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno)
}
+ // 1) we only care for the name of the first tap in the multi queue set
+ // 2) if the original name was empty, the localReq has now the actual name
+ //
+ // In addition:
+ // This ensures that the link name is always identical to what the kernel returns.
+ // Not only in case of an empty name, but also when using name templates.
+ // e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number.
+ if i == 0 {
+ link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00")
+ }
}
- _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1)
- if errno != 0 {
- cleanupFds(fds)
- return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
+ // only persist interface if NonPersist is NOT set
+ if !tuntap.NonPersist {
+ _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1)
+ if errno != 0 {
+ cleanupFds(fds)
+ return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
+ }
}
h.ensureIndex(base)
@@ -928,7 +1132,11 @@ func (h *Handle) linkModify(link Link, flags int) error {
// TODO: verify MasterIndex is actually a bridge?
err := h.LinkSetMasterByIndex(link, base.MasterIndex)
if err != nil {
- _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0)
+ // un-persist (e.g. allow the interface to be removed) the tuntap
+ // should not hurt if not set prior, condition might be not needed
+ if !tuntap.NonPersist {
+ _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0)
+ }
cleanupFds(fds)
return err
}
@@ -978,8 +1186,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
native.PutUint32(b, uint32(base.ParentIndex))
data := nl.NewRtAttr(unix.IFLA_LINK, b)
req.AddData(data)
- } else if link.Type() == "ipvlan" {
- return fmt.Errorf("Can't create ipvlan link without ParentIndex")
+ } else if link.Type() == "ipvlan" || link.Type() == "ipoib" {
+ return fmt.Errorf("Can't create %s link without ParentIndex", link.Type())
}
nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
@@ -1010,14 +1218,29 @@ func (h *Handle) linkModify(link Link, flags int) error {
req.AddData(rxqueues)
}
+ if base.GSOMaxSegs > 0 {
+ gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs))
+ req.AddData(gsoAttr)
+ }
+
+ if base.GSOMaxSize > 0 {
+ gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize))
+ req.AddData(gsoAttr)
+ }
+
+ if base.Group > 0 {
+ groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
+ req.AddData(groupAttr)
+ }
+
if base.Namespace != nil {
var attr *nl.RtAttr
- switch base.Namespace.(type) {
+ switch ns := base.Namespace.(type) {
case NsPid:
- val := nl.Uint32Attr(uint32(base.Namespace.(NsPid)))
+ val := nl.Uint32Attr(uint32(ns))
attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val)
case NsFd:
- val := nl.Uint32Attr(uint32(base.Namespace.(NsFd)))
+ val := nl.Uint32Attr(uint32(ns))
attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val)
}
@@ -1029,47 +1252,56 @@ func (h *Handle) linkModify(link Link, flags int) error {
}
linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
+ linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
switch link := link.(type) {
case *Vlan:
b := make([]byte, 2)
native.PutUint16(b, uint16(link.VlanId))
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- nl.NewRtAttrChild(data, nl.IFLA_VLAN_ID, b)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_VLAN_ID, b)
+
+ if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
+ data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
+ }
case *Veth:
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- peer := nl.NewRtAttrChild(data, nl.VETH_INFO_PEER, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC)
- nl.NewRtAttrChild(peer, unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
+ peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
if base.TxQLen >= 0 {
- nl.NewRtAttrChild(peer, unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
+ peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
}
if base.MTU > 0 {
- nl.NewRtAttrChild(peer, unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
+ peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
+ }
+ if link.PeerHardwareAddr != nil {
+ peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr))
}
-
case *Vxlan:
addVxlanAttrs(link, linkInfo)
case *Bond:
addBondAttrs(link, linkInfo)
case *IPVlan:
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
+ data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
case *Macvlan:
if link.Mode != MACVLAN_MODE_DEFAULT {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
}
case *Macvtap:
if link.Mode != MACVLAN_MODE_DEFAULT {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
}
case *Gretap:
addGretapAttrs(link, linkInfo)
case *Iptun:
addIptunAttrs(link, linkInfo)
+ case *Ip6tnl:
+ addIp6tnlAttrs(link, linkInfo)
case *Sittun:
addSittunAttrs(link, linkInfo)
case *Gretun:
@@ -1082,6 +1314,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
addBridgeAttrs(link, linkInfo)
case *GTP:
addGTPAttrs(link, linkInfo)
+ case *Xfrmi:
+ addXfrmiAttrs(link, linkInfo)
+ case *IPoIB:
+ addIPoIBAttrs(link, linkInfo)
}
req.AddData(linkInfo)
@@ -1170,6 +1406,9 @@ func (h *Handle) LinkByName(name string) (Link, error) {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
req.AddData(msg)
+ attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
+ req.AddData(attr)
+
nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name))
req.AddData(nameData)
@@ -1202,6 +1441,9 @@ func (h *Handle) LinkByAlias(alias string) (Link, error) {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
req.AddData(msg)
+ attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
+ req.AddData(attr)
+
nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias))
req.AddData(nameData)
@@ -1228,6 +1470,8 @@ func (h *Handle) LinkByIndex(index int) (Link, error) {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(index)
req.AddData(msg)
+ attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
+ req.AddData(attr)
return execGetLink(req)
}
@@ -1270,10 +1514,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.Promisc = 1
}
var (
- link Link
- stats32 []byte
- stats64 []byte
- linkType string
+ link Link
+ stats32 *LinkStatistics32
+ stats64 *LinkStatistics64
+ linkType string
+ linkSlave LinkSlave
+ slaveType string
)
for _, attr := range attrs {
switch attr.Attr.Type {
@@ -1313,18 +1559,26 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Gretap{}
case "ipip":
link = &Iptun{}
+ case "ip6tnl":
+ link = &Ip6tnl{}
case "sit":
link = &Sittun{}
case "gre":
link = &Gretun{}
case "ip6gre":
link = &Gretun{}
- case "vti":
+ case "vti", "vti6":
link = &Vti{}
case "vrf":
link = &Vrf{}
case "gtp":
link = &GTP{}
+ case "xfrm":
+ link = &Xfrmi{}
+ case "tun":
+ link = &Tuntap{}
+ case "ipoib":
+ link = &IPoIB{}
default:
link = &GenericLink{LinkType: linkType}
}
@@ -1352,13 +1606,15 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseGretapData(link, data)
case "ipip":
parseIptunData(link, data)
+ case "ip6tnl":
+ parseIp6tnlData(link, data)
case "sit":
parseSittunData(link, data)
case "gre":
parseGretunData(link, data)
case "ip6gre":
parseGretunData(link, data)
- case "vti":
+ case "vti", "vti6":
parseVtiData(link, data)
case "vrf":
parseVrfData(link, data)
@@ -1366,6 +1622,27 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseBridgeData(link, data)
case "gtp":
parseGTPData(link, data)
+ case "xfrm":
+ parseXfrmiData(link, data)
+ case "tun":
+ parseTuntapData(link, data)
+ case "ipoib":
+ parseIPoIBData(link, data)
+ }
+ case nl.IFLA_INFO_SLAVE_KIND:
+ slaveType = string(info.Value[:len(info.Value)-1])
+ switch slaveType {
+ case "bond":
+ linkSlave = &BondSlave{}
+ }
+ case nl.IFLA_INFO_SLAVE_DATA:
+ switch slaveType {
+ case "bond":
+ data, err := nl.ParseRouteAttr(info.Value)
+ if err != nil {
+ return nil, err
+ }
+ parseBondSlaveData(linkSlave, data)
}
}
}
@@ -1392,9 +1669,15 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
case unix.IFLA_IFALIAS:
base.Alias = string(attr.Value[:len(attr.Value)-1])
case unix.IFLA_STATS:
- stats32 = attr.Value[:]
+ stats32 = new(LinkStatistics32)
+ if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil {
+ return nil, err
+ }
case unix.IFLA_STATS64:
- stats64 = attr.Value[:]
+ stats64 = new(LinkStatistics64)
+ if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil {
+ return nil, err
+ }
case unix.IFLA_XDP:
xdp, err := parseLinkXdp(attr.Value[:])
if err != nil {
@@ -1408,19 +1691,40 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
if err != nil {
return nil, err
}
- base.Protinfo = parseProtinfo(attrs)
+ protinfo := parseProtinfo(attrs)
+ base.Protinfo = &protinfo
}
case unix.IFLA_OPERSTATE:
base.OperState = LinkOperState(uint8(attr.Value[0]))
case unix.IFLA_LINK_NETNSID:
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
+ case unix.IFLA_GSO_MAX_SIZE:
+ base.GSOMaxSize = native.Uint32(attr.Value[0:4])
+ case unix.IFLA_GSO_MAX_SEGS:
+ base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
+ case unix.IFLA_VFINFO_LIST:
+ data, err := nl.ParseRouteAttr(attr.Value)
+ if err != nil {
+ return nil, err
+ }
+ vfs, err := parseVfInfoList(data)
+ if err != nil {
+ return nil, err
+ }
+ base.Vfs = vfs
+ case unix.IFLA_NUM_TX_QUEUES:
+ base.NumTxQueues = int(native.Uint32(attr.Value[0:4]))
+ case unix.IFLA_NUM_RX_QUEUES:
+ base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
+ case unix.IFLA_GROUP:
+ base.Group = native.Uint32(attr.Value[0:4])
}
}
if stats64 != nil {
- base.Statistics = parseLinkStats64(stats64)
+ base.Statistics = (*LinkStatistics)(stats64)
} else if stats32 != nil {
- base.Statistics = parseLinkStats32(stats32)
+ base.Statistics = (*LinkStatistics)(stats32.to64())
}
// Links that don't have IFLA_INFO_KIND are hardware devices
@@ -1428,10 +1732,59 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Device{}
}
*link.Attrs() = base
+ link.Attrs().Slave = linkSlave
+
+ // If the tuntap attributes are not updated by netlink due to
+ // an older driver, use sysfs
+ if link != nil && linkType == "tun" {
+ tuntap := link.(*Tuntap)
+
+ if tuntap.Mode == 0 {
+ ifname := tuntap.Attrs().Name
+ if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil {
+
+ if flags&unix.IFF_TUN != 0 {
+ tuntap.Mode = unix.IFF_TUN
+ } else if flags&unix.IFF_TAP != 0 {
+ tuntap.Mode = unix.IFF_TAP
+ }
+
+ tuntap.NonPersist = false
+ if flags&unix.IFF_PERSIST == 0 {
+ tuntap.NonPersist = true
+ }
+ }
+
+ // The sysfs interface for owner/group returns -1 for root user, instead of returning 0.
+ // So explicitly check for negative value, before assigning the owner uid/gid.
+ if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 {
+ tuntap.Owner = uint32(owner)
+ }
+
+ if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 {
+ tuntap.Group = uint32(group)
+ }
+ }
+ }
return link, nil
}
+func readSysPropAsInt64(ifname, prop string) (int64, error) {
+ fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop)
+ contents, err := ioutil.ReadFile(fname)
+ if err != nil {
+ return 0, err
+ }
+
+ num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64)
+ if err == nil {
+ return num, nil
+ }
+
+ return 0, err
+}
+
// LinkList gets a list of link devices.
// Equivalent to: `ip link show`
func LinkList() ([]Link, error) {
@@ -1447,6 +1800,8 @@ func (h *Handle) LinkList() ([]Link, error) {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
req.AddData(msg)
+ attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
+ req.AddData(attr)
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
if err != nil {
@@ -1526,13 +1881,19 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
go func() {
defer close(ch)
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
cberr(err)
}
return
}
+ if from.Pid != nl.PidKernel {
+ if cberr != nil {
+ cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
+ }
+ continue
+ }
for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE {
continue
@@ -1639,7 +2000,7 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
req.AddData(msg)
br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
- nl.NewRtAttrChild(br, attr, boolToByte(mode))
+ br.AddRtAttr(attr, boolToByte(mode))
req.AddData(br)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
if err != nil {
@@ -1675,12 +2036,43 @@ func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
return err
}
+// LinkSetGroup sets the link group id which can be used to perform mass actions
+// with iproute2 as well use it as a reference in nft filters.
+// Equivalent to: `ip link set $link group $id`
+func LinkSetGroup(link Link, group int) error {
+ return pkgHandle.LinkSetGroup(link, group)
+}
+
+// LinkSetGroup sets the link group id which can be used to perform mass actions
+// with iproute2 as well use it as a reference in nft filters.
+// Equivalent to: `ip link set $link group $id`
+func (h *Handle) LinkSetGroup(link Link, group int) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(group))
+
+ data := nl.NewRtAttr(unix.IFLA_GROUP, b)
+ req.AddData(data)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
vlan := link.(*Vlan)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_VLAN_ID:
vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
+ case nl.IFLA_VLAN_PROTOCOL:
+ vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
}
}
}
@@ -1762,7 +2154,7 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BOND_ARP_INTERVAL:
bond.ArpInterval = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_ARP_IP_TARGET:
- // TODO: implement
+ bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value)
case nl.IFLA_BOND_ARP_VALIDATE:
bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_ARP_ALL_TARGETS:
@@ -1805,12 +2197,75 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseBondArpIpTargets(value []byte) []net.IP {
+ data, err := nl.ParseRouteAttr(value)
+ if err != nil {
+ return nil
+ }
+
+ targets := []net.IP{}
+ for i := range data {
+ target := net.IP(data[i].Value)
+ if ip := target.To4(); ip != nil {
+ targets = append(targets, ip)
+ continue
+ }
+ if ip := target.To16(); ip != nil {
+ targets = append(targets, ip)
+ }
+ }
+
+ return targets
+}
+
+func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
+
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State)))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus)))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState))
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState))
+
+ if mac := bondSlave.PermHardwareAddr; mac != nil {
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac))
+ }
+}
+
+func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
+ bondSlave := slave.(*BondSlave)
+ for i := range data {
+ switch data[i].Attr.Type {
+ case nl.IFLA_BOND_SLAVE_STATE:
+ bondSlave.State = BondSlaveState(data[i].Value[0])
+ case nl.IFLA_BOND_SLAVE_MII_STATUS:
+ bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0])
+ case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT:
+ bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4])
+ case nl.IFLA_BOND_SLAVE_PERM_HWADDR:
+ bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6])
+ case nl.IFLA_BOND_SLAVE_QUEUE_ID:
+ bondSlave.QueueId = native.Uint16(data[i].Value[0:2])
+ case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID:
+ bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2])
+ case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE:
+ bondSlave.AdActorOperPortState = uint8(data[i].Value[0])
+ case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE:
+ bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2])
+ }
+ }
+}
+
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan)
for _, datum := range data {
- if datum.Attr.Type == nl.IFLA_IPVLAN_MODE {
+ switch datum.Attr.Type {
+ case nl.IFLA_IPVLAN_MODE:
ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
- return
+ case nl.IFLA_IPVLAN_FLAG:
+ ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
}
}
}
@@ -1873,11 +2328,11 @@ func linkFlags(rawFlags uint32) net.Flags {
}
func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if gretap.FlowBased {
// In flow based mode, no other attributes need to be configured
- nl.NewRtAttrChild(data, nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
+ data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
return
}
@@ -1885,40 +2340,40 @@ func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
if ip.To4() != nil {
ip = ip.To4()
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
}
if ip := gretap.Remote; ip != nil {
if ip.To4() != nil {
ip = ip.To4()
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_REMOTE, []byte(ip))
+ data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
}
if gretap.IKey != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_IKEY, htonl(gretap.IKey))
+ data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey))
gretap.IFlags |= uint16(nl.GRE_KEY)
}
if gretap.OKey != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_OKEY, htonl(gretap.OKey))
+ data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey))
gretap.OFlags |= uint16(nl.GRE_KEY)
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags))
+ data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags))
+ data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags))
if gretap.Link != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link))
+ data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link))
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport))
+ data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc))
+ data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl))
+ data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport))
}
func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
@@ -1930,9 +2385,9 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_GRE_IKEY:
gre.OKey = ntohl(datum.Value[0:4])
case nl.IFLA_GRE_LOCAL:
- gre.Local = net.IP(datum.Value[0:16])
+ gre.Local = net.IP(datum.Value)
case nl.IFLA_GRE_REMOTE:
- gre.Remote = net.IP(datum.Value[0:16])
+ gre.Remote = net.IP(datum.Value)
case nl.IFLA_GRE_ENCAP_SPORT:
gre.EncapSport = ntohs(datum.Value[0:2])
case nl.IFLA_GRE_ENCAP_DPORT:
@@ -1941,7 +2396,6 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
gre.IFlags = ntohs(datum.Value[0:2])
case nl.IFLA_GRE_OFLAGS:
gre.OFlags = ntohs(datum.Value[0:2])
-
case nl.IFLA_GRE_TTL:
gre.Ttl = uint8(datum.Value[0])
case nl.IFLA_GRE_TOS:
@@ -1953,73 +2407,70 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_GRE_ENCAP_FLAGS:
gre.EncapFlags = native.Uint16(datum.Value[0:2])
case nl.IFLA_GRE_COLLECT_METADATA:
- if len(datum.Value) > 0 {
- gre.FlowBased = int8(datum.Value[0]) != 0
- }
+ gre.FlowBased = true
}
}
}
func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if ip := gre.Local; ip != nil {
if ip.To4() != nil {
ip = ip.To4()
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
}
if ip := gre.Remote; ip != nil {
if ip.To4() != nil {
ip = ip.To4()
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_REMOTE, []byte(ip))
+ data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
}
if gre.IKey != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_IKEY, htonl(gre.IKey))
+ data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey))
gre.IFlags |= uint16(nl.GRE_KEY)
}
if gre.OKey != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_OKEY, htonl(gre.OKey))
+ data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey))
gre.OFlags |= uint16(nl.GRE_KEY)
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_IFLAGS, htons(gre.IFlags))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_OFLAGS, htons(gre.OFlags))
+ data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags))
+ data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags))
if gre.Link != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link))
+ data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link))
}
- nl.NewRtAttrChild(data, nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport))
- nl.NewRtAttrChild(data, nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport))
+ data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc))
+ data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl))
+ data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport))
+ data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport))
}
func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
gre := link.(*Gretun)
for _, datum := range data {
switch datum.Attr.Type {
- case nl.IFLA_GRE_OKEY:
- gre.IKey = ntohl(datum.Value[0:4])
case nl.IFLA_GRE_IKEY:
+ gre.IKey = ntohl(datum.Value[0:4])
+ case nl.IFLA_GRE_OKEY:
gre.OKey = ntohl(datum.Value[0:4])
case nl.IFLA_GRE_LOCAL:
- gre.Local = net.IP(datum.Value[0:16])
+ gre.Local = net.IP(datum.Value)
case nl.IFLA_GRE_REMOTE:
- gre.Remote = net.IP(datum.Value[0:16])
+ gre.Remote = net.IP(datum.Value)
case nl.IFLA_GRE_IFLAGS:
gre.IFlags = ntohs(datum.Value[0:2])
case nl.IFLA_GRE_OFLAGS:
gre.OFlags = ntohs(datum.Value[0:2])
-
case nl.IFLA_GRE_TTL:
gre.Ttl = uint8(datum.Value[0])
case nl.IFLA_GRE_TOS:
@@ -2038,23 +2489,15 @@ func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
-func parseLinkStats32(data []byte) *LinkStatistics {
- return (*LinkStatistics)((*LinkStatistics32)(unsafe.Pointer(&data[0:SizeofLinkStats32][0])).to64())
-}
-
-func parseLinkStats64(data []byte) *LinkStatistics {
- return (*LinkStatistics)((*LinkStatistics64)(unsafe.Pointer(&data[0:SizeofLinkStats64][0])))
-}
-
func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil)
b := make([]byte, 4)
native.PutUint32(b, uint32(xdp.Fd))
- nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
+ attrs.AddRtAttr(nl.IFLA_XDP_FD, b)
if xdp.Flags != 0 {
b := make([]byte, 4)
native.PutUint32(b, xdp.Flags)
- nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b)
+ attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b)
}
req.AddData(attrs)
}
@@ -2083,32 +2526,32 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
if iptun.FlowBased {
// In flow based mode, no other attributes need to be configured
- nl.NewRtAttrChild(linkInfo, nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased))
+ linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased))
return
}
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
ip := iptun.Local.To4()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
}
ip = iptun.Remote.To4()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_REMOTE, []byte(ip))
+ data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
}
if iptun.Link != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
+ data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
}
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport))
+ data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
+ data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
+ data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport))
}
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
@@ -2139,34 +2582,83 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ if ip6tnl.Link != 0 {
+ data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
+ }
+
+ ip := ip6tnl.Local.To16()
+ if ip != nil {
+ data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
+ }
+
+ ip = ip6tnl.Remote.To16()
+ if ip != nil {
+ data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
+ }
+
+ data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl))
+ data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit))
+ data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags))
+ data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto))
+ data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo))
+}
+
+func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
+ ip6tnl := link.(*Ip6tnl)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_IPTUN_LOCAL:
+ ip6tnl.Local = net.IP(datum.Value[:16])
+ case nl.IFLA_IPTUN_REMOTE:
+ ip6tnl.Remote = net.IP(datum.Value[:16])
+ case nl.IFLA_IPTUN_TTL:
+ ip6tnl.Ttl = uint8(datum.Value[0])
+ case nl.IFLA_IPTUN_TOS:
+ ip6tnl.Tos = uint8(datum.Value[0])
+ case nl.IFLA_IPTUN_ENCAP_LIMIT:
+ ip6tnl.EncapLimit = uint8(datum.Value[0])
+ case nl.IFLA_IPTUN_FLAGS:
+ ip6tnl.Flags = native.Uint32(datum.Value[:4])
+ case nl.IFLA_IPTUN_PROTO:
+ ip6tnl.Proto = uint8(datum.Value[0])
+ case nl.IFLA_IPTUN_FLOWINFO:
+ ip6tnl.FlowInfo = native.Uint32(datum.Value[:4])
+ }
+ }
+}
+
func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if sittun.Link != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link))
+ data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link))
}
ip := sittun.Local.To4()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
}
ip = sittun.Remote.To4()
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_REMOTE, []byte(ip))
+ data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
}
if sittun.Ttl > 0 {
// Would otherwise fail on 3.10 kernel
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl))
+ data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl))
}
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport))
- nl.NewRtAttrChild(data, nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport))
+ data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos))
+ data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport))
+ data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport))
}
func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) {
@@ -2196,24 +2688,39 @@ func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) {
}
func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ family := FAMILY_V4
+ if vti.Local.To4() == nil {
+ family = FAMILY_V6
+ }
- ip := vti.Local.To4()
+ var ip net.IP
+
+ if family == FAMILY_V4 {
+ ip = vti.Local.To4()
+ } else {
+ ip = vti.Local
+ }
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VTI_LOCAL, []byte(ip))
+ data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip))
}
- ip = vti.Remote.To4()
+ if family == FAMILY_V4 {
+ ip = vti.Remote.To4()
+ } else {
+ ip = vti.Remote
+ }
if ip != nil {
- nl.NewRtAttrChild(data, nl.IFLA_VTI_REMOTE, []byte(ip))
+ data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip))
}
if vti.Link != 0 {
- nl.NewRtAttrChild(data, nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
+ data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
}
- nl.NewRtAttrChild(data, nl.IFLA_VTI_IKEY, htonl(vti.IKey))
- nl.NewRtAttrChild(data, nl.IFLA_VTI_OKEY, htonl(vti.OKey))
+ data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey))
+ data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey))
}
func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
@@ -2221,9 +2728,9 @@ func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_VTI_LOCAL:
- vti.Local = net.IP(datum.Value[0:4])
+ vti.Local = net.IP(datum.Value)
case nl.IFLA_VTI_REMOTE:
- vti.Remote = net.IP(datum.Value[0:4])
+ vti.Remote = net.IP(datum.Value)
case nl.IFLA_VTI_IKEY:
vti.IKey = ntohl(datum.Value[0:4])
case nl.IFLA_VTI_OKEY:
@@ -2233,10 +2740,10 @@ func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
}
func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
b := make([]byte, 4)
native.PutUint32(b, uint32(vrf.Table))
- nl.NewRtAttrChild(data, nl.IFLA_VRF_TABLE, b)
+ data.AddRtAttr(nl.IFLA_VRF_TABLE, b)
}
func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
@@ -2250,12 +2757,15 @@ func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
}
func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
if bridge.MulticastSnooping != nil {
- nl.NewRtAttrChild(data, nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
+ data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
}
if bridge.HelloTime != nil {
- nl.NewRtAttrChild(data, nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
+ data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
+ }
+ if bridge.VlanFiltering != nil {
+ data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering))
}
}
@@ -2269,17 +2779,20 @@ func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BR_MCAST_SNOOPING:
mcastSnooping := datum.Value[0] == 1
br.MulticastSnooping = &mcastSnooping
+ case nl.IFLA_BR_VLAN_FILTERING:
+ vlanFiltering := datum.Value[0] == 1
+ br.VlanFiltering = &vlanFiltering
}
}
}
func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) {
- data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
- nl.NewRtAttrChild(data, nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
- nl.NewRtAttrChild(data, nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
- nl.NewRtAttrChild(data, nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
+ data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
+ data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
if gtp.Role != nl.GTP_ROLE_GGSN {
- nl.NewRtAttrChild(data, nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role)))
+ data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role)))
}
}
@@ -2299,6 +2812,70 @@ func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
+ var vfs []VfInfo
+
+ for i, element := range data {
+ if element.Attr.Type != nl.IFLA_VF_INFO {
+ return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type)
+ }
+ vfAttrs, err := nl.ParseRouteAttr(element.Value)
+ if err != nil {
+ return nil, err
+ }
+ vfs = append(vfs, parseVfInfo(vfAttrs, i))
+ }
+ return vfs, nil
+}
+
+func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
+ vf := VfInfo{ID: id}
+ for _, element := range data {
+ switch element.Attr.Type {
+ case nl.IFLA_VF_MAC:
+ mac := nl.DeserializeVfMac(element.Value[:])
+ vf.Mac = mac.Mac[:6]
+ case nl.IFLA_VF_VLAN:
+ vl := nl.DeserializeVfVlan(element.Value[:])
+ vf.Vlan = int(vl.Vlan)
+ vf.Qos = int(vl.Qos)
+ case nl.IFLA_VF_TX_RATE:
+ txr := nl.DeserializeVfTxRate(element.Value[:])
+ vf.TxRate = int(txr.Rate)
+ case nl.IFLA_VF_SPOOFCHK:
+ sp := nl.DeserializeVfSpoofchk(element.Value[:])
+ vf.Spoofchk = sp.Setting != 0
+ case nl.IFLA_VF_LINK_STATE:
+ ls := nl.DeserializeVfLinkState(element.Value[:])
+ vf.LinkState = ls.LinkState
+ case nl.IFLA_VF_RATE:
+ vfr := nl.DeserializeVfRate(element.Value[:])
+ vf.MaxTxRate = vfr.MaxTxRate
+ vf.MinTxRate = vfr.MinTxRate
+ }
+ }
+ return vf
+}
+
+func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex)))
+ data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid))
+
+}
+
+func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
+ xfrmi := link.(*Xfrmi)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_XFRM_LINK:
+ xfrmi.ParentIndex = int(native.Uint32(datum.Value))
+ case nl.IFLA_XFRM_IF_ID:
+ xfrmi.Ifid = native.Uint32(datum.Value)
+ }
+ }
+}
+
// LinkSetBondSlave add slave to bond link via ioctl interface.
func LinkSetBondSlave(link Link, master *Bond) error {
fd, err := getSocketUDP()
@@ -2316,6 +2893,52 @@ func LinkSetBondSlave(link Link, master *Bond) error {
return nil
}
+// LinkSetBondSlaveQueueId modify bond slave queue-id.
+func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
+ data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId))
+
+ req.AddData(linkInfo)
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetBondSlaveQueueId modify bond slave queue-id.
+func LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
+ return pkgHandle.LinkSetBondSlaveQueueId(link, queueId)
+}
+
+func vethStatsSerialize(stats ethtoolStats) ([]byte, error) {
+ statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0)))
+ b := make([]byte, 0, statsSize)
+ buf := bytes.NewBuffer(b)
+ err := binary.Write(buf, nl.NativeEndian(), stats)
+ return buf.Bytes()[:statsSize], err
+}
+
+type vethEthtoolStats struct {
+ Cmd uint32
+ NStats uint32
+ Peer uint64
+ // Newer kernels have XDP stats in here, but we only care
+ // to extract the peer ifindex here.
+}
+
+func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) {
+ var stats = vethEthtoolStats{}
+ err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats)
+ return stats, err
+}
+
// VethPeerIndex get veth peer index.
func VethPeerIndex(link *Veth) (int, error) {
fd, err := getSocketUDP()
@@ -2330,25 +2953,66 @@ func VethPeerIndex(link *Veth) (int, error) {
return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
}
- gstrings := &ethtoolGstrings{
- cmd: ETHTOOL_GSTRINGS,
- stringSet: ETH_SS_STATS,
- length: sSet.data[0],
+ stats := ethtoolStats{
+ cmd: ETHTOOL_GSTATS,
+ nStats: sSet.data[0],
+ }
+
+ buffer, err := vethStatsSerialize(stats)
+ if err != nil {
+ return -1, err
}
- ifreq.Data = uintptr(unsafe.Pointer(gstrings))
+
+ ifreq.Data = uintptr(unsafe.Pointer(&buffer[0]))
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
}
- stats := &ethtoolStats{
- cmd: ETHTOOL_GSTATS,
- nStats: gstrings.length,
+ vstats, err := vethStatsDeserialize(buffer)
+ if err != nil {
+ return -1, err
}
- ifreq.Data = uintptr(unsafe.Pointer(stats))
- _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
- if errno != 0 {
- return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
+
+ return int(vstats.Peer), nil
+}
+
+func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) {
+ tuntap := link.(*Tuntap)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_TUN_OWNER:
+ tuntap.Owner = native.Uint32(datum.Value)
+ case nl.IFLA_TUN_GROUP:
+ tuntap.Group = native.Uint32(datum.Value)
+ case nl.IFLA_TUN_TYPE:
+ tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
+ case nl.IFLA_TUN_PERSIST:
+ tuntap.NonPersist = false
+ if uint8(datum.Value[0]) == 0 {
+ tuntap.NonPersist = true
+ }
+ }
+ }
+}
+
+func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
+ ipoib := link.(*IPoIB)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_IPOIB_PKEY:
+ ipoib.Pkey = uint16(native.Uint16(datum.Value))
+ case nl.IFLA_IPOIB_MODE:
+ ipoib.Mode = IPoIBMode(native.Uint16(datum.Value))
+ case nl.IFLA_IPOIB_UMCAST:
+ ipoib.Umcast = uint16(native.Uint16(datum.Value))
+ }
}
- return int(stats.data[0]), nil
+}
+
+func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
+ data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
+ data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
}
diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go
index 3f5cd497a..379e5655f 100644
--- a/vendor/github.com/vishvananda/netlink/neigh.go
+++ b/vendor/github.com/vishvananda/netlink/neigh.go
@@ -17,9 +17,16 @@ type Neigh struct {
LLIPAddr net.IP //Used in the case of NHRP
Vlan int
VNI int
+ MasterIndex int
}
// String returns $ip/$hwaddr $label
func (neigh *Neigh) String() string {
return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr)
}
+
+// NeighUpdate is sent when a neighbor changes - type is RTM_NEWNEIGH or RTM_DELNEIGH.
+type NeighUpdate struct {
+ Type uint16
+ Neigh
+}
diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go
index f75c22649..cb3b55d35 100644
--- a/vendor/github.com/vishvananda/netlink/neigh_linux.go
+++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go
@@ -1,10 +1,13 @@
package netlink
import (
+ "fmt"
"net"
+ "syscall"
"unsafe"
"github.com/vishvananda/netlink/nl"
+ "github.com/vishvananda/netns"
"golang.org/x/sys/unix"
)
@@ -18,7 +21,10 @@ const (
NDA_PORT
NDA_VNI
NDA_IFINDEX
- NDA_MAX = NDA_IFINDEX
+ NDA_MASTER
+ NDA_LINK_NETNSID
+ NDA_SRC_VNI
+ NDA_MAX = NDA_SRC_VNI
)
// Neighbor Cache Entry States.
@@ -43,6 +49,7 @@ const (
NTF_ROUTER = 0x80
)
+// Ndmsg is for adding, removing or receiving information about a neighbor table entry
type Ndmsg struct {
Family uint8
Index uint32
@@ -170,45 +177,58 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
req.AddData(vniData)
}
+ if neigh.MasterIndex != 0 {
+ masterData := nl.NewRtAttr(NDA_MASTER, nl.Uint32Attr(uint32(neigh.MasterIndex)))
+ req.AddData(masterData)
+ }
+
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
-// NeighList gets a list of IP-MAC mappings in the system (ARP table).
+// NeighList returns a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family.
func NeighList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighList(linkIndex, family)
}
-// NeighProxyList gets a list of neighbor proxies in the system.
+// NeighProxyList returns a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link and ip family.
func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighProxyList(linkIndex, family)
}
-// NeighList gets a list of IP-MAC mappings in the system (ARP table).
+// NeighList returns a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family.
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
- return h.neighList(linkIndex, family, 0)
+ return h.NeighListExecute(Ndmsg{
+ Family: uint8(family),
+ Index: uint32(linkIndex),
+ })
}
-// NeighProxyList gets a list of neighbor proxies in the system.
+// NeighProxyList returns a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link, ip family.
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
- return h.neighList(linkIndex, family, NTF_PROXY)
+ return h.NeighListExecute(Ndmsg{
+ Family: uint8(family),
+ Index: uint32(linkIndex),
+ Flags: NTF_PROXY,
+ })
+}
+
+// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state.
+func NeighListExecute(msg Ndmsg) ([]Neigh, error) {
+ return pkgHandle.NeighListExecute(msg)
}
-func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
+// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state.
+func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) {
req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
- msg := Ndmsg{
- Family: uint8(family),
- Index: uint32(linkIndex),
- Flags: uint8(flags),
- }
req.AddData(&msg)
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
@@ -219,7 +239,7 @@ func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
var res []Neigh
for _, m := range msgs {
ndm := deserializeNdmsg(m)
- if linkIndex != 0 && int(ndm.Index) != linkIndex {
+ if msg.Index != 0 && ndm.Index != msg.Index {
// Ignore messages from other interfaces
continue
}
@@ -251,14 +271,6 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
return nil, err
}
- // This should be cached for perfomance
- // once per table dump
- link, err := LinkByIndex(neigh.LinkIndex)
- if err != nil {
- return nil, err
- }
- encapType := link.Attrs().EncapType
-
for _, attr := range attrs {
switch attr.Attr.Type {
case NDA_DST:
@@ -268,13 +280,16 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
attrLen := attr.Attr.Len - unix.SizeofRtAttr
- if attrLen == 4 && (encapType == "ipip" ||
- encapType == "sit" ||
- encapType == "gre") {
+ if attrLen == 4 {
neigh.LLIPAddr = net.IP(attr.Value)
- } else if attrLen == 16 &&
- encapType == "tunnel6" {
- neigh.IP = net.IP(attr.Value)
+ } else if attrLen == 16 {
+ // Can be IPv6 or FireWire HWAddr
+ link, err := LinkByIndex(neigh.LinkIndex)
+ if err == nil && link.Attrs().EncapType == "tunnel6" {
+ neigh.IP = net.IP(attr.Value)
+ } else {
+ neigh.HardwareAddr = net.HardwareAddr(attr.Value)
+ }
} else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
@@ -282,8 +297,126 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
case NDA_VNI:
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
+ case NDA_MASTER:
+ neigh.MasterIndex = int(native.Uint32(attr.Value[0:4]))
}
}
return &neigh, nil
}
+
+// NeighSubscribe takes a chan down which notifications will be sent
+// when neighbors are added or deleted. Close the 'done' chan to stop subscription.
+func NeighSubscribe(ch chan<- NeighUpdate, done <-chan struct{}) error {
+ return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
+}
+
+// NeighSubscribeAt works like NeighSubscribe plus it allows the caller
+// to choose the network namespace in which to subscribe (ns).
+func NeighSubscribeAt(ns netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}) error {
+ return neighSubscribeAt(ns, netns.None(), ch, done, nil, false)
+}
+
+// NeighSubscribeOptions contains a set of options to use with
+// NeighSubscribeWithOptions.
+type NeighSubscribeOptions struct {
+ Namespace *netns.NsHandle
+ ErrorCallback func(error)
+ ListExisting bool
+}
+
+// NeighSubscribeWithOptions work like NeighSubscribe but enable to
+// provide additional options to modify the behavior. Currently, the
+// namespace can be provided as well as an error callback.
+func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, options NeighSubscribeOptions) error {
+ if options.Namespace == nil {
+ none := netns.None()
+ options.Namespace = &none
+ }
+ return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
+}
+
+func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
+ s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH)
+ makeRequest := func(family int) error {
+ req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH,
+ unix.NLM_F_DUMP)
+ infmsg := nl.NewIfInfomsg(family)
+ req.AddData(infmsg)
+ if err := s.Send(req); err != nil {
+ return err
+ }
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ if done != nil {
+ go func() {
+ <-done
+ s.Close()
+ }()
+ }
+ if listExisting {
+ if err := makeRequest(unix.AF_UNSPEC); err != nil {
+ return err
+ }
+ // We have to wait for NLMSG_DONE before making AF_BRIDGE request
+ }
+ go func() {
+ defer close(ch)
+ for {
+ msgs, from, err := s.Receive()
+ if err != nil {
+ if cberr != nil {
+ cberr(err)
+ }
+ return
+ }
+ if from.Pid != nl.PidKernel {
+ if cberr != nil {
+ cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
+ }
+ continue
+ }
+ for _, m := range msgs {
+ if m.Header.Type == unix.NLMSG_DONE {
+ if listExisting {
+ // This will be called after handling AF_UNSPEC
+ // list request, we have to wait for NLMSG_DONE
+ // before making another request
+ if err := makeRequest(unix.AF_BRIDGE); err != nil {
+ if cberr != nil {
+ cberr(err)
+ }
+ return
+ }
+ listExisting = false
+ }
+ 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
+ }
+ neigh, err := NeighDeserialize(m.Data)
+ if err != nil {
+ if cberr != nil {
+ cberr(err)
+ }
+ return
+ }
+ ch <- NeighUpdate{Type: m.Header.Type, Neigh: *neigh}
+ }
+ }
+ }()
+
+ return nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/netlink.go b/vendor/github.com/vishvananda/netlink/netlink.go
index fb159526e..9cb685dc8 100644
--- a/vendor/github.com/vishvananda/netlink/netlink.go
+++ b/vendor/github.com/vishvananda/netlink/netlink.go
@@ -27,7 +27,8 @@ func ParseIPNet(s string) (*net.IPNet, error) {
if err != nil {
return nil, err
}
- return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil
+ ipNet.IP = ip
+ return ipNet, nil
}
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
index 86111b92c..42d3acf91 100644
--- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
@@ -48,10 +48,18 @@ func LinkSetVfVlan(link Link, vf, vlan int) error {
return ErrNotImplemented
}
+func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
+ return ErrNotImplemented
+}
+
func LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
+func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
+ return ErrNotImplemented
+}
+
func LinkSetNoMaster(link Link) error {
return ErrNotImplemented
}
@@ -152,6 +160,10 @@ func AddrAdd(link Link, addr *Addr) error {
return ErrNotImplemented
}
+func AddrReplace(link Link, addr *Addr) error {
+ return ErrNotImplemented
+}
+
func AddrDel(link Link, addr *Addr) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go
new file mode 100644
index 000000000..77cf6f469
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/netns_linux.go
@@ -0,0 +1,141 @@
+package netlink
+
+// Network namespace ID functions
+//
+// The kernel has a weird concept called the network namespace ID.
+// This is different from the file reference in proc (and any bind-mounted
+// namespaces, etc.)
+//
+// Instead, namespaces can be assigned a numeric ID at any time. Once set,
+// the ID is fixed. The ID can either be set manually by the user, or
+// automatically, triggered by certain kernel actions. The most common kernel
+// action that triggers namespace ID creation is moving one end of a veth pair
+// in to that namespace.
+
+import (
+ "fmt"
+
+ "github.com/vishvananda/netlink/nl"
+ "golang.org/x/sys/unix"
+)
+
+// These can be replaced by the values from sys/unix when it is next released.
+const (
+ _ = iota
+ NETNSA_NSID
+ NETNSA_PID
+ NETNSA_FD
+)
+
+// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
+// Returns -1 if the namespace does not have an ID set.
+func (h *Handle) GetNetNsIdByPid(pid int) (int, error) {
+ return h.getNetNsId(NETNSA_PID, uint32(pid))
+}
+
+// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
+// Returns -1 if the namespace does not have an ID set.
+func GetNetNsIdByPid(pid int) (int, error) {
+ return pkgHandle.GetNetNsIdByPid(pid)
+}
+
+// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
+// The ID can only be set for namespaces without an ID already set.
+func (h *Handle) SetNetNsIdByPid(pid, nsid int) error {
+ return h.setNetNsId(NETNSA_PID, uint32(pid), uint32(nsid))
+}
+
+// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
+// The ID can only be set for namespaces without an ID already set.
+func SetNetNsIdByPid(pid, nsid int) error {
+ return pkgHandle.SetNetNsIdByPid(pid, nsid)
+}
+
+// GetNetNsIdByFd looks up the network namespace ID for a given fd.
+// fd must be an open file descriptor to a namespace file.
+// Returns -1 if the namespace does not have an ID set.
+func (h *Handle) GetNetNsIdByFd(fd int) (int, error) {
+ return h.getNetNsId(NETNSA_FD, uint32(fd))
+}
+
+// GetNetNsIdByFd looks up the network namespace ID for a given fd.
+// fd must be an open file descriptor to a namespace file.
+// Returns -1 if the namespace does not have an ID set.
+func GetNetNsIdByFd(fd int) (int, error) {
+ return pkgHandle.GetNetNsIdByFd(fd)
+}
+
+// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
+// fd must be an open file descriptor to a namespace file.
+// The ID can only be set for namespaces without an ID already set.
+func (h *Handle) SetNetNsIdByFd(fd, nsid int) error {
+ return h.setNetNsId(NETNSA_FD, uint32(fd), uint32(nsid))
+}
+
+// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
+// fd must be an open file descriptor to a namespace file.
+// The ID can only be set for namespaces without an ID already set.
+func SetNetNsIdByFd(fd, nsid int) error {
+ return pkgHandle.SetNetNsIdByFd(fd, nsid)
+}
+
+// getNetNsId requests the netnsid for a given type-val pair
+// type should be either NETNSA_PID or NETNSA_FD
+func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
+ req := h.newNetlinkRequest(unix.RTM_GETNSID, unix.NLM_F_REQUEST)
+
+ rtgen := nl.NewRtGenMsg()
+ req.AddData(rtgen)
+
+ b := make([]byte, 4, 4)
+ native.PutUint32(b, val)
+ attr := nl.NewRtAttr(attrType, b)
+ req.AddData(attr)
+
+ msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
+
+ if err != nil {
+ return 0, err
+ }
+
+ for _, m := range msgs {
+ msg := nl.DeserializeRtGenMsg(m)
+
+ attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+ if err != nil {
+ return 0, err
+ }
+
+ for _, attr := range attrs {
+ switch attr.Attr.Type {
+ case NETNSA_NSID:
+ return int(int32(native.Uint32(attr.Value))), nil
+ }
+ }
+ }
+
+ return 0, fmt.Errorf("unexpected empty result")
+}
+
+// setNetNsId sets the netnsid for a given type-val pair
+// type should be either NETNSA_PID or NETNSA_FD
+// The ID can only be set for namespaces without an ID already set
+func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
+ req := h.newNetlinkRequest(unix.RTM_NEWNSID, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
+
+ rtgen := nl.NewRtGenMsg()
+ req.AddData(rtgen)
+
+ b := make([]byte, 4, 4)
+ native.PutUint32(b, val)
+ attr := nl.NewRtAttr(attrType, b)
+ req.AddData(attr)
+
+ b1 := make([]byte, 4, 4)
+ native.PutUint32(b1, newnsid)
+ attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
+ req.AddData(attr1)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
+ return err
+}
diff --git a/vendor/github.com/vishvananda/netlink/netns_unspecified.go b/vendor/github.com/vishvananda/netlink/netns_unspecified.go
new file mode 100644
index 000000000..5c5899e36
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/netns_unspecified.go
@@ -0,0 +1,19 @@
+// +build !linux
+
+package netlink
+
+func GetNetNsIdByPid(pid int) (int, error) {
+ return 0, ErrNotImplemented
+}
+
+func SetNetNsIdByPid(pid, nsid int) error {
+ return ErrNotImplemented
+}
+
+func GetNetNsIdByFd(fd int) (int, error) {
+ return 0, ErrNotImplemented
+}
+
+func SetNetNsIdByFd(fd, nsid int) error {
+ return ErrNotImplemented
+}
diff --git a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
index 6c0d33338..34e78ba8d 100644
--- a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
@@ -11,8 +11,8 @@ const (
/* Bridge Flags */
const (
- BRIDGE_FLAGS_MASTER = iota /* Bridge command to/from master */
- BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
+ BRIDGE_FLAGS_MASTER = iota + 1 /* Bridge command to/from master */
+ BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
)
/* Bridge management nested attributes
diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
index 380cc5967..79d2b6b89 100644
--- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
@@ -76,12 +76,17 @@ const (
// __CTA_MAX
// };
const (
- CTA_TUPLE_ORIG = 1
- CTA_TUPLE_REPLY = 2
- CTA_STATUS = 3
- CTA_TIMEOUT = 7
- CTA_MARK = 8
- CTA_PROTOINFO = 4
+ CTA_TUPLE_ORIG = 1
+ CTA_TUPLE_REPLY = 2
+ CTA_STATUS = 3
+ CTA_PROTOINFO = 4
+ CTA_TIMEOUT = 7
+ CTA_MARK = 8
+ CTA_COUNTERS_ORIG = 9
+ CTA_COUNTERS_REPLY = 10
+ CTA_USE = 11
+ CTA_ID = 12
+ CTA_TIMESTAMP = 20
)
// enum ctattr_tuple {
@@ -163,6 +168,29 @@ const (
CTA_PROTOINFO_TCP_FLAGS_REPLY = 5
)
+// enum ctattr_counters {
+// CTA_COUNTERS_UNSPEC,
+// CTA_COUNTERS_PACKETS, /* 64bit counters */
+// CTA_COUNTERS_BYTES, /* 64bit counters */
+// CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
+// CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
+// CTA_COUNTERS_PAD,
+// __CTA_COUNTERS_M
+// };
+// #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
+const (
+ CTA_COUNTERS_PACKETS = 1
+ CTA_COUNTERS_BYTES = 2
+)
+
+// enum CTA TIMESTAMP TLVs
+// CTA_TIMESTAMP_START /* 64bit value */
+// CTA_TIMESTAMP_STOP /* 64bit value */
+const (
+ CTA_TIMESTAMP_START = 1
+ CTA_TIMESTAMP_STOP = 2
+)
+
// /* General form of address family dependent message.
// */
// struct nfgenmsg {
diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
new file mode 100644
index 000000000..db66faaad
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
@@ -0,0 +1,40 @@
+package nl
+
+// All the following constants are coming from:
+// https://github.com/torvalds/linux/blob/master/include/uapi/linux/devlink.h
+
+const (
+ GENL_DEVLINK_VERSION = 1
+ GENL_DEVLINK_NAME = "devlink"
+)
+
+const (
+ DEVLINK_CMD_GET = 1
+ DEVLINK_CMD_ESWITCH_GET = 29
+ DEVLINK_CMD_ESWITCH_SET = 30
+)
+
+const (
+ DEVLINK_ATTR_BUS_NAME = 1
+ DEVLINK_ATTR_DEV_NAME = 2
+ DEVLINK_ATTR_ESWITCH_MODE = 25
+ DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
+ DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
+)
+
+const (
+ DEVLINK_ESWITCH_MODE_LEGACY = 0
+ DEVLINK_ESWITCH_MODE_SWITCHDEV = 1
+)
+
+const (
+ DEVLINK_ESWITCH_INLINE_MODE_NONE = 0
+ DEVLINK_ESWITCH_INLINE_MODE_LINK = 1
+ DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 2
+ DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 3
+)
+
+const (
+ DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0
+ DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index 84a3498dd..afb16a9c1 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -13,7 +13,9 @@ const (
IFLA_INFO_KIND
IFLA_INFO_DATA
IFLA_INFO_XSTATS
- IFLA_INFO_MAX = IFLA_INFO_XSTATS
+ IFLA_INFO_SLAVE_KIND
+ IFLA_INFO_SLAVE_DATA
+ IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA
)
const (
@@ -87,7 +89,8 @@ const (
const (
IFLA_IPVLAN_UNSPEC = iota
IFLA_IPVLAN_MODE
- IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
+ IFLA_IPVLAN_FLAG
+ IFLA_IPVLAN_MAX = IFLA_IPVLAN_FLAG
)
const (
@@ -164,6 +167,8 @@ const (
IFLA_BOND_SLAVE_PERM_HWADDR
IFLA_BOND_SLAVE_QUEUE_ID
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
+ IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
+ IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
)
const (
@@ -217,9 +222,11 @@ const (
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
* on/off switch
*/
- IFLA_VF_STATS /* network device statistics */
- IFLA_VF_TRUST /* Trust state of VF */
- IFLA_VF_MAX = IFLA_VF_TRUST
+ IFLA_VF_STATS /* network device statistics */
+ IFLA_VF_TRUST /* Trust state of VF */
+ IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */
+ IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */
+ IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
)
const (
@@ -248,6 +255,7 @@ const (
SizeofVfLinkState = 0x08
SizeofVfRssQueryEn = 0x08
SizeofVfTrust = 0x08
+ SizeofVfGUID = 0x10
)
// struct ifla_vf_mac {
@@ -430,6 +438,30 @@ func (msg *VfTrust) Serialize() []byte {
return (*(*[SizeofVfTrust]byte)(unsafe.Pointer(msg)))[:]
}
+// struct ifla_vf_guid {
+// __u32 vf;
+// __u32 rsvd;
+// __u64 guid;
+// };
+
+type VfGUID struct {
+ Vf uint32
+ Rsvd uint32
+ GUID uint64
+}
+
+func (msg *VfGUID) Len() int {
+ return SizeofVfGUID
+}
+
+func DeserializeVfGUID(b []byte) *VfGUID {
+ return (*VfGUID)(unsafe.Pointer(&b[0:SizeofVfGUID][0]))
+}
+
+func (msg *VfGUID) Serialize() []byte {
+ return (*(*[SizeofVfGUID]byte)(unsafe.Pointer(msg)))[:]
+}
+
const (
XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota
XDP_FLAGS_SKB_MODE
@@ -546,3 +578,33 @@ const (
GTP_ROLE_GGSN = iota
GTP_ROLE_SGSN
)
+
+const (
+ IFLA_XFRM_UNSPEC = iota
+ IFLA_XFRM_LINK
+ IFLA_XFRM_IF_ID
+
+ IFLA_XFRM_MAX = iota - 1
+)
+
+const (
+ IFLA_TUN_UNSPEC = iota
+ IFLA_TUN_OWNER
+ IFLA_TUN_GROUP
+ IFLA_TUN_TYPE
+ IFLA_TUN_PI
+ IFLA_TUN_VNET_HDR
+ IFLA_TUN_PERSIST
+ IFLA_TUN_MULTI_QUEUE
+ IFLA_TUN_NUM_QUEUES
+ IFLA_TUN_NUM_DISABLED_QUEUES
+ IFLA_TUN_MAX = IFLA_TUN_NUM_DISABLED_QUEUES
+)
+
+const (
+ IFLA_IPOIB_UNSPEC = iota
+ IFLA_IPOIB_PKEY
+ IFLA_IPOIB_MODE
+ IFLA_IPOIB_UMCAST
+ IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index bc8e82c2c..aaf56c671 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -21,7 +21,13 @@ const (
FAMILY_ALL = unix.AF_UNSPEC
FAMILY_V4 = unix.AF_INET
FAMILY_V6 = unix.AF_INET6
- FAMILY_MPLS = AF_MPLS
+ FAMILY_MPLS = unix.AF_MPLS
+ // Arbitrary set value (greater than default 4k) to allow receiving
+ // from kernel more verbose messages e.g. for statistics,
+ // tc rules or filters, or other more memory requiring data.
+ RECEIVE_BUFFER_SIZE = 65536
+ // Kernel netlink pid
+ PidKernel uint32 = 0
)
// SupportedNlFamilies contains the list of netlink families this netlink package supports
@@ -42,7 +48,7 @@ func GetIPFamily(ip net.IP) int {
var nativeEndian binary.ByteOrder
-// Get native endianness for the system
+// NativeEndian gets native endianness for the system
func NativeEndian() binary.ByteOrder {
if nativeEndian == nil {
var x uint32 = 0x01020304
@@ -271,15 +277,22 @@ func NewRtAttr(attrType int, data []byte) *RtAttr {
}
}
-// Create a new RtAttr obj anc add it as a child of an existing object
+// NewRtAttrChild adds an RtAttr as a child to the parent and returns the new attribute
+//
+// Deprecated: Use AddRtAttr() on the parent object
func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
+ return parent.AddRtAttr(attrType, data)
+}
+
+// AddRtAttr adds an RtAttr as a child and returns the new attribute
+func (a *RtAttr) AddRtAttr(attrType int, data []byte) *RtAttr {
attr := NewRtAttr(attrType, data)
- parent.children = append(parent.children, attr)
+ a.children = append(a.children, attr)
return attr
}
-// AddChild adds an existing RtAttr as a child.
-func (a *RtAttr) AddChild(attr *RtAttr) {
+// AddChild adds an existing NetlinkRequestData as a child.
+func (a *RtAttr) AddChild(attr NetlinkRequestData) {
a.children = append(a.children, attr)
}
@@ -360,16 +373,12 @@ func (req *NetlinkRequest) Serialize() []byte {
}
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
- if data != nil {
- req.Data = append(req.Data, data)
- }
+ req.Data = append(req.Data, data)
}
// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization
func (req *NetlinkRequest) AddRawData(data []byte) {
- if data != nil {
- req.RawData = append(req.RawData, data...)
- }
+ req.RawData = append(req.RawData, data...)
}
// Execute the request against a the given sockType.
@@ -413,10 +422,13 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
done:
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
return nil, err
}
+ if from.Pid != PidKernel {
+ return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
+ }
for _, m := range msgs {
if m.Header.Seq != req.Seq {
if sharedSocket {
@@ -425,7 +437,7 @@ done:
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
}
if m.Header.Pid != pid {
- return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
+ continue
}
if m.Header.Type == unix.NLMSG_DONE {
break done
@@ -610,21 +622,31 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
return nil
}
-func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
+func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) {
fd := int(atomic.LoadInt32(&s.fd))
if fd < 0 {
- return nil, fmt.Errorf("Receive called on a closed socket")
+ return nil, nil, fmt.Errorf("Receive called on a closed socket")
}
- rb := make([]byte, unix.Getpagesize())
- nr, _, err := unix.Recvfrom(fd, rb, 0)
+ var fromAddr *unix.SockaddrNetlink
+ var rb [RECEIVE_BUFFER_SIZE]byte
+ nr, from, err := unix.Recvfrom(fd, rb[:], 0)
if err != nil {
- return nil, err
+ return nil, nil, err
+ }
+ fromAddr, ok := from.(*unix.SockaddrNetlink)
+ if !ok {
+ return nil, nil, fmt.Errorf("Error converting to netlink sockaddr")
}
if nr < unix.NLMSG_HDRLEN {
- return nil, fmt.Errorf("Got short response from netlink")
+ return nil, nil, fmt.Errorf("Got short response from netlink")
+ }
+ rb2 := make([]byte, nr)
+ copy(rb2, rb[:nr])
+ nl, err := syscall.ParseNetlinkMessage(rb2)
+ if err != nil {
+ return nil, nil, err
}
- rb = rb[:nr]
- return syscall.ParseNetlinkMessage(rb)
+ return nl, fromAddr, nil
}
// SetSendTimeout allows to set a send timeout on the socket
diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
new file mode 100644
index 000000000..1224b747d
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
@@ -0,0 +1,35 @@
+package nl
+
+const (
+ RDMA_NL_GET_CLIENT_SHIFT = 10
+)
+
+const (
+ RDMA_NL_NLDEV = 5
+)
+
+const (
+ RDMA_NLDEV_CMD_GET = 1
+ RDMA_NLDEV_CMD_SET = 2
+ RDMA_NLDEV_CMD_SYS_GET = 6
+ RDMA_NLDEV_CMD_SYS_SET = 7
+)
+
+const (
+ RDMA_NLDEV_ATTR_DEV_INDEX = 1
+ RDMA_NLDEV_ATTR_DEV_NAME = 2
+ RDMA_NLDEV_ATTR_PORT_INDEX = 3
+ RDMA_NLDEV_ATTR_CAP_FLAGS = 4
+ RDMA_NLDEV_ATTR_FW_VERSION = 5
+ RDMA_NLDEV_ATTR_NODE_GUID = 6
+ RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7
+ RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8
+ RDMA_NLDEV_ATTR_LID = 9
+ RDMA_NLDEV_ATTR_SM_LID = 10
+ RDMA_NLDEV_ATTR_LMC = 11
+ RDMA_NLDEV_ATTR_PORT_STATE = 12
+ RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
+ RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
+ RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
+ RDMA_NLDEV_NET_NS_FD = 68
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/github.com/vishvananda/netlink/nl/route_linux.go
index f6906fcaf..03c1900ff 100644
--- a/vendor/github.com/vishvananda/netlink/nl/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/route_linux.go
@@ -79,3 +79,29 @@ func (msg *RtNexthop) Serialize() []byte {
}
return buf
}
+
+type RtGenMsg struct {
+ unix.RtGenmsg
+}
+
+func NewRtGenMsg() *RtGenMsg {
+ return &RtGenMsg{
+ RtGenmsg: unix.RtGenmsg{
+ Family: unix.AF_UNSPEC,
+ },
+ }
+}
+
+func (msg *RtGenMsg) Len() int {
+ return rtaAlignOf(unix.SizeofRtGenmsg)
+}
+
+func DeserializeRtGenMsg(b []byte) *RtGenMsg {
+ return &RtGenMsg{RtGenmsg: unix.RtGenmsg{Family: b[0]}}
+}
+
+func (msg *RtGenMsg) Serialize() []byte {
+ out := make([]byte, msg.Len())
+ out[0] = msg.Family
+ return out
+}
diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
index b3425f6b0..5774cbb15 100644
--- a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
@@ -99,6 +99,49 @@ func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
return mode, srh.Segments, nil
}
+func DecodeSEG6Srh(buf []byte) ([]net.IP, error) {
+ native := NativeEndian()
+ srh := IPv6SrHdr{
+ nextHdr: buf[0],
+ hdrLen: buf[1],
+ routingType: buf[2],
+ segmentsLeft: buf[3],
+ firstSegment: buf[4],
+ flags: buf[5],
+ reserved: native.Uint16(buf[6:8]),
+ }
+ buf = buf[8:]
+ if len(buf)%16 != 0 {
+ err := fmt.Errorf("DecodeSEG6Srh: error parsing Segment List (buf len: %d)", len(buf))
+ return nil, err
+ }
+ for len(buf) > 0 {
+ srh.Segments = append(srh.Segments, net.IP(buf[:16]))
+ buf = buf[16:]
+ }
+ return srh.Segments, nil
+}
+func EncodeSEG6Srh(segments []net.IP) ([]byte, error) {
+ nsegs := len(segments) // nsegs: number of segments
+ if nsegs == 0 {
+ return nil, errors.New("EncodeSEG6Srh: No Segments")
+ }
+ b := make([]byte, 8, 8+len(segments)*16)
+ native := NativeEndian()
+ b[0] = 0 // srh.nextHdr (0 when calling netlink)
+ b[1] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit)
+ b[2] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA)
+ b[3] = uint8(nsegs - 1) // srh.segmentsLeft
+ b[4] = uint8(nsegs - 1) // srh.firstSegment
+ b[5] = 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[6:], 0) // srh.reserved
+ for _, netIP := range segments {
+ b = append(b, netIP...) // srh.Segments
+ }
+ return b, nil
+}
+
// Helper functions
func SEG6EncapModeString(mode int) string {
switch mode {
diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
new file mode 100644
index 000000000..150017726
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
@@ -0,0 +1,76 @@
+package nl
+
+import ()
+
+// seg6local parameters
+const (
+ SEG6_LOCAL_UNSPEC = iota
+ SEG6_LOCAL_ACTION
+ SEG6_LOCAL_SRH
+ SEG6_LOCAL_TABLE
+ SEG6_LOCAL_NH4
+ SEG6_LOCAL_NH6
+ SEG6_LOCAL_IIF
+ SEG6_LOCAL_OIF
+ __SEG6_LOCAL_MAX
+)
+const (
+ SEG6_LOCAL_MAX = __SEG6_LOCAL_MAX
+)
+
+// seg6local actions
+const (
+ SEG6_LOCAL_ACTION_END = iota + 1 // 1
+ SEG6_LOCAL_ACTION_END_X // 2
+ SEG6_LOCAL_ACTION_END_T // 3
+ SEG6_LOCAL_ACTION_END_DX2 // 4
+ SEG6_LOCAL_ACTION_END_DX6 // 5
+ SEG6_LOCAL_ACTION_END_DX4 // 6
+ SEG6_LOCAL_ACTION_END_DT6 // 7
+ SEG6_LOCAL_ACTION_END_DT4 // 8
+ SEG6_LOCAL_ACTION_END_B6 // 9
+ SEG6_LOCAL_ACTION_END_B6_ENCAPS // 10
+ SEG6_LOCAL_ACTION_END_BM // 11
+ SEG6_LOCAL_ACTION_END_S // 12
+ SEG6_LOCAL_ACTION_END_AS // 13
+ SEG6_LOCAL_ACTION_END_AM // 14
+ __SEG6_LOCAL_ACTION_MAX
+)
+const (
+ SEG6_LOCAL_ACTION_MAX = __SEG6_LOCAL_ACTION_MAX - 1
+)
+
+// Helper functions
+func SEG6LocalActionString(action int) string {
+ switch action {
+ case SEG6_LOCAL_ACTION_END:
+ return "End"
+ case SEG6_LOCAL_ACTION_END_X:
+ return "End.X"
+ case SEG6_LOCAL_ACTION_END_T:
+ return "End.T"
+ case SEG6_LOCAL_ACTION_END_DX2:
+ return "End.DX2"
+ case SEG6_LOCAL_ACTION_END_DX6:
+ return "End.DX6"
+ case SEG6_LOCAL_ACTION_END_DX4:
+ return "End.DX4"
+ case SEG6_LOCAL_ACTION_END_DT6:
+ return "End.DT6"
+ case SEG6_LOCAL_ACTION_END_DT4:
+ return "End.DT4"
+ case SEG6_LOCAL_ACTION_END_B6:
+ return "End.B6"
+ case SEG6_LOCAL_ACTION_END_B6_ENCAPS:
+ return "End.B6.Encaps"
+ case SEG6_LOCAL_ACTION_END_BM:
+ return "End.BM"
+ case SEG6_LOCAL_ACTION_END_S:
+ return "End.S"
+ case SEG6_LOCAL_ACTION_END_AS:
+ return "End.AS"
+ case SEG6_LOCAL_ACTION_END_AM:
+ return "End.AM"
+ }
+ return "unknown"
+}
diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go
index fc631e0e5..f7f7f92e6 100644
--- a/vendor/github.com/vishvananda/netlink/nl/syscall.go
+++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go
@@ -42,16 +42,6 @@ const (
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
)
-const (
- AF_MPLS = 28
-)
-
-const (
- RTA_NEWDST = 0x13
- RTA_ENCAP_TYPE = 0x15
- RTA_ENCAP = 0x16
-)
-
// RTA_ENCAP subtype
const (
MPLS_IPTUNNEL_UNSPEC = iota
@@ -67,6 +57,7 @@ const (
LWTUNNEL_ENCAP_IP6
LWTUNNEL_ENCAP_SEG6
LWTUNNEL_ENCAP_BPF
+ LWTUNNEL_ENCAP_SEG6_LOCAL
)
// routing header types
diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
index 94ebc290a..501f554b2 100644
--- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
@@ -1,6 +1,7 @@
package nl
import (
+ "encoding/binary"
"unsafe"
)
@@ -65,6 +66,15 @@ const (
)
const (
+ TCA_STATS_UNSPEC = iota
+ TCA_STATS_BASIC
+ TCA_STATS_RATE_EST
+ TCA_STATS_QUEUE
+ TCA_STATS_APP
+ TCA_STATS_MAX = TCA_STATS_APP
+)
+
+const (
SizeofTcMsg = 0x14
SizeofTcActionMsg = 0x04
SizeofTcPrioMap = 0x14
@@ -79,7 +89,10 @@ const (
SizeofTcU32Key = 0x10
SizeofTcU32Sel = 0x10 // without keys
SizeofTcGen = 0x14
+ SizeofTcConnmark = SizeofTcGen + 0x04
SizeofTcMirred = SizeofTcGen + 0x08
+ SizeofTcTunnelKey = SizeofTcGen + 0x04
+ SizeofTcSkbEdit = SizeofTcGen
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
)
@@ -412,6 +425,57 @@ func (x *TcHtbGlob) Serialize() []byte {
return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:]
}
+// HFSC
+
+type Curve struct {
+ m1 uint32
+ d uint32
+ m2 uint32
+}
+
+type HfscCopt struct {
+ Rsc Curve
+ Fsc Curve
+ Usc Curve
+}
+
+func (c *Curve) Attrs() (uint32, uint32, uint32) {
+ return c.m1, c.d, c.m2
+}
+
+func (c *Curve) Set(m1 uint32, d uint32, m2 uint32) {
+ c.m1 = m1
+ c.d = d
+ c.m2 = m2
+}
+
+func DeserializeHfscCurve(b []byte) *Curve {
+ return &Curve{
+ m1: binary.LittleEndian.Uint32(b[0:4]),
+ d: binary.LittleEndian.Uint32(b[4:8]),
+ m2: binary.LittleEndian.Uint32(b[8:12]),
+ }
+}
+
+func SerializeHfscCurve(c *Curve) (b []byte) {
+ t := make([]byte, binary.MaxVarintLen32)
+ binary.LittleEndian.PutUint32(t, c.m1)
+ b = append(b, t[:4]...)
+ binary.LittleEndian.PutUint32(t, c.d)
+ b = append(b, t[:4]...)
+ binary.LittleEndian.PutUint32(t, c.m2)
+ b = append(b, t[:4]...)
+ return b
+}
+
+type TcHfscOpt struct {
+ Defcls uint16
+}
+
+func (x *TcHfscOpt) Serialize() []byte {
+ return (*(*[2]byte)(unsafe.Pointer(x)))[:]
+}
+
const (
TCA_U32_UNSPEC = iota
TCA_U32_CLASSID
@@ -586,12 +650,48 @@ const (
TCA_BPF_FD
TCA_BPF_NAME
TCA_BPF_FLAGS
- TCA_BPF_MAX = TCA_BPF_FLAGS
+ TCA_BPF_FLAGS_GEN
+ TCA_BPF_TAG
+ TCA_BPF_ID
+ TCA_BPF_MAX = TCA_BPF_ID
)
type TcBpf TcGen
const (
+ TCA_ACT_CONNMARK = 14
+)
+
+const (
+ TCA_CONNMARK_UNSPEC = iota
+ TCA_CONNMARK_PARMS
+ TCA_CONNMARK_TM
+ TCA_CONNMARK_MAX = TCA_CONNMARK_TM
+)
+
+// struct tc_connmark {
+// tc_gen;
+// __u16 zone;
+// };
+
+type TcConnmark struct {
+ TcGen
+ Zone uint16
+}
+
+func (msg *TcConnmark) Len() int {
+ return SizeofTcConnmark
+}
+
+func DeserializeTcConnmark(b []byte) *TcConnmark {
+ return (*TcConnmark)(unsafe.Pointer(&b[0:SizeofTcConnmark][0]))
+}
+
+func (x *TcConnmark) Serialize() []byte {
+ return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:]
+}
+
+const (
TCA_ACT_MIRRED = 8
)
@@ -626,6 +726,63 @@ func (x *TcMirred) Serialize() []byte {
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
}
+const (
+ TCA_TUNNEL_KEY_UNSPEC = iota
+ TCA_TUNNEL_KEY_TM
+ TCA_TUNNEL_KEY_PARMS
+ TCA_TUNNEL_KEY_ENC_IPV4_SRC
+ TCA_TUNNEL_KEY_ENC_IPV4_DST
+ TCA_TUNNEL_KEY_ENC_IPV6_SRC
+ TCA_TUNNEL_KEY_ENC_IPV6_DST
+ TCA_TUNNEL_KEY_ENC_KEY_ID
+ TCA_TUNNEL_KEY_MAX = TCA_TUNNEL_KEY_ENC_KEY_ID
+)
+
+type TcTunnelKey struct {
+ TcGen
+ Action int32
+}
+
+func (x *TcTunnelKey) Len() int {
+ return SizeofTcTunnelKey
+}
+
+func DeserializeTunnelKey(b []byte) *TcTunnelKey {
+ return (*TcTunnelKey)(unsafe.Pointer(&b[0:SizeofTcTunnelKey][0]))
+}
+
+func (x *TcTunnelKey) Serialize() []byte {
+ return (*(*[SizeofTcTunnelKey]byte)(unsafe.Pointer(x)))[:]
+}
+
+const (
+ TCA_SKBEDIT_UNSPEC = iota
+ TCA_SKBEDIT_TM
+ TCA_SKBEDIT_PARMS
+ TCA_SKBEDIT_PRIORITY
+ TCA_SKBEDIT_QUEUE_MAPPING
+ TCA_SKBEDIT_MARK
+ TCA_SKBEDIT_PAD
+ TCA_SKBEDIT_PTYPE
+ TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
+)
+
+type TcSkbEdit struct {
+ TcGen
+}
+
+func (x *TcSkbEdit) Len() int {
+ return SizeofTcSkbEdit
+}
+
+func DeserializeSkbEdit(b []byte) *TcSkbEdit {
+ return (*TcSkbEdit)(unsafe.Pointer(&b[0:SizeofTcSkbEdit][0]))
+}
+
+func (x *TcSkbEdit) Serialize() []byte {
+ return (*(*[SizeofTcSkbEdit]byte)(unsafe.Pointer(x)))[:]
+}
+
// struct tc_police {
// __u32 index;
// int action;
@@ -708,3 +865,10 @@ const (
TCA_FQ_CODEL_DROP_BATCH_SIZE
TCA_FQ_CODEL_MEMORY_LIMIT
)
+
+const (
+ TCA_HFSC_UNSPEC = iota
+ TCA_HFSC_RSC
+ TCA_HFSC_FSC
+ TCA_HFSC_USC
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
index 09a2ffa10..dce9073f7 100644
--- a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
@@ -50,34 +50,44 @@ const (
// Attribute types
const (
/* Netlink message attributes. */
- XFRMA_UNSPEC = 0x00
- XFRMA_ALG_AUTH = 0x01 /* struct xfrm_algo */
- XFRMA_ALG_CRYPT = 0x02 /* struct xfrm_algo */
- XFRMA_ALG_COMP = 0x03 /* struct xfrm_algo */
- XFRMA_ENCAP = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */
- XFRMA_TMPL = 0x05 /* 1 or more struct xfrm_user_tmpl */
- XFRMA_SA = 0x06 /* struct xfrm_usersa_info */
- XFRMA_POLICY = 0x07 /* struct xfrm_userpolicy_info */
- XFRMA_SEC_CTX = 0x08 /* struct xfrm_sec_ctx */
- XFRMA_LTIME_VAL = 0x09
- XFRMA_REPLAY_VAL = 0x0a
- XFRMA_REPLAY_THRESH = 0x0b
- XFRMA_ETIMER_THRESH = 0x0c
- XFRMA_SRCADDR = 0x0d /* xfrm_address_t */
- XFRMA_COADDR = 0x0e /* xfrm_address_t */
- XFRMA_LASTUSED = 0x0f /* unsigned long */
- XFRMA_POLICY_TYPE = 0x10 /* struct xfrm_userpolicy_type */
- XFRMA_MIGRATE = 0x11
- XFRMA_ALG_AEAD = 0x12 /* struct xfrm_algo_aead */
- XFRMA_KMADDRESS = 0x13 /* struct xfrm_user_kmaddress */
- XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */
- XFRMA_MARK = 0x15 /* struct xfrm_mark */
- XFRMA_TFCPAD = 0x16 /* __u32 */
- XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */
- XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */
- XFRMA_MAX = 0x18
+ XFRMA_UNSPEC = iota
+ XFRMA_ALG_AUTH /* struct xfrm_algo */
+ XFRMA_ALG_CRYPT /* struct xfrm_algo */
+ XFRMA_ALG_COMP /* struct xfrm_algo */
+ XFRMA_ENCAP /* struct xfrm_algo + struct xfrm_encap_tmpl */
+ XFRMA_TMPL /* 1 or more struct xfrm_user_tmpl */
+ XFRMA_SA /* struct xfrm_usersa_info */
+ XFRMA_POLICY /* struct xfrm_userpolicy_info */
+ XFRMA_SEC_CTX /* struct xfrm_sec_ctx */
+ XFRMA_LTIME_VAL
+ XFRMA_REPLAY_VAL
+ XFRMA_REPLAY_THRESH
+ XFRMA_ETIMER_THRESH
+ XFRMA_SRCADDR /* xfrm_address_t */
+ XFRMA_COADDR /* xfrm_address_t */
+ XFRMA_LASTUSED /* unsigned long */
+ XFRMA_POLICY_TYPE /* struct xfrm_userpolicy_type */
+ XFRMA_MIGRATE
+ XFRMA_ALG_AEAD /* struct xfrm_algo_aead */
+ XFRMA_KMADDRESS /* struct xfrm_user_kmaddress */
+ XFRMA_ALG_AUTH_TRUNC /* struct xfrm_algo_auth */
+ XFRMA_MARK /* struct xfrm_mark */
+ XFRMA_TFCPAD /* __u32 */
+ XFRMA_REPLAY_ESN_VAL /* struct xfrm_replay_esn */
+ XFRMA_SA_EXTRA_FLAGS /* __u32 */
+ XFRMA_PROTO /* __u8 */
+ XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */
+ XFRMA_PAD
+ XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
+ XFRMA_SET_MARK /* __u32 */
+ XFRMA_SET_MARK_MASK /* __u32 */
+ XFRMA_IF_ID /* __u32 */
+
+ XFRMA_MAX = iota - 1
)
+const XFRMA_OUTPUT_MARK = XFRMA_SET_MARK
+
const (
SizeofXfrmAddress = 0x10
SizeofXfrmSelector = 0x38
diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go
index 0087c4438..60b23b374 100644
--- a/vendor/github.com/vishvananda/netlink/protinfo.go
+++ b/vendor/github.com/vishvananda/netlink/protinfo.go
@@ -18,6 +18,10 @@ type Protinfo struct {
// String returns a list of enabled flags
func (prot *Protinfo) String() string {
+ if prot == nil {
+ return "<nil>"
+ }
+
var boolStrings []string
if prot.Hairpin {
boolStrings = append(boolStrings, "Hairpin")
diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go
index 43c465f05..15b65123c 100644
--- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go
+++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go
@@ -41,7 +41,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
if err != nil {
return pi, err
}
- pi = *parseProtinfo(infos)
+ pi = parseProtinfo(infos)
return pi, nil
}
@@ -49,8 +49,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
return pi, fmt.Errorf("Device with index %d not found", base.Index)
}
-func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
- var pi Protinfo
+func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
for _, info := range infos {
switch info.Attr.Type {
case nl.IFLA_BRPORT_MODE:
@@ -71,5 +70,5 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
pi.ProxyArpWiFi = byteToBool(info.Value[0])
}
}
- return &pi
+ return
}
diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go
index 3df4b5c29..af78305ac 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc.go
@@ -176,6 +176,13 @@ type Netem struct {
CorruptCorr uint32
}
+func (netem *Netem) String() string {
+ return fmt.Sprintf(
+ "{Latency: %v, Limit: %v, Loss: %v, Gap: %v, Duplicate: %v, Jitter: %v}",
+ netem.Latency, netem.Limit, netem.Loss, netem.Gap, netem.Duplicate, netem.Jitter,
+ )
+}
+
func (qdisc *Netem) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
@@ -231,6 +238,33 @@ func (qdisc *GenericQdisc) Type() string {
return qdisc.QdiscType
}
+type Hfsc struct {
+ QdiscAttrs
+ Defcls uint16
+}
+
+func NewHfsc(attrs QdiscAttrs) *Hfsc {
+ return &Hfsc{
+ QdiscAttrs: attrs,
+ Defcls: 1,
+ }
+}
+
+func (hfsc *Hfsc) Attrs() *QdiscAttrs {
+ return &hfsc.QdiscAttrs
+}
+
+func (hfsc *Hfsc) Type() string {
+ return "hfsc"
+}
+
+func (hfsc *Hfsc) String() string {
+ return fmt.Sprintf(
+ "{%v -- default: %d}",
+ hfsc.Attrs(), hfsc.Defcls,
+ )
+}
+
// Fq is a classless packet scheduler meant to be mostly used for locally generated traffic.
type Fq struct {
QdiscAttrs
@@ -249,6 +283,13 @@ type Fq struct {
LowRateThreshold uint32
}
+func (fq *Fq) String() string {
+ return fmt.Sprintf(
+ "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}",
+ fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold,
+ )
+}
+
func NewFq(attrs QdiscAttrs) *Fq {
return &Fq{
QdiscAttrs: attrs,
@@ -276,6 +317,13 @@ type FqCodel struct {
// There are some more attributes here, but support for them seems not ubiquitous
}
+func (fqcodel *FqCodel) String() string {
+ return fmt.Sprintf(
+ "{%v -- Target: %v, Limit: %v, Interval: %v, ECM: %v, Flows: %v, Quantum: %v}",
+ fqcodel.Attrs(), fqcodel.Target, fqcodel.Limit, fqcodel.Interval, fqcodel.ECN, fqcodel.Flows, fqcodel.Quantum,
+ )
+}
+
func NewFqCodel(attrs QdiscAttrs) *FqCodel {
return &FqCodel{
QdiscAttrs: attrs,
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index 3794ac18a..e9eee5908 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -175,15 +175,15 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
opt.Peakrate.Rate = uint32(qdisc.Peakrate)
opt.Limit = qdisc.Limit
opt.Buffer = qdisc.Buffer
- nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize())
+ options.AddRtAttr(nl.TCA_TBF_PARMS, opt.Serialize())
if qdisc.Rate >= uint64(1<<32) {
- nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate))
+ options.AddRtAttr(nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate))
}
if qdisc.Peakrate >= uint64(1<<32) {
- nl.NewRtAttrChild(options, nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate))
+ options.AddRtAttr(nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate))
}
if qdisc.Peakrate > 0 {
- nl.NewRtAttrChild(options, nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst))
+ options.AddRtAttr(nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst))
}
case *Htb:
opt := nl.TcHtbGlob{}
@@ -193,8 +193,12 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
// TODO: Handle Debug properly. For now default to 0
opt.Debug = qdisc.Debug
opt.DirectPkts = qdisc.DirectPkts
- nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize())
- // nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
+ options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize())
+ // options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
+ case *Hfsc:
+ opt := nl.TcHfscOpt{}
+ opt.Defcls = qdisc.Defcls
+ options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
case *Netem:
opt := nl.TcNetemQopt{}
opt.Latency = qdisc.Latency
@@ -211,21 +215,21 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
corr.DupCorr = qdisc.DuplicateCorr
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
- nl.NewRtAttrChild(options, nl.TCA_NETEM_CORR, corr.Serialize())
+ options.AddRtAttr(nl.TCA_NETEM_CORR, corr.Serialize())
}
// Corruption
corruption := nl.TcNetemCorrupt{}
corruption.Probability = qdisc.CorruptProb
corruption.Correlation = qdisc.CorruptCorr
if corruption.Probability > 0 {
- nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize())
+ options.AddRtAttr(nl.TCA_NETEM_CORRUPT, corruption.Serialize())
}
// Reorder
reorder := nl.TcNetemReorder{}
reorder.Probability = qdisc.ReorderProb
reorder.Correlation = qdisc.ReorderCorr
if reorder.Probability > 0 {
- nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize())
+ options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
}
case *Ingress:
// ingress filters must use the proper handle
@@ -233,50 +237,54 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(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))))
+ options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
}
+ default:
+ options = nil
}
- req.AddData(options)
+ if options != nil {
+ req.AddData(options)
+ }
return nil
}
@@ -348,6 +356,8 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
qdisc = &Htb{}
case "fq":
qdisc = &Fq{}
+ case "hfsc":
+ qdisc = &Hfsc{}
case "fq_codel":
qdisc = &FqCodel{}
case "netem":
@@ -375,6 +385,10 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
if err := parseTbfData(qdisc, data); err != nil {
return nil, err
}
+ case "hfsc":
+ if err := parseHfscData(qdisc, attr.Value); err != nil {
+ return nil, err
+ }
case "htb":
data, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
@@ -474,6 +488,13 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
return nil
}
+func parseHfscData(qdisc Qdisc, data []byte) error {
+ Hfsc := qdisc.(*Hfsc)
+ native = nl.NativeEndian()
+ Hfsc.Defcls = native.Uint16(data)
+ return nil
+}
+
func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
native = nl.NativeEndian()
fq := qdisc.(*Fq)
diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
new file mode 100644
index 000000000..2d0bdc8c3
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
@@ -0,0 +1,264 @@
+package netlink
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "net"
+
+ "github.com/vishvananda/netlink/nl"
+ "golang.org/x/sys/unix"
+)
+
+// LinkAttrs represents data shared by most link types
+type RdmaLinkAttrs struct {
+ Index uint32
+ Name string
+ FirmwareVersion string
+ NodeGuid string
+ SysImageGuid string
+}
+
+// Link represents a rdma device from netlink.
+type RdmaLink struct {
+ Attrs RdmaLinkAttrs
+}
+
+func getProtoField(clientType int, op int) int {
+ return ((clientType << nl.RDMA_NL_GET_CLIENT_SHIFT) | op)
+}
+
+func uint64ToGuidString(guid uint64) string {
+ //Convert to byte array
+ sysGuidBytes := new(bytes.Buffer)
+ binary.Write(sysGuidBytes, binary.LittleEndian, guid)
+
+ //Convert to HardwareAddr
+ sysGuidNet := net.HardwareAddr(sysGuidBytes.Bytes())
+
+ //Get the String
+ return sysGuidNet.String()
+}
+
+func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) {
+
+ link := RdmaLink{}
+
+ reader := bytes.NewReader(data)
+ for reader.Len() >= 4 {
+ _, attrType, len, value := parseNfAttrTLV(reader)
+
+ switch attrType {
+ case nl.RDMA_NLDEV_ATTR_DEV_INDEX:
+ var Index uint32
+ r := bytes.NewReader(value)
+ binary.Read(r, nl.NativeEndian(), &Index)
+ link.Attrs.Index = Index
+ case nl.RDMA_NLDEV_ATTR_DEV_NAME:
+ link.Attrs.Name = string(value[0 : len-1])
+ case nl.RDMA_NLDEV_ATTR_FW_VERSION:
+ link.Attrs.FirmwareVersion = string(value[0 : len-1])
+ case nl.RDMA_NLDEV_ATTR_NODE_GUID:
+ var guid uint64
+ r := bytes.NewReader(value)
+ binary.Read(r, nl.NativeEndian(), &guid)
+ link.Attrs.NodeGuid = uint64ToGuidString(guid)
+ case nl.RDMA_NLDEV_ATTR_SYS_IMAGE_GUID:
+ var sysGuid uint64
+ r := bytes.NewReader(value)
+ binary.Read(r, nl.NativeEndian(), &sysGuid)
+ link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid)
+ }
+ if (len % 4) != 0 {
+ // Skip pad bytes
+ reader.Seek(int64(4-(len%4)), seekCurrent)
+ }
+ }
+ return &link, nil
+}
+
+func execRdmaGetLink(req *nl.NetlinkRequest, name string) (*RdmaLink, error) {
+
+ msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
+ if err != nil {
+ return nil, err
+ }
+ for _, m := range msgs {
+ link, err := executeOneGetRdmaLink(m)
+ if err != nil {
+ return nil, err
+ }
+ if link.Attrs.Name == name {
+ return link, nil
+ }
+ }
+ return nil, fmt.Errorf("Rdma device %v not found", name)
+}
+
+func execRdmaSetLink(req *nl.NetlinkRequest) error {
+
+ _, err := req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
+
+// RdmaLinkByName finds a link by name and returns a pointer to the object if
+// found and nil error, otherwise returns error code.
+func RdmaLinkByName(name string) (*RdmaLink, error) {
+ return pkgHandle.RdmaLinkByName(name)
+}
+
+// RdmaLinkByName finds a link by name and returns a pointer to the object if
+// found and nil error, otherwise returns error code.
+func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) {
+
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP)
+
+ return execRdmaGetLink(req, name)
+}
+
+// RdmaLinkSetName sets the name of the rdma link device. Return nil on success
+// or error otherwise.
+// Equivalent to: `rdma dev set $old_devname name $name`
+func RdmaLinkSetName(link *RdmaLink, name string) error {
+ return pkgHandle.RdmaLinkSetName(link, name)
+}
+
+// RdmaLinkSetName sets the name of the rdma link device. Return nil on success
+// or error otherwise.
+// Equivalent to: `rdma dev set $old_devname name $name`
+func (h *Handle) RdmaLinkSetName(link *RdmaLink, name string) error {
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(link.Attrs.Index))
+ data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b)
+ req.AddData(data)
+
+ b = make([]byte, len(name)+1)
+ copy(b, name)
+ data = nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, b)
+ req.AddData(data)
+
+ return execRdmaSetLink(req)
+}
+
+func netnsModeToString(mode uint8) string {
+ switch mode {
+ case 0:
+ return "exclusive"
+ case 1:
+ return "shared"
+ default:
+ return "unknown"
+ }
+}
+
+func executeOneGetRdmaNetnsMode(data []byte) (string, error) {
+ reader := bytes.NewReader(data)
+ for reader.Len() >= 4 {
+ _, attrType, len, value := parseNfAttrTLV(reader)
+
+ switch attrType {
+ case nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE:
+ var mode uint8
+ r := bytes.NewReader(value)
+ binary.Read(r, nl.NativeEndian(), &mode)
+ return netnsModeToString(mode), nil
+ }
+ if (len % 4) != 0 {
+ // Skip pad bytes
+ reader.Seek(int64(4-(len%4)), seekCurrent)
+ }
+ }
+ return "", fmt.Errorf("Invalid netns mode")
+}
+
+// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem
+// Returns mode string and error status as nil on success or returns error
+// otherwise.
+// Equivalent to: `rdma system show netns'
+func RdmaSystemGetNetnsMode() (string, error) {
+ return pkgHandle.RdmaSystemGetNetnsMode()
+}
+
+// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem
+// Returns mode string and error status as nil on success or returns error
+// otherwise.
+// Equivalent to: `rdma system show netns'
+func (h *Handle) RdmaSystemGetNetnsMode() (string, error) {
+
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_GET)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
+ if err != nil {
+ return "", err
+ }
+ if len(msgs) == 0 {
+ return "", fmt.Errorf("No valid response from kernel")
+ }
+ return executeOneGetRdmaNetnsMode(msgs[0])
+}
+
+func netnsModeStringToUint8(mode string) (uint8, error) {
+ switch mode {
+ case "exclusive":
+ return 0, nil
+ case "shared":
+ return 1, nil
+ default:
+ return 0, fmt.Errorf("Invalid mode; %q", mode)
+ }
+}
+
+// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem
+// Returns nil on success or appropriate error code.
+// Equivalent to: `rdma system set netns { shared | exclusive }'
+func RdmaSystemSetNetnsMode(NewMode string) error {
+ return pkgHandle.RdmaSystemSetNetnsMode(NewMode)
+}
+
+// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem
+// Returns nil on success or appropriate error code.
+// Equivalent to: `rdma system set netns { shared | exclusive }'
+func (h *Handle) RdmaSystemSetNetnsMode(NewMode string) error {
+ value, err := netnsModeStringToUint8(NewMode)
+ if err != nil {
+ return err
+ }
+
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_SET)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ data := nl.NewRtAttr(nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE, []byte{value})
+ req.AddData(data)
+
+ _, err = req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
+
+// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The
+// fd must be an open file descriptor to a network namespace.
+// Similar to: `rdma dev set $dev netns $ns`
+func RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
+ return pkgHandle.RdmaLinkSetNsFd(link, fd)
+}
+
+// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The
+// fd must be an open file descriptor to a network namespace.
+// Similar to: `rdma dev set $dev netns $ns`
+func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX,
+ nl.Uint32Attr(link.Attrs.Index))
+ req.AddData(data)
+
+ data = nl.NewRtAttr(nl.RDMA_NLDEV_NET_NS_FD, nl.Uint32Attr(fd))
+ req.AddData(data)
+
+ return execRdmaSetLink(req)
+}
diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go
index 2cd58ee33..58ff1af60 100644
--- a/vendor/github.com/vishvananda/netlink/route.go
+++ b/vendor/github.com/vishvananda/netlink/route.go
@@ -47,6 +47,7 @@ type Route struct {
Encap Encap
MTU int
AdvMSS int
+ Hoplimit int
}
func (r Route) String() string {
@@ -89,6 +90,7 @@ func (r Route) Equal(x Route) bool {
r.Table == x.Table &&
r.Type == x.Type &&
r.Tos == x.Tos &&
+ r.Hoplimit == x.Hoplimit &&
r.Flags == x.Flags &&
(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 3f856711f..c69c595ed 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -32,6 +32,7 @@ const (
RT_FILTER_SRC
RT_FILTER_GW
RT_FILTER_TABLE
+ RT_FILTER_HOPLIMIT
)
const (
@@ -207,6 +208,7 @@ func (e *SEG6Encap) Decode(buf []byte) error {
}
buf = buf[:l] // make sure buf size upper limit is Length
typ := native.Uint16(buf[2:])
+ // LWTUNNEL_ENCAP_SEG6 has only one attr type SEG6_IPTUNNEL_SRH
if typ != nl.SEG6_IPTUNNEL_SRH {
return fmt.Errorf("unknown SEG6 Type: %d", typ)
}
@@ -259,6 +261,188 @@ func (e *SEG6Encap) Equal(x Encap) bool {
return true
}
+// SEG6LocalEncap definitions
+type SEG6LocalEncap struct {
+ Flags [nl.SEG6_LOCAL_MAX]bool
+ Action int
+ Segments []net.IP // from SRH in seg6_local_lwt
+ Table int // table id for End.T and End.DT6
+ InAddr net.IP
+ In6Addr net.IP
+ Iif int
+ Oif int
+}
+
+func (e *SEG6LocalEncap) Type() int {
+ return nl.LWTUNNEL_ENCAP_SEG6_LOCAL
+}
+func (e *SEG6LocalEncap) Decode(buf []byte) error {
+ attrs, err := nl.ParseRouteAttr(buf)
+ if err != nil {
+ return err
+ }
+ native := nl.NativeEndian()
+ for _, attr := range attrs {
+ switch attr.Attr.Type {
+ case nl.SEG6_LOCAL_ACTION:
+ e.Action = int(native.Uint32(attr.Value[0:4]))
+ e.Flags[nl.SEG6_LOCAL_ACTION] = true
+ case nl.SEG6_LOCAL_SRH:
+ e.Segments, err = nl.DecodeSEG6Srh(attr.Value[:])
+ e.Flags[nl.SEG6_LOCAL_SRH] = true
+ case nl.SEG6_LOCAL_TABLE:
+ e.Table = int(native.Uint32(attr.Value[0:4]))
+ e.Flags[nl.SEG6_LOCAL_TABLE] = true
+ case nl.SEG6_LOCAL_NH4:
+ e.InAddr = net.IP(attr.Value[0:4])
+ e.Flags[nl.SEG6_LOCAL_NH4] = true
+ case nl.SEG6_LOCAL_NH6:
+ e.In6Addr = net.IP(attr.Value[0:16])
+ e.Flags[nl.SEG6_LOCAL_NH6] = true
+ case nl.SEG6_LOCAL_IIF:
+ e.Iif = int(native.Uint32(attr.Value[0:4]))
+ e.Flags[nl.SEG6_LOCAL_IIF] = true
+ case nl.SEG6_LOCAL_OIF:
+ e.Oif = int(native.Uint32(attr.Value[0:4]))
+ e.Flags[nl.SEG6_LOCAL_OIF] = true
+ }
+ }
+ return err
+}
+func (e *SEG6LocalEncap) Encode() ([]byte, error) {
+ var err error
+ native := nl.NativeEndian()
+ res := make([]byte, 8)
+ native.PutUint16(res, 8) // length
+ native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION)
+ native.PutUint32(res[4:], uint32(e.Action))
+ if e.Flags[nl.SEG6_LOCAL_SRH] {
+ srh, err := nl.EncodeSEG6Srh(e.Segments)
+ if err != nil {
+ return nil, err
+ }
+ attr := make([]byte, 4)
+ native.PutUint16(attr, uint16(len(srh)+4))
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_SRH)
+ attr = append(attr, srh...)
+ res = append(res, attr...)
+ }
+ if e.Flags[nl.SEG6_LOCAL_TABLE] {
+ attr := make([]byte, 8)
+ native.PutUint16(attr, 8)
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_TABLE)
+ native.PutUint32(attr[4:], uint32(e.Table))
+ res = append(res, attr...)
+ }
+ if e.Flags[nl.SEG6_LOCAL_NH4] {
+ attr := make([]byte, 4)
+ native.PutUint16(attr, 8)
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH4)
+ ipv4 := e.InAddr.To4()
+ if ipv4 == nil {
+ err = fmt.Errorf("SEG6_LOCAL_NH4 has invalid IPv4 address")
+ return nil, err
+ }
+ attr = append(attr, ipv4...)
+ res = append(res, attr...)
+ }
+ if e.Flags[nl.SEG6_LOCAL_NH6] {
+ attr := make([]byte, 4)
+ native.PutUint16(attr, 20)
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH6)
+ attr = append(attr, e.In6Addr...)
+ res = append(res, attr...)
+ }
+ if e.Flags[nl.SEG6_LOCAL_IIF] {
+ attr := make([]byte, 8)
+ native.PutUint16(attr, 8)
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_IIF)
+ native.PutUint32(attr[4:], uint32(e.Iif))
+ res = append(res, attr...)
+ }
+ if e.Flags[nl.SEG6_LOCAL_OIF] {
+ attr := make([]byte, 8)
+ native.PutUint16(attr, 8)
+ native.PutUint16(attr[2:], nl.SEG6_LOCAL_OIF)
+ native.PutUint32(attr[4:], uint32(e.Oif))
+ res = append(res, attr...)
+ }
+ return res, err
+}
+func (e *SEG6LocalEncap) String() string {
+ strs := make([]string, 0, nl.SEG6_LOCAL_MAX)
+ strs = append(strs, fmt.Sprintf("action %s", nl.SEG6LocalActionString(e.Action)))
+
+ if e.Flags[nl.SEG6_LOCAL_TABLE] {
+ strs = append(strs, fmt.Sprintf("table %d", e.Table))
+ }
+ if e.Flags[nl.SEG6_LOCAL_NH4] {
+ strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr))
+ }
+ if e.Flags[nl.SEG6_LOCAL_NH6] {
+ strs = append(strs, fmt.Sprintf("nh6 %s", e.In6Addr))
+ }
+ if e.Flags[nl.SEG6_LOCAL_IIF] {
+ link, err := LinkByIndex(e.Iif)
+ if err != nil {
+ strs = append(strs, fmt.Sprintf("iif %d", e.Iif))
+ } else {
+ strs = append(strs, fmt.Sprintf("iif %s", link.Attrs().Name))
+ }
+ }
+ if e.Flags[nl.SEG6_LOCAL_OIF] {
+ link, err := LinkByIndex(e.Oif)
+ if err != nil {
+ strs = append(strs, fmt.Sprintf("oif %d", e.Oif))
+ } else {
+ strs = append(strs, fmt.Sprintf("oif %s", link.Attrs().Name))
+ }
+ }
+ if e.Flags[nl.SEG6_LOCAL_SRH] {
+ 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]))
+ }
+ strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
+ }
+ return strings.Join(strs, " ")
+}
+func (e *SEG6LocalEncap) Equal(x Encap) bool {
+ o, ok := x.(*SEG6LocalEncap)
+ if !ok {
+ return false
+ }
+ if e == o {
+ return true
+ }
+ if e == nil || o == nil {
+ return false
+ }
+ // compare all arrays first
+ for i := range e.Flags {
+ if e.Flags[i] != o.Flags[i] {
+ 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
+ }
+ }
+ // compare values
+ if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
+ return false
+ }
+ if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif {
+ return false
+ }
+ return true
+}
+
// RouteAdd will add a route to the system.
// Equivalent to: `ip route add $route`
func RouteAdd(route *Route) error {
@@ -335,18 +519,18 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil {
return err
}
- rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf))
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf))
}
if route.Encap != nil {
buf := make([]byte, 2)
native.PutUint16(buf, uint16(route.Encap.Type()))
- rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := route.Encap.Encode()
if err != nil {
return err
}
- rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf))
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
}
if route.Src != nil {
@@ -410,17 +594,17 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil {
return err
}
- children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf))
+ children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf))
}
if nh.Encap != nil {
buf := make([]byte, 2)
native.PutUint16(buf, uint16(nh.Encap.Type()))
- rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
+ children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
buf, err := nh.Encap.Encode()
if err != nil {
return err
}
- children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf))
+ children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
}
rtnh.Children = children
buf = append(buf, rtnh.Serialize()...)
@@ -464,6 +648,10 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
b := nl.Uint32Attr(uint32(route.AdvMSS))
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
}
+ if route.Hoplimit > 0 {
+ b := nl.Uint32Attr(uint32(route.Hoplimit))
+ metrics = append(metrics, nl.NewRtAttr(unix.RTAX_HOPLIMIT, b))
+ }
if metrics != nil {
attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
@@ -574,6 +762,8 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
continue
}
}
+ case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
+ continue
}
}
res = append(res, route)
@@ -649,7 +839,7 @@ func deserializeRoute(m []byte) (Route, error) {
switch attr.Attr.Type {
case unix.RTA_GATEWAY:
info.Gw = net.IP(attr.Value)
- case nl.RTA_NEWDST:
+ case unix.RTA_NEWDST:
var d Destination
switch msg.Family {
case nl.FAMILY_MPLS:
@@ -659,9 +849,9 @@ func deserializeRoute(m []byte) (Route, error) {
return nil, nil, err
}
info.NewDst = d
- case nl.RTA_ENCAP_TYPE:
+ case unix.RTA_ENCAP_TYPE:
encapType = attr
- case nl.RTA_ENCAP:
+ case unix.RTA_ENCAP:
encap = attr
}
}
@@ -690,7 +880,7 @@ func deserializeRoute(m []byte) (Route, error) {
route.MultiPath = append(route.MultiPath, info)
rest = buf
}
- case nl.RTA_NEWDST:
+ case unix.RTA_NEWDST:
var d Destination
switch msg.Family {
case nl.FAMILY_MPLS:
@@ -700,9 +890,9 @@ func deserializeRoute(m []byte) (Route, error) {
return route, err
}
route.NewDst = d
- case nl.RTA_ENCAP_TYPE:
+ case unix.RTA_ENCAP_TYPE:
encapType = attr
- case nl.RTA_ENCAP:
+ case unix.RTA_ENCAP:
encap = attr
case unix.RTA_METRICS:
metrics, err := nl.ParseRouteAttr(attr.Value)
@@ -715,6 +905,8 @@ func deserializeRoute(m []byte) (Route, error) {
route.MTU = int(native.Uint32(metric.Value[0:4]))
case unix.RTAX_ADVMSS:
route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
+ case unix.RTAX_HOPLIMIT:
+ route.Hoplimit = int(native.Uint32(metric.Value[0:4]))
}
}
}
@@ -734,6 +926,11 @@ func deserializeRoute(m []byte) (Route, error) {
if err := e.Decode(encap.Value); err != nil {
return route, err
}
+ case nl.LWTUNNEL_ENCAP_SEG6_LOCAL:
+ e = &SEG6LocalEncap{}
+ if err := e.Decode(encap.Value); err != nil {
+ return route, err
+ }
}
route.Encap = e
}
@@ -840,13 +1037,19 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
go func() {
defer close(ch)
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
cberr(err)
}
return
}
+ if from.Pid != nl.PidKernel {
+ if cberr != nil {
+ cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
+ }
+ continue
+ }
for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE {
continue
diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go
index 6238ae458..e12569fe4 100644
--- a/vendor/github.com/vishvananda/netlink/rule_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rule_linux.go
@@ -144,7 +144,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
}
if rule.Goto >= 0 {
- msg.Type = nl.FR_ACT_NOP
+ msg.Type = nl.FR_ACT_GOTO
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Goto))
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index 99e9fb4d8..c4d89c17e 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -141,10 +141,13 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
},
})
s.Send(req)
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
return nil, err
}
+ if from.Pid != nl.PidKernel {
+ return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ }
if len(msgs) == 0 {
return nil, errors.New("no message nor error from netlink")
}
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
index efe72ddf2..985d3a915 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
@@ -54,11 +54,15 @@ func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error
go func() {
defer close(ch)
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
errorChan <- err
return
}
+ if from.Pid != nl.PidKernel {
+ errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ return
+ }
for _, m := range msgs {
switch m.Header.Type {
case nl.XFRM_MSG_EXPIRE:
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
index c97ec43a2..6219d2772 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
@@ -35,6 +35,25 @@ func (d Dir) String() string {
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
}
+// PolicyAction is an enum representing an ipsec policy action.
+type PolicyAction uint8
+
+const (
+ XFRM_POLICY_ALLOW PolicyAction = 0
+ XFRM_POLICY_BLOCK PolicyAction = 1
+)
+
+func (a PolicyAction) String() string {
+ switch a {
+ case XFRM_POLICY_ALLOW:
+ return "allow"
+ case XFRM_POLICY_BLOCK:
+ return "block"
+ default:
+ return fmt.Sprintf("action %d", a)
+ }
+}
+
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
// policy. These rules are matched with XfrmState to determine encryption
// and authentication algorithms.
@@ -64,11 +83,14 @@ type XfrmPolicy struct {
Dir Dir
Priority int
Index int
+ Action PolicyAction
+ Ifindex int
+ Ifid int
Mark *XfrmMark
Tmpls []XfrmPolicyTmpl
}
func (p XfrmPolicy) String() string {
- return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Mark: %s, Tmpls: %s}",
- p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Mark, p.Tmpls)
+ return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}",
+ p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls)
}
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
index fde0c2ca5..a4e132ef5 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
@@ -27,6 +27,7 @@ func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
if sel.Sport != 0 {
sel.SportMask = ^uint16(0)
}
+ sel.Ifindex = int32(policy.Ifindex)
}
// XfrmPolicyAdd will add an xfrm policy to the system.
@@ -61,6 +62,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
msg.Priority = uint32(policy.Priority)
msg.Index = uint32(policy.Index)
msg.Dir = uint8(policy.Dir)
+ msg.Action = uint8(policy.Action)
msg.Lft.SoftByteLimit = nl.XFRM_INF
msg.Lft.HardByteLimit = nl.XFRM_INF
msg.Lft.SoftPacketLimit = nl.XFRM_INF
@@ -90,6 +92,9 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
req.AddData(out)
}
+ ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
+ req.AddData(ifId)
+
_, err := req.Execute(unix.NETLINK_XFRM, 0)
return err
}
@@ -183,6 +188,9 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
req.AddData(out)
}
+ ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
+ req.AddData(ifId)
+
resType := nl.XFRM_MSG_NEWPOLICY
if nlProto == nl.XFRM_MSG_DELPOLICY {
resType = 0
@@ -197,12 +205,7 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
return nil, err
}
- p, err := parseXfrmPolicy(msgs[0], FAMILY_ALL)
- if err != nil {
- return nil, err
- }
-
- return p, nil
+ return parseXfrmPolicy(msgs[0], FAMILY_ALL)
}
func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
@@ -220,9 +223,11 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
policy.Proto = Proto(msg.Sel.Proto)
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
+ policy.Ifindex = int(msg.Sel.Ifindex)
policy.Priority = int(msg.Priority)
policy.Index = int(msg.Index)
policy.Dir = Dir(msg.Dir)
+ policy.Action = PolicyAction(msg.Action)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
@@ -249,6 +254,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
policy.Mark = new(XfrmMark)
policy.Mark.Value = mark.Value
policy.Mark.Mask = mark.Mask
+ case nl.XFRMA_IF_ID:
+ policy.Ifid = int(native.Uint32(attr.Value))
}
}
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go
index d14740dc5..483d8934a 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state.go
@@ -94,6 +94,8 @@ type XfrmState struct {
Limits XfrmStateLimits
Statistics XfrmStateStats
Mark *XfrmMark
+ OutputMark int
+ Ifid int
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
Aead *XfrmStateAlgo
@@ -102,8 +104,8 @@ type XfrmState struct {
}
func (sa XfrmState) String() string {
- return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
- sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
+ return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
+ sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
}
func (sa XfrmState) Print(stats bool) string {
if !stats {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
index 5dfdb33e4..66c99423c 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -158,6 +158,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
req.AddData(out)
}
+ if state.OutputMark != 0 {
+ out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark)))
+ req.AddData(out)
+ }
+
+ ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
+ req.AddData(ifId)
_, err := req.Execute(unix.NETLINK_XFRM, 0)
return err
@@ -184,12 +191,7 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
return nil, err
}
- s, err := parseXfrmState(msgs[0], FAMILY_ALL)
- if err != nil {
- return nil, err
- }
-
- return s, err
+ return parseXfrmState(msgs[0], FAMILY_ALL)
}
// XfrmStateDel will delete an xfrm state from the system. Note that
@@ -275,6 +277,9 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
req.AddData(out)
}
+ ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
+ req.AddData(ifId)
+
resType := nl.XFRM_MSG_NEWSA
if nlProto == nl.XFRM_MSG_DELSA {
resType = 0
@@ -372,6 +377,10 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
state.Mark = new(XfrmMark)
state.Mark.Value = mark.Value
state.Mark.Mask = mark.Mask
+ case nl.XFRMA_OUTPUT_MARK:
+ state.OutputMark = int(native.Uint32(attr.Value))
+ case nl.XFRMA_IF_ID:
+ state.Ifid = int(native.Uint32(attr.Value))
}
}
@@ -394,11 +403,7 @@ func (h *Handle) XfrmStateFlush(proto Proto) error {
req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
_, err := req.Execute(unix.NETLINK_XFRM, 0)
- if err != nil {
- return err
- }
-
- return nil
+ return err
}
func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
diff --git a/vendor/github.com/vishvananda/netns/go.mod b/vendor/github.com/vishvananda/netns/go.mod
new file mode 100644
index 000000000..8221f782c
--- /dev/null
+++ b/vendor/github.com/vishvananda/netns/go.mod
@@ -0,0 +1,3 @@
+module github.com/vishvananda/netns
+
+go 1.12
diff --git a/vendor/github.com/vishvananda/netns/go.sum b/vendor/github.com/vishvananda/netns/go.sum
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/github.com/vishvananda/netns/go.sum
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 8fa756fbb..a8bdf14a3 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -516,10 +516,10 @@ github.com/vbauerster/mpb/v4
github.com/vbauerster/mpb/v4/cwriter
github.com/vbauerster/mpb/v4/decor
github.com/vbauerster/mpb/v4/internal
-# github.com/vishvananda/netlink v1.0.0
+# github.com/vishvananda/netlink v1.1.0
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl
-# github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f
+# github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
github.com/vishvananda/netns
# github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b
github.com/xeipuuv/gojsonpointer