vendor folder bump.
This commit is contained in:
parent
18874aac7d
commit
dc536993e2
26
Godeps/Godeps.json
generated
26
Godeps/Godeps.json
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/plugins",
|
"ImportPath": "github.com/containernetworking/plugins",
|
||||||
"GoVersion": "go1.7",
|
"GoVersion": "go1.7",
|
||||||
"GodepVersion": "v79",
|
"GodepVersion": "v80",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
@ -318,39 +318,45 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vishvananda/netlink",
|
"ImportPath": "github.com/vishvananda/netlink",
|
||||||
"Rev": "6e453822d85ef5721799774b654d4d02fed62afb"
|
"Comment": "v1.0.0-40-g023a6da",
|
||||||
|
"Rev": "023a6dafdcdfa7068ac83b260ab7f03cd4131aca"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vishvananda/netlink/nl",
|
"ImportPath": "github.com/vishvananda/netlink/nl",
|
||||||
"Rev": "6e453822d85ef5721799774b654d4d02fed62afb"
|
"Comment": "v1.0.0-40-g023a6da",
|
||||||
|
"Rev": "023a6dafdcdfa7068ac83b260ab7f03cd4131aca"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vishvananda/netns",
|
"ImportPath": "github.com/vishvananda/netns",
|
||||||
"Rev": "54f0e4339ce73702a0607f49922aaa1e749b418d"
|
"Rev": "13995c7128ccc8e51e9a6bd2b551020a27180abd"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
||||||
"Rev": "94eea52f7b742c7cbe0b03b22f0c4c8631ece122"
|
"Rev": "7c1a557ab941a71c619514f229f0b27ccb0c27cf"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/bpf",
|
"ImportPath": "golang.org/x/net/bpf",
|
||||||
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
"Rev": "49bb7cea24b1df9410e1712aa6433dae904ff66a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/internal/iana",
|
"ImportPath": "golang.org/x/net/internal/iana",
|
||||||
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
"Rev": "49bb7cea24b1df9410e1712aa6433dae904ff66a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/ipv4",
|
"ImportPath": "golang.org/x/net/ipv4",
|
||||||
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
"Rev": "49bb7cea24b1df9410e1712aa6433dae904ff66a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
"ImportPath": "golang.org/x/sys/unix",
|
||||||
"Rev": "d5840adf789d732bc8b00f37b26ca956a7cc8e79"
|
"Rev": "66b7b1311ac80bbafcd2daeef9a5e6e2cd1e2399"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/sys/windows",
|
"ImportPath": "golang.org/x/sys/windows",
|
||||||
"Rev": "d5840adf789d732bc8b00f37b26ca956a7cc8e79"
|
"Rev": "66b7b1311ac80bbafcd2daeef9a5e6e2cd1e2399"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/internal/socket",
|
||||||
|
"Rev": "49bb7cea24b1df9410e1712aa6433dae904ff66a"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
4
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
@ -1,4 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
|
go:
|
||||||
|
- "1.10.x"
|
||||||
|
- "1.11.x"
|
||||||
before_script:
|
before_script:
|
||||||
# make sure we keep path in tact when we sudo
|
# make sure we keep path in tact when we sudo
|
||||||
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
||||||
@ -9,5 +12,6 @@ before_script:
|
|||||||
- sudo modprobe nf_conntrack_netlink
|
- sudo modprobe nf_conntrack_netlink
|
||||||
- sudo modprobe nf_conntrack_ipv4
|
- sudo modprobe nf_conntrack_ipv4
|
||||||
- sudo modprobe nf_conntrack_ipv6
|
- sudo modprobe nf_conntrack_ipv6
|
||||||
|
- sudo modprobe sch_hfsc
|
||||||
install:
|
install:
|
||||||
- go get github.com/vishvananda/netns
|
- go get github.com/vishvananda/netns
|
||||||
|
5
vendor/github.com/vishvananda/netlink/CHANGELOG.md
generated
vendored
Normal file
5
vendor/github.com/vishvananda/netlink/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.0 (2018-03-15)
|
||||||
|
|
||||||
|
Initial release tagging
|
5
vendor/github.com/vishvananda/netlink/Makefile
generated
vendored
5
vendor/github.com/vishvananda/netlink/Makefile
generated
vendored
@ -3,7 +3,8 @@ DIRS := \
|
|||||||
nl
|
nl
|
||||||
|
|
||||||
DEPS = \
|
DEPS = \
|
||||||
github.com/vishvananda/netns
|
github.com/vishvananda/netns \
|
||||||
|
golang.org/x/sys/unix
|
||||||
|
|
||||||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||||
testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go))))
|
testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go))))
|
||||||
@ -18,7 +19,7 @@ $(call goroot,$(DEPS)):
|
|||||||
|
|
||||||
.PHONY: $(call testdirs,$(DIRS))
|
.PHONY: $(call testdirs,$(DIRS))
|
||||||
$(call testdirs,$(DIRS)):
|
$(call testdirs,$(DIRS)):
|
||||||
sudo -E go test -test.parallel 4 -timeout 60s -v github.com/vishvananda/netlink/$@
|
go test -test.exec sudo -test.parallel 4 -timeout 60s -test.v github.com/vishvananda/netlink/$@
|
||||||
|
|
||||||
$(call fmt,$(call testdirs,$(DIRS))):
|
$(call fmt,$(call testdirs,$(DIRS))):
|
||||||
! gofmt -l $(subst fmt-,,$@)/*.go | grep -q .
|
! gofmt -l $(subst fmt-,,$@)/*.go | grep -q .
|
||||||
|
11
vendor/github.com/vishvananda/netlink/README.md
generated
vendored
11
vendor/github.com/vishvananda/netlink/README.md
generated
vendored
@ -38,15 +38,18 @@ Add a new bridge and add eth1 into it:
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"fmt"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
la := netlink.NewLinkAttrs()
|
la := netlink.NewLinkAttrs()
|
||||||
la.Name = "foo"
|
la.Name = "foo"
|
||||||
mybridge := &netlink.Bridge{la}}
|
mybridge := &netlink.Bridge{LinkAttrs: la}
|
||||||
_ := netlink.LinkAdd(mybridge)
|
err := netlink.LinkAdd(mybridge)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("could not add %s: %v\n", la.Name, err)
|
||||||
|
}
|
||||||
eth1, _ := netlink.LinkByName("eth1")
|
eth1, _ := netlink.LinkByName("eth1")
|
||||||
netlink.LinkSetMaster(eth1, mybridge)
|
netlink.LinkSetMaster(eth1, mybridge)
|
||||||
}
|
}
|
||||||
@ -63,7 +66,6 @@ Add a new ip address to loopback:
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -87,3 +89,4 @@ There are also a few pieces of low level netlink functionality that still
|
|||||||
need to be implemented. Routing rules are not in place and some of the
|
need to be implemented. Routing rules are not in place and some of the
|
||||||
more advanced link types. Hopefully there is decent structure and testing
|
more advanced link types. Hopefully there is decent structure and testing
|
||||||
in place to make these fairly straightforward to add.
|
in place to make these fairly straightforward to add.
|
||||||
|
|
||||||
|
156
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
156
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@ -2,13 +2,13 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IFA_FLAGS is a u32 attribute.
|
// IFA_FLAGS is a u32 attribute.
|
||||||
@ -23,7 +23,7 @@ func AddrAdd(link Link, addr *Addr) error {
|
|||||||
// AddrAdd will add an IP address to a link device.
|
// AddrAdd will add an IP address to a link device.
|
||||||
// Equivalent to: `ip addr add $addr dev $link`
|
// Equivalent to: `ip addr add $addr dev $link`
|
||||||
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
|
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ func AddrReplace(link Link, addr *Addr) error {
|
|||||||
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
||||||
// Equivalent to: `ip addr replace $addr dev $link`
|
// Equivalent to: `ip addr replace $addr dev $link`
|
||||||
func (h *Handle) AddrReplace(link Link, addr *Addr) error {
|
func (h *Handle) AddrReplace(link Link, addr *Addr) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func AddrDel(link Link, addr *Addr) error {
|
|||||||
// AddrDel will delete an IP address from a link device.
|
// AddrDel will delete an IP address from a link device.
|
||||||
// Equivalent to: `ip addr del $addr dev $link`
|
// Equivalent to: `ip addr del $addr dev $link`
|
||||||
func (h *Handle) AddrDel(link Link, addr *Addr) error {
|
func (h *Handle) AddrDel(link Link, addr *Addr) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
msg := nl.NewIfAddrmsg(family)
|
msg := nl.NewIfAddrmsg(family)
|
||||||
msg.Index = uint32(base.Index)
|
msg.Index = uint32(base.Index)
|
||||||
msg.Scope = uint8(addr.Scope)
|
msg.Scope = uint8(addr.Scope)
|
||||||
prefixlen, _ := addr.Mask.Size()
|
mask := addr.Mask
|
||||||
|
if addr.Peer != nil {
|
||||||
|
mask = addr.Peer.Mask
|
||||||
|
}
|
||||||
|
prefixlen, masklen := mask.Size()
|
||||||
msg.Prefixlen = uint8(prefixlen)
|
msg.Prefixlen = uint8(prefixlen)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
@ -76,7 +80,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
localAddrData = addr.IP.To16()
|
localAddrData = addr.IP.To16()
|
||||||
}
|
}
|
||||||
|
|
||||||
localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
|
localData := nl.NewRtAttr(unix.IFA_LOCAL, localAddrData)
|
||||||
req.AddData(localData)
|
req.AddData(localData)
|
||||||
var peerAddrData []byte
|
var peerAddrData []byte
|
||||||
if addr.Peer != nil {
|
if addr.Peer != nil {
|
||||||
@ -89,7 +93,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
peerAddrData = localAddrData
|
peerAddrData = localAddrData
|
||||||
}
|
}
|
||||||
|
|
||||||
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
|
addressData := nl.NewRtAttr(unix.IFA_ADDRESS, peerAddrData)
|
||||||
req.AddData(addressData)
|
req.AddData(addressData)
|
||||||
|
|
||||||
if addr.Flags != 0 {
|
if addr.Flags != 0 {
|
||||||
@ -103,16 +107,34 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr.Broadcast != nil {
|
if family == FAMILY_V4 {
|
||||||
req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
|
if addr.Broadcast == nil {
|
||||||
|
calcBroadcast := make(net.IP, masklen/8)
|
||||||
|
for i := range localAddrData {
|
||||||
|
calcBroadcast[i] = localAddrData[i] | ^mask[i]
|
||||||
|
}
|
||||||
|
addr.Broadcast = calcBroadcast
|
||||||
|
}
|
||||||
|
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
|
||||||
|
|
||||||
|
if addr.Label != "" {
|
||||||
|
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
||||||
|
req.AddData(labelData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr.Label != "" {
|
// 0 is the default value for these attributes. However, 0 means "expired", while the least-surprising default
|
||||||
labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
// value should be "forever". To compensate for that, only add the attributes if at least one of the values is
|
||||||
req.AddData(labelData)
|
// non-zero, which means the caller has explicitly set them
|
||||||
|
if addr.ValidLft > 0 || addr.PreferedLft > 0 {
|
||||||
|
cachedata := nl.IfaCacheInfo{
|
||||||
|
IfaValid: uint32(addr.ValidLft),
|
||||||
|
IfaPrefered: uint32(addr.PreferedLft),
|
||||||
|
}
|
||||||
|
req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +149,11 @@ func AddrList(link Link, family int) ([]Addr, error) {
|
|||||||
// Equivalent to: `ip addr show`.
|
// Equivalent to: `ip addr show`.
|
||||||
// The list can be filtered by link and ip family.
|
// The list can be filtered by link and ip family.
|
||||||
func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
|
func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP)
|
||||||
msg := nl.NewIfInfomsg(family)
|
msg := nl.NewIfInfomsg(family)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -183,21 +205,25 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
|
|||||||
var local, dst *net.IPNet
|
var local, dst *net.IPNet
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case syscall.IFA_ADDRESS:
|
case unix.IFA_ADDRESS:
|
||||||
dst = &net.IPNet{
|
dst = &net.IPNet{
|
||||||
IP: attr.Value,
|
IP: attr.Value,
|
||||||
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
||||||
}
|
}
|
||||||
addr.Peer = dst
|
case unix.IFA_LOCAL:
|
||||||
case syscall.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{
|
local = &net.IPNet{
|
||||||
IP: attr.Value,
|
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:
|
||||||
case syscall.IFA_BROADCAST:
|
|
||||||
addr.Broadcast = attr.Value
|
addr.Broadcast = attr.Value
|
||||||
case syscall.IFA_LABEL:
|
case unix.IFA_LABEL:
|
||||||
addr.Label = string(attr.Value[:len(attr.Value)-1])
|
addr.Label = string(attr.Value[:len(attr.Value)-1])
|
||||||
case IFA_FLAGS:
|
case IFA_FLAGS:
|
||||||
addr.Flags = int(native.Uint32(attr.Value[0:4]))
|
addr.Flags = int(native.Uint32(attr.Value[0:4]))
|
||||||
@ -208,12 +234,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 {
|
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 {
|
} else {
|
||||||
addr.IPNet = dst
|
addr.IPNet = dst
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.Scope = int(msg.Scope)
|
addr.Scope = int(msg.Scope)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -232,17 +270,36 @@ type AddrUpdate struct {
|
|||||||
// AddrSubscribe takes a chan down which notifications will be sent
|
// AddrSubscribe takes a chan down which notifications will be sent
|
||||||
// when addresses change. Close the 'done' chan to stop subscription.
|
// when addresses change. Close the 'done' chan to stop subscription.
|
||||||
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||||
return addrSubscribe(netns.None(), netns.None(), ch, done)
|
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
|
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
|
||||||
// to choose the network namespace in which to subscribe (ns).
|
// to choose the network namespace in which to subscribe (ns).
|
||||||
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||||
return addrSubscribe(ns, netns.None(), ch, done)
|
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
// AddrSubscribeOptions contains a set of options to use with
|
||||||
s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
|
// AddrSubscribeWithOptions.
|
||||||
|
type AddrSubscribeOptions struct {
|
||||||
|
Namespace *netns.NsHandle
|
||||||
|
ErrorCallback func(error)
|
||||||
|
ListExisting bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
|
||||||
|
// provide additional options to modify the behavior. Currently, the
|
||||||
|
// namespace can be provided as well as an error callback.
|
||||||
|
func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, options AddrSubscribeOptions) error {
|
||||||
|
if options.Namespace == nil {
|
||||||
|
none := netns.None()
|
||||||
|
options.Namespace = &none
|
||||||
|
}
|
||||||
|
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||||
|
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -252,30 +309,59 @@ func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-cha
|
|||||||
s.Close()
|
s.Close()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if listExisting {
|
||||||
|
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
|
||||||
|
unix.NLM_F_DUMP)
|
||||||
|
infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
|
req.AddData(infmsg)
|
||||||
|
if err := s.Send(req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("netlink.AddrSubscribe: Receive() error: %v", err)
|
if cberr != nil {
|
||||||
|
cberr(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
msgType := m.Header.Type
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR {
|
|
||||||
log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
|
native := nl.NativeEndian()
|
||||||
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
|
if error == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(syscall.Errno(-error))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msgType := m.Header.Type
|
||||||
|
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(fmt.Errorf("bad message type: %d", msgType))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
addr, _, ifindex, err := parseAddr(m.Data)
|
addr, _, ifindex, err := parseAddr(m.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("netlink.AddrSubscribe: could not parse address: %v", err)
|
if cberr != nil {
|
||||||
continue
|
cberr(fmt.Errorf("could not parse address: %v", err))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- AddrUpdate{LinkAddress: *addr.IPNet,
|
ch <- AddrUpdate{LinkAddress: *addr.IPNet,
|
||||||
LinkIndex: ifindex,
|
LinkIndex: ifindex,
|
||||||
NewAddr: msgType == syscall.RTM_NEWADDR,
|
NewAddr: msgType == unix.RTM_NEWADDR,
|
||||||
Flags: addr.Flags,
|
Flags: addr.Flags,
|
||||||
Scope: addr.Scope,
|
Scope: addr.Scope,
|
||||||
PreferedLft: addr.PreferedLft,
|
PreferedLft: addr.PreferedLft,
|
||||||
|
83
vendor/github.com/vishvananda/netlink/bpf_linux.go
generated
vendored
83
vendor/github.com/vishvananda/netlink/bpf_linux.go
generated
vendored
@ -1,49 +1,12 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
/*
|
import (
|
||||||
#include <asm/types.h>
|
"unsafe"
|
||||||
#include <asm/unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static int load_simple_bpf(int prog_type, int ret) {
|
"golang.org/x/sys/unix"
|
||||||
#ifdef __NR_bpf
|
)
|
||||||
// { return ret; }
|
|
||||||
__u64 __attribute__((aligned(8))) insns[] = {
|
|
||||||
0x00000000000000b7ull | ((__u64)ret<<32),
|
|
||||||
0x0000000000000095ull,
|
|
||||||
};
|
|
||||||
__u8 __attribute__((aligned(8))) license[] = "ASL2";
|
|
||||||
// Copied from a header file since libc is notoriously slow to update.
|
|
||||||
// The call will succeed or fail and that will be our indication on
|
|
||||||
// whether or not it is supported.
|
|
||||||
struct {
|
|
||||||
__u32 prog_type;
|
|
||||||
__u32 insn_cnt;
|
|
||||||
__u64 insns;
|
|
||||||
__u64 license;
|
|
||||||
__u32 log_level;
|
|
||||||
__u32 log_size;
|
|
||||||
__u64 log_buf;
|
|
||||||
__u32 kern_version;
|
|
||||||
} __attribute__((aligned(8))) attr = {
|
|
||||||
.prog_type = prog_type,
|
|
||||||
.insn_cnt = 2,
|
|
||||||
.insns = (uintptr_t)&insns,
|
|
||||||
.license = (uintptr_t)&license,
|
|
||||||
};
|
|
||||||
return syscall(__NR_bpf, 5, &attr, sizeof(attr));
|
|
||||||
#else
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type BpfProgType C.int
|
type BpfProgType uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BPF_PROG_TYPE_UNSPEC BpfProgType = iota
|
BPF_PROG_TYPE_UNSPEC BpfProgType = iota
|
||||||
@ -55,8 +18,36 @@ const (
|
|||||||
BPF_PROG_TYPE_XDP
|
BPF_PROG_TYPE_XDP
|
||||||
)
|
)
|
||||||
|
|
||||||
// loadSimpleBpf loads a trivial bpf program for testing purposes
|
type BPFAttr struct {
|
||||||
func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
|
ProgType uint32
|
||||||
fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
|
InsnCnt uint32
|
||||||
return int(fd), err
|
Insns uintptr
|
||||||
|
License uintptr
|
||||||
|
LogLevel uint32
|
||||||
|
LogSize uint32
|
||||||
|
LogBuf uintptr
|
||||||
|
KernVersion uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadSimpleBpf loads a trivial bpf program for testing purposes.
|
||||||
|
func loadSimpleBpf(progType BpfProgType, ret uint32) (int, error) {
|
||||||
|
insns := []uint64{
|
||||||
|
0x00000000000000b7 | (uint64(ret) << 32),
|
||||||
|
0x0000000000000095,
|
||||||
|
}
|
||||||
|
license := []byte{'A', 'S', 'L', '2', '\x00'}
|
||||||
|
attr := BPFAttr{
|
||||||
|
ProgType: uint32(progType),
|
||||||
|
InsnCnt: uint32(len(insns)),
|
||||||
|
Insns: uintptr(unsafe.Pointer(&insns[0])),
|
||||||
|
License: uintptr(unsafe.Pointer(&license[0])),
|
||||||
|
}
|
||||||
|
fd, _, errno := unix.Syscall(unix.SYS_BPF,
|
||||||
|
5, /* bpf cmd */
|
||||||
|
uintptr(unsafe.Pointer(&attr)),
|
||||||
|
unsafe.Sizeof(attr))
|
||||||
|
if errno != 0 {
|
||||||
|
return 0, errno
|
||||||
|
}
|
||||||
|
return int(fd), nil
|
||||||
}
|
}
|
||||||
|
28
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
28
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
@ -2,9 +2,9 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
||||||
@ -16,12 +16,12 @@ func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
|||||||
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
||||||
// Equivalent to: `bridge vlan show`
|
// Equivalent to: `bridge vlan show`
|
||||||
func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
|
||||||
msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
req.AddData(nl.NewRtAttr(nl.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
|
req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWLINK)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
|||||||
}
|
}
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case nl.IFLA_AF_SPEC:
|
case unix.IFLA_AF_SPEC:
|
||||||
//nested attr
|
//nested attr
|
||||||
nestAttrs, err := nl.ParseRouteAttr(attr.Value)
|
nestAttrs, err := nl.ParseRouteAttr(attr.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,7 +63,7 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
|
|||||||
// BridgeVlanAdd adds a new vlan filter entry
|
// BridgeVlanAdd adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||||
func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
return h.bridgeVlanModify(syscall.RTM_SETLINK, link, vid, pvid, untagged, self, master)
|
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BridgeVlanDel adds a new vlan filter entry
|
// BridgeVlanDel adds a new vlan filter entry
|
||||||
@ -75,19 +75,19 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
|
|||||||
// BridgeVlanDel adds a new vlan filter entry
|
// BridgeVlanDel adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||||
func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
return h.bridgeVlanModify(syscall.RTM_DELLINK, link, vid, pvid, untagged, self, master)
|
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
base := link.Attrs()
|
base := link.Attrs()
|
||||||
h.ensureIndex(base)
|
h.ensureIndex(base)
|
||||||
req := h.newNetlinkRequest(cmd, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
||||||
msg.Index = int32(base.Index)
|
msg.Index = int32(base.Index)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
br := nl.NewRtAttr(nl.IFLA_AF_SPEC, nil)
|
br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
|
||||||
var flags uint16
|
var flags uint16
|
||||||
if self {
|
if self {
|
||||||
flags |= nl.BRIDGE_FLAGS_SELF
|
flags |= nl.BRIDGE_FLAGS_SELF
|
||||||
@ -96,7 +96,7 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
|||||||
flags |= nl.BRIDGE_FLAGS_MASTER
|
flags |= nl.BRIDGE_FLAGS_MASTER
|
||||||
}
|
}
|
||||||
if flags > 0 {
|
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}
|
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
||||||
if pvid {
|
if pvid {
|
||||||
@ -105,9 +105,9 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
|||||||
if untagged {
|
if untagged {
|
||||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_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)
|
req.AddData(br)
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
141
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
141
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
@ -4,25 +4,76 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Class interfaces for all classes
|
||||||
type Class interface {
|
type Class interface {
|
||||||
Attrs() *ClassAttrs
|
Attrs() *ClassAttrs
|
||||||
Type() string
|
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 representaion based on generic networking statisticsfor 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,
|
// 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
|
// has a handle and a parent. The root filter of a device should have a
|
||||||
// parent == HANDLE_ROOT.
|
// parent == HANDLE_ROOT.
|
||||||
type ClassAttrs struct {
|
type ClassAttrs struct {
|
||||||
LinkIndex int
|
LinkIndex int
|
||||||
Handle uint32
|
Handle uint32
|
||||||
Parent uint32
|
Parent uint32
|
||||||
Leaf uint32
|
Leaf uint32
|
||||||
|
Statistics *ClassStatistics
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q ClassAttrs) String() string {
|
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)
|
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 {
|
type HtbClassAttrs struct {
|
||||||
// TODO handle all attributes
|
// TODO handle all attributes
|
||||||
Rate uint64
|
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)
|
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 {
|
func (q *HtbClass) Attrs() *ClassAttrs {
|
||||||
return &q.ClassAttrs
|
return &q.ClassAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type return the class type
|
||||||
func (q *HtbClass) Type() string {
|
func (q *HtbClass) Type() string {
|
||||||
return "htb"
|
return "htb"
|
||||||
}
|
}
|
||||||
@ -69,10 +122,90 @@ type GenericClass struct {
|
|||||||
ClassType string
|
ClassType string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attrs return the class attributes
|
||||||
func (class *GenericClass) Attrs() *ClassAttrs {
|
func (class *GenericClass) Attrs() *ClassAttrs {
|
||||||
return &class.ClassAttrs
|
return &class.ClassAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type retrun the class type
|
||||||
func (class *GenericClass) Type() string {
|
func (class *GenericClass) Type() string {
|
||||||
return class.ClassType
|
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 implemtens 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"
|
||||||
|
}
|
||||||
|
170
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
170
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
@ -1,13 +1,34 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: function is in here because it uses other linux functions
|
// 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 {
|
func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
|
||||||
mtu := 1600
|
mtu := 1600
|
||||||
rate := cattrs.Rate / 8
|
rate := cattrs.Rate / 8
|
||||||
@ -50,7 +71,7 @@ func ClassDel(class Class) error {
|
|||||||
// ClassDel will delete a class from the system.
|
// ClassDel will delete a class from the system.
|
||||||
// Equivalent to: `tc class del $class`
|
// Equivalent to: `tc class del $class`
|
||||||
func (h *Handle) ClassDel(class Class) error {
|
func (h *Handle) ClassDel(class Class) error {
|
||||||
return h.classModify(syscall.RTM_DELTCLASS, 0, class)
|
return h.classModify(unix.RTM_DELTCLASS, 0, class)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClassChange will change a class in place
|
// ClassChange will change a class in place
|
||||||
@ -64,7 +85,7 @@ func ClassChange(class Class) error {
|
|||||||
// Equivalent to: `tc class change $class`
|
// Equivalent to: `tc class change $class`
|
||||||
// The parent and handle MUST NOT be changed.
|
// The parent and handle MUST NOT be changed.
|
||||||
func (h *Handle) ClassChange(class Class) error {
|
func (h *Handle) ClassChange(class Class) error {
|
||||||
return h.classModify(syscall.RTM_NEWTCLASS, 0, class)
|
return h.classModify(unix.RTM_NEWTCLASS, 0, class)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClassReplace will replace a class to the system.
|
// ClassReplace will replace a class to the system.
|
||||||
@ -82,7 +103,7 @@ func ClassReplace(class Class) error {
|
|||||||
// If a class already exist with this parent/handle pair, the class is changed.
|
// If a class already exist with this parent/handle pair, the class is changed.
|
||||||
// If a class does not already exist with this parent/handle, a new class is created.
|
// If a class does not already exist with this parent/handle, a new class is created.
|
||||||
func (h *Handle) ClassReplace(class Class) error {
|
func (h *Handle) ClassReplace(class Class) error {
|
||||||
return h.classModify(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE, class)
|
return h.classModify(unix.RTM_NEWTCLASS, unix.NLM_F_CREATE, class)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClassAdd will add a class to the system.
|
// ClassAdd will add a class to the system.
|
||||||
@ -95,14 +116,14 @@ func ClassAdd(class Class) error {
|
|||||||
// Equivalent to: `tc class add $class`
|
// Equivalent to: `tc class add $class`
|
||||||
func (h *Handle) ClassAdd(class Class) error {
|
func (h *Handle) ClassAdd(class Class) error {
|
||||||
return h.classModify(
|
return h.classModify(
|
||||||
syscall.RTM_NEWTCLASS,
|
unix.RTM_NEWTCLASS,
|
||||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
|
unix.NLM_F_CREATE|unix.NLM_F_EXCL,
|
||||||
class,
|
class,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) classModify(cmd, flags int, class Class) error {
|
func (h *Handle) classModify(cmd, flags int, class Class) error {
|
||||||
req := h.newNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
|
||||||
base := class.Attrs()
|
base := class.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
@ -112,12 +133,12 @@ func (h *Handle) classModify(cmd, flags int, class Class) error {
|
|||||||
}
|
}
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
if cmd != syscall.RTM_DELTCLASS {
|
if cmd != unix.RTM_DELTCLASS {
|
||||||
if err := classPayload(req, class); err != nil {
|
if err := classPayload(req, class); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +146,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
|
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
|
||||||
|
|
||||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
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 := nl.TcHtbCopt{}
|
||||||
opt.Buffer = htb.Buffer
|
opt.Buffer = htb.Buffer
|
||||||
opt.Cbuffer = htb.Cbuffer
|
opt.Cbuffer = htb.Cbuffer
|
||||||
@ -141,18 +164,27 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||||||
var rtab [256]uint32
|
var rtab [256]uint32
|
||||||
var ctab [256]uint32
|
var ctab [256]uint32
|
||||||
tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
|
tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
|
||||||
if CalcRtable(&tcrate, rtab, cellLog, uint32(mtu), linklayer) < 0 {
|
if CalcRtable(&tcrate, rtab[:], cellLog, uint32(mtu), linklayer) < 0 {
|
||||||
return errors.New("HTB: failed to calculate rate table")
|
return errors.New("HTB: failed to calculate rate table")
|
||||||
}
|
}
|
||||||
opt.Rate = tcrate
|
opt.Rate = tcrate
|
||||||
tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
|
tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
|
||||||
if CalcRtable(&tcceil, ctab, ccellLog, uint32(mtu), linklayer) < 0 {
|
if CalcRtable(&tcceil, ctab[:], ccellLog, uint32(mtu), linklayer) < 0 {
|
||||||
return errors.New("HTB: failed to calculate ceil rate table")
|
return errors.New("HTB: failed to calculate ceil rate table")
|
||||||
}
|
}
|
||||||
opt.Ceil = tcceil
|
opt.Ceil = tcceil
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
|
options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize())
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab))
|
options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab))
|
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)
|
req.AddData(options)
|
||||||
return nil
|
return nil
|
||||||
@ -169,7 +201,7 @@ func ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
// Equivalent to: `tc class show`.
|
// Equivalent to: `tc class show`.
|
||||||
// Generally returns nothing if link and parent are not specified.
|
// Generally returns nothing if link and parent are not specified.
|
||||||
func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETTCLASS, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP)
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
Parent: parent,
|
Parent: parent,
|
||||||
@ -181,7 +213,7 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
}
|
}
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTCLASS)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -196,9 +228,10 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
base := ClassAttrs{
|
base := ClassAttrs{
|
||||||
LinkIndex: int(msg.Ifindex),
|
LinkIndex: int(msg.Ifindex),
|
||||||
Handle: msg.Handle,
|
Handle: msg.Handle,
|
||||||
Parent: msg.Parent,
|
Parent: msg.Parent,
|
||||||
|
Statistics: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
var class Class
|
var class Class
|
||||||
@ -210,6 +243,8 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
switch classType {
|
switch classType {
|
||||||
case "htb":
|
case "htb":
|
||||||
class = &HtbClass{}
|
class = &HtbClass{}
|
||||||
|
case "hfsc":
|
||||||
|
class = &HfscClass{}
|
||||||
default:
|
default:
|
||||||
class = &GenericClass{ClassType: classType}
|
class = &GenericClass{ClassType: classType}
|
||||||
}
|
}
|
||||||
@ -224,6 +259,26 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,3 +307,78 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro
|
|||||||
}
|
}
|
||||||
return detailed, nil
|
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
|
||||||
|
}
|
||||||
|
128
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
128
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@ -6,9 +6,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConntrackTableType Conntrack table for the netlink operation
|
// ConntrackTableType Conntrack table for the netlink operation
|
||||||
@ -22,7 +22,11 @@ const (
|
|||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
|
||||||
ConntrackExpectTable = 2
|
ConntrackExpectTable = 2
|
||||||
)
|
)
|
||||||
|
const (
|
||||||
|
// For Parsing Mark
|
||||||
|
TCP_PROTO = 6
|
||||||
|
UDP_PROTO = 17
|
||||||
|
)
|
||||||
const (
|
const (
|
||||||
// backward compatibility with golang 1.6 which does not have io.SeekCurrent
|
// backward compatibility with golang 1.6 which does not have io.SeekCurrent
|
||||||
seekCurrent = 1
|
seekCurrent = 1
|
||||||
@ -81,8 +85,8 @@ func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily)
|
|||||||
// conntrack -F [table] Flush table
|
// conntrack -F [table] Flush table
|
||||||
// The flush operation applies to all the family types
|
// The flush operation applies to all the family types
|
||||||
func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||||
req := h.newConntrackRequest(table, syscall.AF_INET, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK)
|
req := h.newConntrackRequest(table, unix.AF_INET, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
|
||||||
_, err := req.Execute(syscall.NETLINK_NETFILTER, 0)
|
_, err := req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,10 +102,10 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
|
|||||||
for _, dataRaw := range res {
|
for _, dataRaw := range res {
|
||||||
flow := parseRawData(dataRaw)
|
flow := parseRawData(dataRaw)
|
||||||
if match := filter.MatchConntrackFlow(flow); match {
|
if match := filter.MatchConntrackFlow(flow); match {
|
||||||
req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, syscall.NLM_F_ACK)
|
req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
|
||||||
// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
|
// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
|
||||||
req2.AddRawData(dataRaw[4:])
|
req2.AddRawData(dataRaw[4:])
|
||||||
req2.Execute(syscall.NETLINK_NETFILTER, 0)
|
req2.Execute(unix.NETLINK_NETFILTER, 0)
|
||||||
matched++
|
matched++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,34 +127,38 @@ func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) {
|
func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) {
|
||||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, syscall.NLM_F_DUMP)
|
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, unix.NLM_F_DUMP)
|
||||||
return req.Execute(syscall.NETLINK_NETFILTER, 0)
|
return req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The full conntrack flow structure is very complicated and can be found in the file:
|
// The full conntrack flow structure is very complicated and can be found in the file:
|
||||||
// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h
|
// 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
|
// For the time being, the structure below allows to parse and extract the base information of a flow
|
||||||
type ipTuple struct {
|
type ipTuple struct {
|
||||||
SrcIP net.IP
|
Bytes uint64
|
||||||
DstIP net.IP
|
DstIP net.IP
|
||||||
Protocol uint8
|
|
||||||
SrcPort uint16
|
|
||||||
DstPort uint16
|
DstPort uint16
|
||||||
|
Packets uint64
|
||||||
|
Protocol uint8
|
||||||
|
SrcIP net.IP
|
||||||
|
SrcPort uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConntrackFlow struct {
|
type ConntrackFlow struct {
|
||||||
FamilyType uint8
|
FamilyType uint8
|
||||||
Forward ipTuple
|
Forward ipTuple
|
||||||
Reverse ipTuple
|
Reverse ipTuple
|
||||||
|
Mark uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConntrackFlow) String() string {
|
func (s *ConntrackFlow) String() string {
|
||||||
// conntrack cmd output:
|
// 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
|
// 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\tsrc=%s dst=%s sport=%d dport=%d",
|
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,
|
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
||||||
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort,
|
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.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
|
// This method parse the ip tuple structure
|
||||||
@ -160,7 +168,7 @@ func (s *ConntrackFlow) String() string {
|
|||||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding>
|
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding>
|
||||||
// <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding>
|
// <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||||
// <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding>
|
// <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||||
func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) {
|
func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
_, t, _, v := parseNfAttrTLV(reader)
|
_, t, _, v := parseNfAttrTLV(reader)
|
||||||
switch t {
|
switch t {
|
||||||
@ -189,6 +197,7 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) {
|
|||||||
// Skip some padding 2 byte
|
// Skip some padding 2 byte
|
||||||
reader.Seek(2, seekCurrent)
|
reader.Seek(2, seekCurrent)
|
||||||
}
|
}
|
||||||
|
return tpl.Protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNfAttrTLV(r *bytes.Reader) (isNested bool, attrType, len uint16, value []byte) {
|
func parseNfAttrTLV(r *bytes.Reader) (isNested bool, attrType, len uint16, value []byte) {
|
||||||
@ -214,8 +223,27 @@ func parseBERaw16(r *bytes.Reader, v *uint16) {
|
|||||||
binary.Read(r, binary.BigEndian, v)
|
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 parseRawData(data []byte) *ConntrackFlow {
|
func parseRawData(data []byte) *ConntrackFlow {
|
||||||
s := &ConntrackFlow{}
|
s := &ConntrackFlow{}
|
||||||
|
var proto uint8
|
||||||
// First there is the Nfgenmsg header
|
// First there is the Nfgenmsg header
|
||||||
// consume only the family field
|
// consume only the family field
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
@ -231,24 +259,39 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes
|
// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes
|
||||||
// flow information of the reverse flow
|
// flow information of the reverse flow
|
||||||
for reader.Len() > 0 {
|
for reader.Len() > 0 {
|
||||||
nested, t, l := parseNfAttrTL(reader)
|
if nested, t, l := parseNfAttrTL(reader); nested {
|
||||||
if nested && t == nl.CTA_TUPLE_ORIG {
|
switch t {
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
case nl.CTA_TUPLE_ORIG:
|
||||||
parseIpTuple(reader, &s.Forward)
|
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
||||||
}
|
proto = parseIpTuple(reader, &s.Forward)
|
||||||
} else if nested && t == nl.CTA_TUPLE_REPLY {
|
}
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
case nl.CTA_TUPLE_REPLY:
|
||||||
parseIpTuple(reader, &s.Reverse)
|
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
||||||
|
parseIpTuple(reader, &s.Reverse)
|
||||||
// Got all the useful information stop parsing
|
} else {
|
||||||
break
|
// Header not recognized skip it
|
||||||
} else {
|
reader.Seek(int64(l), seekCurrent)
|
||||||
// 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +309,7 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
// Common parameters and options:
|
// Common parameters and options:
|
||||||
// -s, --src, --orig-src ip Source address from original direction
|
// -s, --src, --orig-src ip Source address from original direction
|
||||||
// -d, --dst, --orig-dst ip Destination 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
|
// -q, --reply-dst ip Destination address from reply direction
|
||||||
// -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
|
// -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
|
||||||
// -f, --family proto Layer 3 Protocol, eg. 'ipv6'
|
// -f, --family proto Layer 3 Protocol, eg. 'ipv6'
|
||||||
@ -283,11 +326,14 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
type ConntrackFilterType uint8
|
type ConntrackFilterType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||||
ConntrackNatSrcIP // -src-nat ip Source NAT ip
|
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||||
ConntrackNatDstIP // -dst-nat ip Destination NAT ip
|
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||||
ConntrackNatAnyIP // -any-nat ip Source or destination NAT 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 {
|
type CustomConntrackFilter interface {
|
||||||
@ -332,17 +378,17 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -src-nat ip Source NAT ip
|
// -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)
|
match = match && elem.Equal(flow.Reverse.SrcIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -dst-nat ip Destination NAT ip
|
// -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)
|
match = match && elem.Equal(flow.Reverse.DstIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -any-nat ip Source or destination NAT ip
|
// Match source or destination reply IP
|
||||||
if elem, found := f.ipFilter[ConntrackNatAnyIP]; match && found {
|
if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
|
||||||
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
|
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
29
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
@ -2,8 +2,6 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Filter interface {
|
type Filter interface {
|
||||||
@ -19,7 +17,7 @@ type FilterAttrs struct {
|
|||||||
Handle uint32
|
Handle uint32
|
||||||
Parent uint32
|
Parent uint32
|
||||||
Priority uint16 // lower is higher priority
|
Priority uint16 // lower is higher priority
|
||||||
Protocol uint16 // syscall.ETH_P_*
|
Protocol uint16 // unix.ETH_P_*
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q FilterAttrs) String() string {
|
func (q FilterAttrs) String() string {
|
||||||
@ -184,14 +182,6 @@ func NewMirredAction(redirIndex int) *MirredAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants used in TcU32Sel.Flags.
|
|
||||||
const (
|
|
||||||
TC_U32_TERMINAL = nl.TC_U32_TERMINAL
|
|
||||||
TC_U32_OFFSET = nl.TC_U32_OFFSET
|
|
||||||
TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET
|
|
||||||
TC_U32_EAT = nl.TC_U32_EAT
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sel of the U32 filters that contains multiple TcU32Key. This is the copy
|
// 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
|
// and the frontend representation of nl.TcU32Sel. It is serialized into canonical
|
||||||
// nl.TcU32Sel with the appropriate endianness.
|
// nl.TcU32Sel with the appropriate endianness.
|
||||||
@ -222,6 +212,8 @@ type TcU32Key struct {
|
|||||||
type U32 struct {
|
type U32 struct {
|
||||||
FilterAttrs
|
FilterAttrs
|
||||||
ClassId uint32
|
ClassId uint32
|
||||||
|
Divisor uint32 // Divisor MUST be power of 2.
|
||||||
|
Hash uint32
|
||||||
RedirIndex int
|
RedirIndex int
|
||||||
Sel *TcU32Sel
|
Sel *TcU32Sel
|
||||||
Actions []Action
|
Actions []Action
|
||||||
@ -235,6 +227,21 @@ func (filter *U32) Type() string {
|
|||||||
return "u32"
|
return "u32"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchAll filters match all packets
|
||||||
|
type MatchAll struct {
|
||||||
|
FilterAttrs
|
||||||
|
ClassId uint32
|
||||||
|
Actions []Action
|
||||||
|
}
|
||||||
|
|
||||||
|
func (filter *MatchAll) Attrs() *FilterAttrs {
|
||||||
|
return &filter.FilterAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (filter *MatchAll) Type() string {
|
||||||
|
return "matchall"
|
||||||
|
}
|
||||||
|
|
||||||
type FilterFwAttrs struct {
|
type FilterFwAttrs struct {
|
||||||
ClassId uint32
|
ClassId uint32
|
||||||
InDev string
|
InDev string
|
||||||
|
179
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
179
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
@ -9,6 +9,15 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constants used in TcU32Sel.Flags.
|
||||||
|
const (
|
||||||
|
TC_U32_TERMINAL = nl.TC_U32_TERMINAL
|
||||||
|
TC_U32_OFFSET = nl.TC_U32_OFFSET
|
||||||
|
TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET
|
||||||
|
TC_U32_EAT = nl.TC_U32_EAT
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fw filter filters on firewall marks
|
// Fw filter filters on firewall marks
|
||||||
@ -47,7 +56,7 @@ func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
|
|||||||
if police.Rate.Rate != 0 {
|
if police.Rate.Rate != 0 {
|
||||||
police.Rate.Mpu = fattrs.Mpu
|
police.Rate.Mpu = fattrs.Mpu
|
||||||
police.Rate.Overhead = fattrs.Overhead
|
police.Rate.Overhead = fattrs.Overhead
|
||||||
if CalcRtable(&police.Rate, rtab, rcellLog, fattrs.Mtu, linklayer) < 0 {
|
if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
|
||||||
return nil, errors.New("TBF: failed to calculate rate table")
|
return nil, errors.New("TBF: failed to calculate rate table")
|
||||||
}
|
}
|
||||||
police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer)))
|
police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer)))
|
||||||
@ -56,7 +65,7 @@ func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
|
|||||||
if police.PeakRate.Rate != 0 {
|
if police.PeakRate.Rate != 0 {
|
||||||
police.PeakRate.Mpu = fattrs.Mpu
|
police.PeakRate.Mpu = fattrs.Mpu
|
||||||
police.PeakRate.Overhead = fattrs.Overhead
|
police.PeakRate.Overhead = fattrs.Overhead
|
||||||
if CalcRtable(&police.PeakRate, ptab, pcellLog, fattrs.Mtu, linklayer) < 0 {
|
if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
|
||||||
return nil, errors.New("POLICE: failed to calculate peak rate table")
|
return nil, errors.New("POLICE: failed to calculate peak rate table")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +99,7 @@ func FilterDel(filter Filter) error {
|
|||||||
// FilterDel will delete a filter from the system.
|
// FilterDel will delete a filter from the system.
|
||||||
// Equivalent to: `tc filter del $filter`
|
// Equivalent to: `tc filter del $filter`
|
||||||
func (h *Handle) FilterDel(filter Filter) error {
|
func (h *Handle) FilterDel(filter Filter) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_DELTFILTER, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK)
|
||||||
base := filter.Attrs()
|
base := filter.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
@ -101,7 +110,7 @@ func (h *Handle) FilterDel(filter Filter) error {
|
|||||||
}
|
}
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +124,7 @@ func FilterAdd(filter Filter) error {
|
|||||||
// Equivalent to: `tc filter add $filter`
|
// Equivalent to: `tc filter add $filter`
|
||||||
func (h *Handle) FilterAdd(filter Filter) error {
|
func (h *Handle) FilterAdd(filter Filter) error {
|
||||||
native = nl.NativeEndian()
|
native = nl.NativeEndian()
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWTFILTER, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
base := filter.Attrs()
|
base := filter.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
@ -128,9 +137,11 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
|
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
|
||||||
|
|
||||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||||
if u32, ok := filter.(*U32); ok {
|
|
||||||
|
switch filter := filter.(type) {
|
||||||
|
case *U32:
|
||||||
// Convert TcU32Sel into nl.TcU32Sel as it is without copy.
|
// Convert TcU32Sel into nl.TcU32Sel as it is without copy.
|
||||||
sel := (*nl.TcU32Sel)(unsafe.Pointer(u32.Sel))
|
sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel))
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
// match all
|
// match all
|
||||||
sel = &nl.TcU32Sel{
|
sel = &nl.TcU32Sel{
|
||||||
@ -157,64 +168,81 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sel.Nkeys = uint8(len(sel.Keys))
|
sel.Nkeys = uint8(len(sel.Keys))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
|
options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
|
||||||
if u32.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(u32.ClassId))
|
options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
|
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))
|
||||||
|
}
|
||||||
|
if filter.Hash != 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
|
||||||
|
}
|
||||||
|
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
|
||||||
// backwards compatibility
|
// backwards compatibility
|
||||||
if u32.RedirIndex != 0 {
|
if filter.RedirIndex != 0 {
|
||||||
u32.Actions = append([]Action{NewMirredAction(u32.RedirIndex)}, u32.Actions...)
|
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
|
||||||
}
|
}
|
||||||
if err := EncodeActions(actionsAttr, u32.Actions); err != nil {
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if fw, ok := filter.(*Fw); ok {
|
case *Fw:
|
||||||
if fw.Mask != 0 {
|
if filter.Mask != 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, fw.Mask)
|
native.PutUint32(b, filter.Mask)
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
|
options.AddRtAttr(nl.TCA_FW_MASK, b)
|
||||||
}
|
}
|
||||||
if fw.InDev != "" {
|
if filter.InDev != "" {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(fw.InDev))
|
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
||||||
}
|
}
|
||||||
if (fw.Police != nl.TcPolice{}) {
|
if (filter.Police != nl.TcPolice{}) {
|
||||||
|
|
||||||
police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
|
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, fw.Police.Serialize())
|
police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
||||||
if (fw.Police.Rate != nl.TcRateSpec{}) {
|
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
||||||
payload := SerializeRtab(fw.Rtab)
|
payload := SerializeRtab(filter.Rtab)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
|
police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
|
||||||
}
|
}
|
||||||
if (fw.Police.PeakRate != nl.TcRateSpec{}) {
|
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
||||||
payload := SerializeRtab(fw.Ptab)
|
payload := SerializeRtab(filter.Ptab)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
|
police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fw.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, fw.ClassId)
|
native.PutUint32(b, filter.ClassId)
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
|
options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
||||||
}
|
}
|
||||||
} else if bpf, ok := filter.(*BpfFilter); ok {
|
case *BpfFilter:
|
||||||
var bpfFlags uint32
|
var bpfFlags uint32
|
||||||
if bpf.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(bpf.ClassId))
|
options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
if bpf.Fd >= 0 {
|
if filter.Fd >= 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(bpf.Fd))))
|
options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
|
||||||
}
|
}
|
||||||
if bpf.Name != "" {
|
if filter.Name != "" {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(bpf.Name))
|
options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
|
||||||
}
|
}
|
||||||
if bpf.DirectAction {
|
if filter.DirectAction {
|
||||||
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
|
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 := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil)
|
||||||
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if filter.ClassId != 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req.AddData(options)
|
req.AddData(options)
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +257,7 @@ func FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
// Equivalent to: `tc filter show`.
|
// Equivalent to: `tc filter show`.
|
||||||
// Generally returns nothing if link and parent are not specified.
|
// Generally returns nothing if link and parent are not specified.
|
||||||
func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETTFILTER, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP)
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
Parent: parent,
|
Parent: parent,
|
||||||
@ -241,7 +269,7 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
}
|
}
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTFILTER)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -277,6 +305,8 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
filter = &Fw{}
|
filter = &Fw{}
|
||||||
case "bpf":
|
case "bpf":
|
||||||
filter = &BpfFilter{}
|
filter = &BpfFilter{}
|
||||||
|
case "matchall":
|
||||||
|
filter = &MatchAll{}
|
||||||
default:
|
default:
|
||||||
filter = &GenericFilter{FilterType: filterType}
|
filter = &GenericFilter{FilterType: filterType}
|
||||||
}
|
}
|
||||||
@ -301,6 +331,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case "matchall":
|
||||||
|
detailed, err = parseMatchAllData(filter, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
detailed = true
|
detailed = true
|
||||||
}
|
}
|
||||||
@ -340,34 +375,34 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown action type %s", action.Type())
|
return fmt.Errorf("unknown action type %s", action.Type())
|
||||||
case *MirredAction:
|
case *MirredAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
mirred := nl.TcMirred{
|
mirred := nl.TcMirred{
|
||||||
Eaction: int32(action.MirredAction),
|
Eaction: int32(action.MirredAction),
|
||||||
Ifindex: uint32(action.Ifindex),
|
Ifindex: uint32(action.Ifindex),
|
||||||
}
|
}
|
||||||
toTcGen(action.Attrs(), &mirred.TcGen)
|
toTcGen(action.Attrs(), &mirred.TcGen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
||||||
case *BpfAction:
|
case *BpfAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
gen := nl.TcGen{}
|
gen := nl.TcGen{}
|
||||||
toTcGen(action.Attrs(), &gen)
|
toTcGen(action.Attrs(), &gen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
aopts.AddRtAttr(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_NAME, nl.ZeroTerminated(action.Name))
|
||||||
case *GenericAction:
|
case *GenericAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
gen := nl.TcGen{}
|
gen := nl.TcGen{}
|
||||||
toTcGen(action.Attrs(), &gen)
|
toTcGen(action.Attrs(), &gen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize())
|
aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -474,6 +509,10 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
}
|
}
|
||||||
case nl.TCA_U32_CLASSID:
|
case nl.TCA_U32_CLASSID:
|
||||||
u32.ClassId = native.Uint32(datum.Value)
|
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
|
return detailed, nil
|
||||||
@ -530,6 +569,28 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
return detailed, nil
|
return detailed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
|
native = nl.NativeEndian()
|
||||||
|
matchall := filter.(*MatchAll)
|
||||||
|
detailed := true
|
||||||
|
for _, datum := range data {
|
||||||
|
switch datum.Attr.Type {
|
||||||
|
case nl.TCA_MATCHALL_CLASSID:
|
||||||
|
matchall.ClassId = native.Uint32(datum.Value[0:4])
|
||||||
|
case nl.TCA_MATCHALL_ACT:
|
||||||
|
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||||
|
if err != nil {
|
||||||
|
return detailed, err
|
||||||
|
}
|
||||||
|
matchall.Actions, err = parseActions(tables)
|
||||||
|
if err != nil {
|
||||||
|
return detailed, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return detailed, nil
|
||||||
|
}
|
||||||
|
|
||||||
func AlignToAtm(size uint) uint {
|
func AlignToAtm(size uint) uint {
|
||||||
var linksize, cells int
|
var linksize, cells int
|
||||||
cells = int(size / nl.ATM_CELL_PAYLOAD)
|
cells = int(size / nl.ATM_CELL_PAYLOAD)
|
||||||
@ -552,7 +613,7 @@ func AdjustSize(sz uint, mpu uint, linklayer int) uint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CalcRtable(rate *nl.TcRateSpec, rtab [256]uint32, cellLog int, mtu uint32, linklayer int) int {
|
func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int {
|
||||||
bps := rate.Rate
|
bps := rate.Rate
|
||||||
mpu := rate.Mpu
|
mpu := rate.Mpu
|
||||||
var sz uint
|
var sz uint
|
||||||
|
21
vendor/github.com/vishvananda/netlink/fou.go
generated
vendored
Normal file
21
vendor/github.com/vishvananda/netlink/fou.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrAttrHeaderTruncated is returned when a netlink attribute's header is
|
||||||
|
// truncated.
|
||||||
|
ErrAttrHeaderTruncated = errors.New("attribute header truncated")
|
||||||
|
// ErrAttrBodyTruncated is returned when a netlink attribute's body is
|
||||||
|
// truncated.
|
||||||
|
ErrAttrBodyTruncated = errors.New("attribute body truncated")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fou struct {
|
||||||
|
Family int
|
||||||
|
Port int
|
||||||
|
Protocol int
|
||||||
|
EncapType int
|
||||||
|
}
|
215
vendor/github.com/vishvananda/netlink/fou_linux.go
generated
vendored
Normal file
215
vendor/github.com/vishvananda/netlink/fou_linux.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FOU_GENL_NAME = "fou"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FOU_CMD_UNSPEC uint8 = iota
|
||||||
|
FOU_CMD_ADD
|
||||||
|
FOU_CMD_DEL
|
||||||
|
FOU_CMD_GET
|
||||||
|
FOU_CMD_MAX = FOU_CMD_GET
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FOU_ATTR_UNSPEC = iota
|
||||||
|
FOU_ATTR_PORT
|
||||||
|
FOU_ATTR_AF
|
||||||
|
FOU_ATTR_IPPROTO
|
||||||
|
FOU_ATTR_TYPE
|
||||||
|
FOU_ATTR_REMCSUM_NOPARTIAL
|
||||||
|
FOU_ATTR_MAX = FOU_ATTR_REMCSUM_NOPARTIAL
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FOU_ENCAP_UNSPEC = iota
|
||||||
|
FOU_ENCAP_DIRECT
|
||||||
|
FOU_ENCAP_GUE
|
||||||
|
FOU_ENCAP_MAX = FOU_ENCAP_GUE
|
||||||
|
)
|
||||||
|
|
||||||
|
var fouFamilyId int
|
||||||
|
|
||||||
|
func FouFamilyId() (int, error) {
|
||||||
|
if fouFamilyId != 0 {
|
||||||
|
return fouFamilyId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fam, err := GenlFamilyGet(FOU_GENL_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fouFamilyId = int(fam.ID)
|
||||||
|
return fouFamilyId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FouAdd(f Fou) error {
|
||||||
|
return pkgHandle.FouAdd(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) FouAdd(f Fou) error {
|
||||||
|
fam_id, err := FouFamilyId()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting ip protocol conflicts with encapsulation type GUE
|
||||||
|
if f.EncapType == FOU_ENCAP_GUE && f.Protocol != 0 {
|
||||||
|
return errors.New("GUE encapsulation doesn't specify an IP protocol")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK)
|
||||||
|
|
||||||
|
// int to byte for port
|
||||||
|
bp := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port))
|
||||||
|
|
||||||
|
attrs := []*nl.RtAttr{
|
||||||
|
nl.NewRtAttr(FOU_ATTR_PORT, bp),
|
||||||
|
nl.NewRtAttr(FOU_ATTR_TYPE, []byte{uint8(f.EncapType)}),
|
||||||
|
nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}),
|
||||||
|
nl.NewRtAttr(FOU_ATTR_IPPROTO, []byte{uint8(f.Protocol)}),
|
||||||
|
}
|
||||||
|
raw := []byte{FOU_CMD_ADD, 1, 0, 0}
|
||||||
|
for _, a := range attrs {
|
||||||
|
raw = append(raw, a.Serialize()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddRawData(raw)
|
||||||
|
|
||||||
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FouDel(f Fou) error {
|
||||||
|
return pkgHandle.FouDel(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) FouDel(f Fou) error {
|
||||||
|
fam_id, err := FouFamilyId()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req := h.newNetlinkRequest(fam_id, unix.NLM_F_ACK)
|
||||||
|
|
||||||
|
// int to byte for port
|
||||||
|
bp := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(bp[0:2], uint16(f.Port))
|
||||||
|
|
||||||
|
attrs := []*nl.RtAttr{
|
||||||
|
nl.NewRtAttr(FOU_ATTR_PORT, bp),
|
||||||
|
nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(f.Family)}),
|
||||||
|
}
|
||||||
|
raw := []byte{FOU_CMD_DEL, 1, 0, 0}
|
||||||
|
for _, a := range attrs {
|
||||||
|
raw = append(raw, a.Serialize()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddRawData(raw)
|
||||||
|
|
||||||
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FouList(fam int) ([]Fou, error) {
|
||||||
|
return pkgHandle.FouList(fam)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) FouList(fam int) ([]Fou, error) {
|
||||||
|
fam_id, err := FouFamilyId()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req := h.newNetlinkRequest(fam_id, unix.NLM_F_DUMP)
|
||||||
|
|
||||||
|
attrs := []*nl.RtAttr{
|
||||||
|
nl.NewRtAttr(FOU_ATTR_AF, []byte{uint8(fam)}),
|
||||||
|
}
|
||||||
|
raw := []byte{FOU_CMD_GET, 1, 0, 0}
|
||||||
|
for _, a := range attrs {
|
||||||
|
raw = append(raw, a.Serialize()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddRawData(raw)
|
||||||
|
|
||||||
|
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fous := make([]Fou, 0, len(msgs))
|
||||||
|
for _, m := range msgs {
|
||||||
|
f, err := deserializeFouMsg(m)
|
||||||
|
if err != nil {
|
||||||
|
return fous, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fous = append(fous, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fous, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeFouMsg(msg []byte) (Fou, error) {
|
||||||
|
// we'll skip to byte 4 to first attribute
|
||||||
|
msg = msg[3:]
|
||||||
|
var shift int
|
||||||
|
fou := Fou{}
|
||||||
|
|
||||||
|
for {
|
||||||
|
// attribute header is at least 16 bits
|
||||||
|
if len(msg) < 4 {
|
||||||
|
return fou, ErrAttrHeaderTruncated
|
||||||
|
}
|
||||||
|
|
||||||
|
lgt := int(binary.BigEndian.Uint16(msg[0:2]))
|
||||||
|
if len(msg) < lgt+4 {
|
||||||
|
return fou, ErrAttrBodyTruncated
|
||||||
|
}
|
||||||
|
attr := binary.BigEndian.Uint16(msg[2:4])
|
||||||
|
|
||||||
|
shift = lgt + 3
|
||||||
|
switch attr {
|
||||||
|
case FOU_ATTR_AF:
|
||||||
|
fou.Family = int(msg[5])
|
||||||
|
case FOU_ATTR_PORT:
|
||||||
|
fou.Port = int(binary.BigEndian.Uint16(msg[5:7]))
|
||||||
|
// port is 2 bytes
|
||||||
|
shift = lgt + 2
|
||||||
|
case FOU_ATTR_IPPROTO:
|
||||||
|
fou.Protocol = int(msg[5])
|
||||||
|
case FOU_ATTR_TYPE:
|
||||||
|
fou.EncapType = int(msg[5])
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = msg[shift:]
|
||||||
|
|
||||||
|
if len(msg) < 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fou, nil
|
||||||
|
}
|
15
vendor/github.com/vishvananda/netlink/fou_unspecified.go
generated
vendored
Normal file
15
vendor/github.com/vishvananda/netlink/fou_unspecified.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package netlink
|
||||||
|
|
||||||
|
func FouAdd(f Fou) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func FouDel(f Fou) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func FouList(fam int) ([]Fou, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
7
vendor/github.com/vishvananda/netlink/genetlink_linux.go
generated
vendored
7
vendor/github.com/vishvananda/netlink/genetlink_linux.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GenlOp struct {
|
type GenlOp struct {
|
||||||
@ -130,9 +131,9 @@ func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
|
|||||||
Command: nl.GENL_CTRL_CMD_GETFAMILY,
|
Command: nl.GENL_CTRL_CMD_GETFAMILY,
|
||||||
Version: nl.GENL_CTRL_VERSION,
|
Version: nl.GENL_CTRL_VERSION,
|
||||||
}
|
}
|
||||||
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, unix.NLM_F_DUMP)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
|
|||||||
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
|
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
|
req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
|
||||||
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
15
vendor/github.com/vishvananda/netlink/gtp_linux.go
generated
vendored
15
vendor/github.com/vishvananda/netlink/gtp_linux.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PDP struct {
|
type PDP struct {
|
||||||
@ -82,9 +83,9 @@ func (h *Handle) GTPPDPList() ([]*PDP, error) {
|
|||||||
Command: nl.GENL_GTP_CMD_GETPDP,
|
Command: nl.GENL_GTP_CMD_GETPDP,
|
||||||
Version: nl.GENL_GTP_VERSION,
|
Version: nl.GENL_GTP_VERSION,
|
||||||
}
|
}
|
||||||
req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_DUMP)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -96,7 +97,7 @@ func GTPPDPList() ([]*PDP, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
|
func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
|
||||||
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -182,7 +183,7 @@ func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
|
|||||||
Command: nl.GENL_GTP_CMD_NEWPDP,
|
Command: nl.GENL_GTP_CMD_NEWPDP,
|
||||||
Version: nl.GENL_GTP_VERSION,
|
Version: nl.GENL_GTP_VERSION,
|
||||||
}
|
}
|
||||||
req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
|
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
|
||||||
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
|
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
|
||||||
@ -199,7 +200,7 @@ func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
|
return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
|
||||||
}
|
}
|
||||||
_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
|
|||||||
Command: nl.GENL_GTP_CMD_DELPDP,
|
Command: nl.GENL_GTP_CMD_DELPDP,
|
||||||
Version: nl.GENL_GTP_VERSION,
|
Version: nl.GENL_GTP_VERSION,
|
||||||
}
|
}
|
||||||
req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
|
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
|
||||||
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
|
req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
|
||||||
@ -229,7 +230,7 @@ func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
|
return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
|
||||||
}
|
}
|
||||||
_, err = req.Execute(syscall.NETLINK_GENERIC, 0)
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
51
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
@ -2,11 +2,11 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Empty handle used by the netlink package methods
|
// Empty handle used by the netlink package methods
|
||||||
@ -43,14 +43,29 @@ func (h *Handle) SetSocketTimeout(to time.Duration) error {
|
|||||||
if to < time.Microsecond {
|
if to < time.Microsecond {
|
||||||
return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
|
return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
|
||||||
}
|
}
|
||||||
tv := syscall.NsecToTimeval(to.Nanoseconds())
|
tv := unix.NsecToTimeval(to.Nanoseconds())
|
||||||
for _, sh := range h.sockets {
|
for _, sh := range h.sockets {
|
||||||
fd := sh.Socket.GetFd()
|
if err := sh.Socket.SetSendTimeout(&tv); err != nil {
|
||||||
err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
|
if err := sh.Socket.SetReceiveTimeout(&tv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSocketReceiveBufferSize sets the receive buffer size for each
|
||||||
|
// socket in the netlink handle. The maximum value is capped by
|
||||||
|
// /proc/sys/net/core/rmem_max.
|
||||||
|
func (h *Handle) SetSocketReceiveBufferSize(size int, force bool) error {
|
||||||
|
opt := unix.SO_RCVBUF
|
||||||
|
if force {
|
||||||
|
opt = unix.SO_RCVBUFFORCE
|
||||||
|
}
|
||||||
|
for _, sh := range h.sockets {
|
||||||
|
fd := sh.Socket.GetFd()
|
||||||
|
err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, opt, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -58,6 +73,24 @@ func (h *Handle) SetSocketTimeout(to time.Duration) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSocketReceiveBufferSize gets the receiver buffer size for each
|
||||||
|
// socket in the netlink handle. The retrieved value should be the
|
||||||
|
// double to the one set for SetSocketReceiveBufferSize.
|
||||||
|
func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
|
||||||
|
results := make([]int, len(h.sockets))
|
||||||
|
i := 0
|
||||||
|
for _, sh := range h.sockets {
|
||||||
|
fd := sh.Socket.GetFd()
|
||||||
|
size, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_RCVBUF)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
results[i] = size
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewHandle returns a netlink handle on the network namespace
|
// NewHandle returns a netlink handle on the network namespace
|
||||||
// specified by ns. If ns=netns.None(), current network namespace
|
// specified by ns. If ns=netns.None(), current network namespace
|
||||||
// will be assumed
|
// will be assumed
|
||||||
@ -101,10 +134,10 @@ func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
|||||||
return nl.NewNetlinkRequest(proto, flags)
|
return nl.NewNetlinkRequest(proto, flags)
|
||||||
}
|
}
|
||||||
return &nl.NetlinkRequest{
|
return &nl.NetlinkRequest{
|
||||||
NlMsghdr: syscall.NlMsghdr{
|
NlMsghdr: unix.NlMsghdr{
|
||||||
Len: uint32(syscall.SizeofNlMsghdr),
|
Len: uint32(unix.SizeofNlMsghdr),
|
||||||
Type: uint16(proto),
|
Type: uint16(proto),
|
||||||
Flags: syscall.NLM_F_REQUEST | uint16(flags),
|
Flags: unix.NLM_F_REQUEST | uint16(flags),
|
||||||
},
|
},
|
||||||
Sockets: h.sockets,
|
Sockets: h.sockets,
|
||||||
}
|
}
|
||||||
|
40
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
40
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
@ -145,6 +145,10 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
@ -216,3 +220,39 @@ func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
|
|||||||
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
||||||
return nil, ErrNotImplemented
|
return nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteAdd(route *Route) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteDel(route *Route) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RouteReplace(route *Route) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RuleAdd(rule *Rule) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RuleDel(rule *Rule) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) RuleList(family int) ([]Rule, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
98
vendor/github.com/vishvananda/netlink/ioctl_linux.go
generated
vendored
Normal file
98
vendor/github.com/vishvananda/netlink/ioctl_linux.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ioctl for statistics.
|
||||||
|
const (
|
||||||
|
// ETHTOOL_GSSET_INFO gets string set info
|
||||||
|
ETHTOOL_GSSET_INFO = 0x00000037
|
||||||
|
// SIOCETHTOOL is Ethtool interface
|
||||||
|
SIOCETHTOOL = 0x8946
|
||||||
|
// ETHTOOL_GSTRINGS gets specified string set
|
||||||
|
ETHTOOL_GSTRINGS = 0x0000001b
|
||||||
|
// ETHTOOL_GSTATS gets NIC-specific statistics
|
||||||
|
ETHTOOL_GSTATS = 0x0000001d
|
||||||
|
)
|
||||||
|
|
||||||
|
// string set id.
|
||||||
|
const (
|
||||||
|
// ETH_SS_TEST is self-test result names, for use with %ETHTOOL_TEST
|
||||||
|
ETH_SS_TEST = iota
|
||||||
|
// ETH_SS_STATS statistic names, for use with %ETHTOOL_GSTATS
|
||||||
|
ETH_SS_STATS
|
||||||
|
// ETH_SS_PRIV_FLAGS are driver private flag names
|
||||||
|
ETH_SS_PRIV_FLAGS
|
||||||
|
// _ETH_SS_NTUPLE_FILTERS is deprecated
|
||||||
|
_ETH_SS_NTUPLE_FILTERS
|
||||||
|
// ETH_SS_FEATURES are device feature names
|
||||||
|
ETH_SS_FEATURES
|
||||||
|
// ETH_SS_RSS_HASH_FUNCS is RSS hush function names
|
||||||
|
ETH_SS_RSS_HASH_FUNCS
|
||||||
|
)
|
||||||
|
|
||||||
|
// IfreqSlave is a struct for ioctl bond manipulation syscalls.
|
||||||
|
// It is used to assign slave to bond interface with Name.
|
||||||
|
type IfreqSlave struct {
|
||||||
|
Name [unix.IFNAMSIZ]byte
|
||||||
|
Slave [unix.IFNAMSIZ]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ifreq is a struct for ioctl ethernet manipulation syscalls.
|
||||||
|
type Ifreq struct {
|
||||||
|
Name [unix.IFNAMSIZ]byte
|
||||||
|
Data uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// ethtoolSset is a string set information
|
||||||
|
type ethtoolSset struct {
|
||||||
|
cmd uint32
|
||||||
|
reserved uint32
|
||||||
|
mask uint64
|
||||||
|
data [1]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ethtoolGstrings is string set for data tagging
|
||||||
|
type ethtoolGstrings struct {
|
||||||
|
cmd uint32
|
||||||
|
stringSet uint32
|
||||||
|
length uint32
|
||||||
|
data [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type ethtoolStats struct {
|
||||||
|
cmd uint32
|
||||||
|
nStats uint32
|
||||||
|
data [1]uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIocltSlaveReq returns filled IfreqSlave with proper interface names
|
||||||
|
// It is used by ioctl to assign slave to bond master
|
||||||
|
func newIocltSlaveReq(slave, master string) *IfreqSlave {
|
||||||
|
ifreq := &IfreqSlave{}
|
||||||
|
copy(ifreq.Name[:unix.IFNAMSIZ-1], master)
|
||||||
|
copy(ifreq.Slave[:unix.IFNAMSIZ-1], slave)
|
||||||
|
return ifreq
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIocltStringSetReq creates request to get interface string set
|
||||||
|
func newIocltStringSetReq(linkName string) (*Ifreq, *ethtoolSset) {
|
||||||
|
e := ðtoolSset{
|
||||||
|
cmd: ETHTOOL_GSSET_INFO,
|
||||||
|
mask: 1 << ETH_SS_STATS,
|
||||||
|
}
|
||||||
|
|
||||||
|
ifreq := &Ifreq{Data: uintptr(unsafe.Pointer(e))}
|
||||||
|
copy(ifreq.Name[:unix.IFNAMSIZ-1], linkName)
|
||||||
|
return ifreq, e
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSocketUDP returns file descriptor to new UDP socket
|
||||||
|
// It is used for communication with ioctl interface.
|
||||||
|
func getSocketUDP() (int, error) {
|
||||||
|
return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0)
|
||||||
|
}
|
148
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
148
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
@ -3,6 +3,7 @@ package netlink
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Link represents a link device from netlink. Shared link attributes
|
// Link represents a link device from netlink. Shared link attributes
|
||||||
@ -37,6 +38,21 @@ type LinkAttrs struct {
|
|||||||
EncapType string
|
EncapType string
|
||||||
Protinfo *Protinfo
|
Protinfo *Protinfo
|
||||||
OperState LinkOperState
|
OperState LinkOperState
|
||||||
|
NetNsID int
|
||||||
|
NumTxQueues int
|
||||||
|
NumRxQueues int
|
||||||
|
Vfs []VfInfo // virtual functions available on link
|
||||||
|
}
|
||||||
|
|
||||||
|
// VfInfo represents configuration of virtual function
|
||||||
|
type VfInfo struct {
|
||||||
|
ID int
|
||||||
|
Mac net.HardwareAddr
|
||||||
|
Vlan int
|
||||||
|
Qos int
|
||||||
|
TxRate int
|
||||||
|
Spoofchk bool
|
||||||
|
LinkState uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinkOperState represents the values of the IFLA_OPERSTATE link
|
// LinkOperState represents the values of the IFLA_OPERSTATE link
|
||||||
@ -171,6 +187,7 @@ type LinkXdp struct {
|
|||||||
Fd int
|
Fd int
|
||||||
Attached bool
|
Attached bool
|
||||||
Flags uint32
|
Flags uint32
|
||||||
|
ProgId uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device links cannot be created via netlink. These links
|
// Device links cannot be created via netlink. These links
|
||||||
@ -218,6 +235,7 @@ type Bridge struct {
|
|||||||
LinkAttrs
|
LinkAttrs
|
||||||
MulticastSnooping *bool
|
MulticastSnooping *bool
|
||||||
HelloTime *uint32
|
HelloTime *uint32
|
||||||
|
VlanFiltering *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *Bridge) Attrs() *LinkAttrs {
|
func (bridge *Bridge) Attrs() *LinkAttrs {
|
||||||
@ -257,6 +275,9 @@ const (
|
|||||||
type Macvlan struct {
|
type Macvlan struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Mode MacvlanMode
|
Mode MacvlanMode
|
||||||
|
|
||||||
|
// MACAddrs is only populated for Macvlan SOURCE links
|
||||||
|
MACAddrs []net.HardwareAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (macvlan *Macvlan) Attrs() *LinkAttrs {
|
func (macvlan *Macvlan) Attrs() *LinkAttrs {
|
||||||
@ -282,8 +303,11 @@ type TuntapFlag uint16
|
|||||||
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
||||||
type Tuntap struct {
|
type Tuntap struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Mode TuntapMode
|
Mode TuntapMode
|
||||||
Flags TuntapFlag
|
Flags TuntapFlag
|
||||||
|
NonPersist bool
|
||||||
|
Queues int
|
||||||
|
Fds []*os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
||||||
@ -325,26 +349,28 @@ func (generic *GenericLink) Type() string {
|
|||||||
|
|
||||||
type Vxlan struct {
|
type Vxlan struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
VxlanId int
|
VxlanId int
|
||||||
VtepDevIndex int
|
VtepDevIndex int
|
||||||
SrcAddr net.IP
|
SrcAddr net.IP
|
||||||
Group net.IP
|
Group net.IP
|
||||||
TTL int
|
TTL int
|
||||||
TOS int
|
TOS int
|
||||||
Learning bool
|
Learning bool
|
||||||
Proxy bool
|
Proxy bool
|
||||||
RSC bool
|
RSC bool
|
||||||
L2miss bool
|
L2miss bool
|
||||||
L3miss bool
|
L3miss bool
|
||||||
UDPCSum bool
|
UDPCSum bool
|
||||||
NoAge bool
|
UDP6ZeroCSumTx bool
|
||||||
GBP bool
|
UDP6ZeroCSumRx bool
|
||||||
FlowBased bool
|
NoAge bool
|
||||||
Age int
|
GBP bool
|
||||||
Limit int
|
FlowBased bool
|
||||||
Port int
|
Age int
|
||||||
PortLow int
|
Limit int
|
||||||
PortHigh int
|
Port int
|
||||||
|
PortLow int
|
||||||
|
PortHigh int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vxlan *Vxlan) Attrs() *LinkAttrs {
|
func (vxlan *Vxlan) Attrs() *LinkAttrs {
|
||||||
@ -693,17 +719,25 @@ func (gretap *Gretap) Attrs() *LinkAttrs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gretap *Gretap) Type() string {
|
func (gretap *Gretap) Type() string {
|
||||||
|
if gretap.Local.To4() == nil {
|
||||||
|
return "ip6gretap"
|
||||||
|
}
|
||||||
return "gretap"
|
return "gretap"
|
||||||
}
|
}
|
||||||
|
|
||||||
type Iptun struct {
|
type Iptun struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Ttl uint8
|
Ttl uint8
|
||||||
Tos uint8
|
Tos uint8
|
||||||
PMtuDisc uint8
|
PMtuDisc uint8
|
||||||
Link uint32
|
Link uint32
|
||||||
Local net.IP
|
Local net.IP
|
||||||
Remote net.IP
|
Remote net.IP
|
||||||
|
EncapSport uint16
|
||||||
|
EncapDport uint16
|
||||||
|
EncapType uint16
|
||||||
|
EncapFlags uint16
|
||||||
|
FlowBased bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iptun *Iptun) Attrs() *LinkAttrs {
|
func (iptun *Iptun) Attrs() *LinkAttrs {
|
||||||
@ -714,6 +748,28 @@ func (iptun *Iptun) Type() string {
|
|||||||
return "ipip"
|
return "ipip"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Sittun struct {
|
||||||
|
LinkAttrs
|
||||||
|
Link uint32
|
||||||
|
Local net.IP
|
||||||
|
Remote net.IP
|
||||||
|
Ttl uint8
|
||||||
|
Tos uint8
|
||||||
|
PMtuDisc uint8
|
||||||
|
EncapType uint16
|
||||||
|
EncapFlags uint16
|
||||||
|
EncapSport uint16
|
||||||
|
EncapDport uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sittun *Sittun) Attrs() *LinkAttrs {
|
||||||
|
return &sittun.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sittun *Sittun) Type() string {
|
||||||
|
return "sit"
|
||||||
|
}
|
||||||
|
|
||||||
type Vti struct {
|
type Vti struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
IKey uint32
|
IKey uint32
|
||||||
@ -727,10 +783,42 @@ func (vti *Vti) Attrs() *LinkAttrs {
|
|||||||
return &vti.LinkAttrs
|
return &vti.LinkAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iptun *Vti) Type() string {
|
func (vti *Vti) Type() string {
|
||||||
|
if vti.Local.To4() == nil {
|
||||||
|
return "vti6"
|
||||||
|
}
|
||||||
return "vti"
|
return "vti"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Gretun struct {
|
||||||
|
LinkAttrs
|
||||||
|
Link uint32
|
||||||
|
IFlags uint16
|
||||||
|
OFlags uint16
|
||||||
|
IKey uint32
|
||||||
|
OKey uint32
|
||||||
|
Local net.IP
|
||||||
|
Remote net.IP
|
||||||
|
Ttl uint8
|
||||||
|
Tos uint8
|
||||||
|
PMtuDisc uint8
|
||||||
|
EncapType uint16
|
||||||
|
EncapFlags uint16
|
||||||
|
EncapSport uint16
|
||||||
|
EncapDport uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gretun *Gretun) Attrs() *LinkAttrs {
|
||||||
|
return &gretun.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gretun *Gretun) Type() string {
|
||||||
|
if gretun.Local.To4() == nil {
|
||||||
|
return "ip6gre"
|
||||||
|
}
|
||||||
|
return "gre"
|
||||||
|
}
|
||||||
|
|
||||||
type Vrf struct {
|
type Vrf struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Table uint32
|
Table uint32
|
||||||
@ -763,7 +851,7 @@ func (gtp *GTP) Type() string {
|
|||||||
// iproute2 supported devices;
|
// iproute2 supported devices;
|
||||||
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
||||||
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
||||||
// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
|
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
|
||||||
// bond_slave | ipvlan
|
// bond_slave | ipvlan
|
||||||
|
|
||||||
// LinkNotFoundError wraps the various not found errors when
|
// LinkNotFoundError wraps the various not found errors when
|
||||||
|
1410
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
1410
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
@ -14,9 +14,18 @@ type Neigh struct {
|
|||||||
Flags int
|
Flags int
|
||||||
IP net.IP
|
IP net.IP
|
||||||
HardwareAddr net.HardwareAddr
|
HardwareAddr net.HardwareAddr
|
||||||
|
LLIPAddr net.IP //Used in the case of NHRP
|
||||||
|
Vlan int
|
||||||
|
VNI int
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns $ip/$hwaddr $label
|
// String returns $ip/$hwaddr $label
|
||||||
func (neigh *Neigh) String() string {
|
func (neigh *Neigh) String() string {
|
||||||
return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr)
|
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
|
||||||
|
}
|
||||||
|
152
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
152
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
@ -6,6 +6,8 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -73,7 +75,7 @@ func NeighAdd(neigh *Neigh) error {
|
|||||||
// NeighAdd will add an IP to MAC mapping to the ARP table
|
// NeighAdd will add an IP to MAC mapping to the ARP table
|
||||||
// Equivalent to: `ip neigh add ....`
|
// Equivalent to: `ip neigh add ....`
|
||||||
func (h *Handle) NeighAdd(neigh *Neigh) error {
|
func (h *Handle) NeighAdd(neigh *Neigh) error {
|
||||||
return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
|
return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighSet will add or replace an IP to MAC mapping to the ARP table
|
// NeighSet will add or replace an IP to MAC mapping to the ARP table
|
||||||
@ -85,7 +87,7 @@ func NeighSet(neigh *Neigh) error {
|
|||||||
// NeighSet will add or replace an IP to MAC mapping to the ARP table
|
// NeighSet will add or replace an IP to MAC mapping to the ARP table
|
||||||
// Equivalent to: `ip neigh replace....`
|
// Equivalent to: `ip neigh replace....`
|
||||||
func (h *Handle) NeighSet(neigh *Neigh) error {
|
func (h *Handle) NeighSet(neigh *Neigh) error {
|
||||||
return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
|
return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_REPLACE)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighAppend will append an entry to FDB
|
// NeighAppend will append an entry to FDB
|
||||||
@ -97,7 +99,7 @@ func NeighAppend(neigh *Neigh) error {
|
|||||||
// NeighAppend will append an entry to FDB
|
// NeighAppend will append an entry to FDB
|
||||||
// Equivalent to: `bridge fdb append...`
|
// Equivalent to: `bridge fdb append...`
|
||||||
func (h *Handle) NeighAppend(neigh *Neigh) error {
|
func (h *Handle) NeighAppend(neigh *Neigh) error {
|
||||||
return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
|
return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_APPEND)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighAppend will append an entry to FDB
|
// NeighAppend will append an entry to FDB
|
||||||
@ -109,7 +111,7 @@ func neighAdd(neigh *Neigh, mode int) error {
|
|||||||
// NeighAppend will append an entry to FDB
|
// NeighAppend will append an entry to FDB
|
||||||
// Equivalent to: `bridge fdb append...`
|
// Equivalent to: `bridge fdb append...`
|
||||||
func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
|
func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWNEIGH, mode|unix.NLM_F_ACK)
|
||||||
return neighHandle(neigh, req)
|
return neighHandle(neigh, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,12 +124,13 @@ func NeighDel(neigh *Neigh) error {
|
|||||||
// NeighDel will delete an IP address from a link device.
|
// NeighDel will delete an IP address from a link device.
|
||||||
// Equivalent to: `ip addr del $addr dev $link`
|
// Equivalent to: `ip addr del $addr dev $link`
|
||||||
func (h *Handle) NeighDel(neigh *Neigh) error {
|
func (h *Handle) NeighDel(neigh *Neigh) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELNEIGH, unix.NLM_F_ACK)
|
||||||
return neighHandle(neigh, req)
|
return neighHandle(neigh, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
||||||
var family int
|
var family int
|
||||||
|
|
||||||
if neigh.Family > 0 {
|
if neigh.Family > 0 {
|
||||||
family = neigh.Family
|
family = neigh.Family
|
||||||
} else {
|
} else {
|
||||||
@ -151,12 +154,25 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
|||||||
dstData := nl.NewRtAttr(NDA_DST, ipData)
|
dstData := nl.NewRtAttr(NDA_DST, ipData)
|
||||||
req.AddData(dstData)
|
req.AddData(dstData)
|
||||||
|
|
||||||
if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
|
if neigh.LLIPAddr != nil {
|
||||||
|
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
|
||||||
|
req.AddData(llIPData)
|
||||||
|
} else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
|
||||||
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
||||||
req.AddData(hwData)
|
req.AddData(hwData)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
if neigh.Vlan != 0 {
|
||||||
|
vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
|
||||||
|
req.AddData(vlanData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if neigh.VNI != 0 {
|
||||||
|
vniData := nl.NewRtAttr(NDA_VNI, nl.Uint32Attr(uint32(neigh.VNI)))
|
||||||
|
req.AddData(vniData)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +205,7 @@ func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
|
func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
|
||||||
msg := Ndmsg{
|
msg := Ndmsg{
|
||||||
Family: uint8(family),
|
Family: uint8(family),
|
||||||
Index: uint32(linkIndex),
|
Index: uint32(linkIndex),
|
||||||
@ -197,7 +213,7 @@ func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
|
|||||||
}
|
}
|
||||||
req.AddData(&msg)
|
req.AddData(&msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -237,14 +253,130 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
|||||||
return nil, err
|
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 {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case NDA_DST:
|
case NDA_DST:
|
||||||
neigh.IP = net.IP(attr.Value)
|
neigh.IP = net.IP(attr.Value)
|
||||||
case NDA_LLADDR:
|
case NDA_LLADDR:
|
||||||
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
// BUG: Is this a bug in the netlink library?
|
||||||
|
// #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") {
|
||||||
|
neigh.LLIPAddr = net.IP(attr.Value)
|
||||||
|
} else if attrLen == 16 &&
|
||||||
|
encapType == "tunnel6" {
|
||||||
|
neigh.IP = net.IP(attr.Value)
|
||||||
|
} else {
|
||||||
|
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
||||||
|
}
|
||||||
|
case NDA_VLAN:
|
||||||
|
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
|
||||||
|
case NDA_VNI:
|
||||||
|
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &neigh, nil
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if done != nil {
|
||||||
|
go func() {
|
||||||
|
<-done
|
||||||
|
s.Close()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
if listExisting {
|
||||||
|
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH,
|
||||||
|
unix.NLM_F_DUMP)
|
||||||
|
infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
|
req.AddData(infmsg)
|
||||||
|
if err := s.Send(req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
for {
|
||||||
|
msgs, err := s.Receive()
|
||||||
|
if err != nil {
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, m := range msgs {
|
||||||
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
|
native := nl.NativeEndian()
|
||||||
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
|
if error == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(syscall.Errno(-error))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
neigh, err := NeighDeserialize(m.Data)
|
||||||
|
if err != nil {
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch <- NeighUpdate{Type: m.Header.Type, Neigh: *neigh}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
3
vendor/github.com/vishvananda/netlink/netlink.go
generated
vendored
3
vendor/github.com/vishvananda/netlink/netlink.go
generated
vendored
@ -27,7 +27,8 @@ func ParseIPNet(s string) (*net.IPNet, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
|
||||||
|
4
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
@ -108,6 +108,10 @@ func LinkSetFlood(link Link, mode bool) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkSetTxQLen(link Link, qlen int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func LinkAdd(link Link) error {
|
func LinkAdd(link Link) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
141
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
Normal file
141
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetNsIdByPid 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetNsIdByPid 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
|
||||||
|
}
|
19
vendor/github.com/vishvananda/netlink/netns_unspecified.go
generated
vendored
Normal file
19
vendor/github.com/vishvananda/netlink/netns_unspecified.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
13
vendor/github.com/vishvananda/netlink/nl/addr_linux.go
generated
vendored
13
vendor/github.com/vishvananda/netlink/nl/addr_linux.go
generated
vendored
@ -1,17 +1,18 @@
|
|||||||
package nl
|
package nl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IfAddrmsg struct {
|
type IfAddrmsg struct {
|
||||||
syscall.IfAddrmsg
|
unix.IfAddrmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIfAddrmsg(family int) *IfAddrmsg {
|
func NewIfAddrmsg(family int) *IfAddrmsg {
|
||||||
return &IfAddrmsg{
|
return &IfAddrmsg{
|
||||||
IfAddrmsg: syscall.IfAddrmsg{
|
IfAddrmsg: unix.IfAddrmsg{
|
||||||
Family: uint8(family),
|
Family: uint8(family),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -35,15 +36,15 @@ func NewIfAddrmsg(family int) *IfAddrmsg {
|
|||||||
// SizeofIfAddrmsg = 0x8
|
// SizeofIfAddrmsg = 0x8
|
||||||
|
|
||||||
func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
|
func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
|
||||||
return (*IfAddrmsg)(unsafe.Pointer(&b[0:syscall.SizeofIfAddrmsg][0]))
|
return (*IfAddrmsg)(unsafe.Pointer(&b[0:unix.SizeofIfAddrmsg][0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfAddrmsg) Serialize() []byte {
|
func (msg *IfAddrmsg) Serialize() []byte {
|
||||||
return (*(*[syscall.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
|
return (*(*[unix.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfAddrmsg) Len() int {
|
func (msg *IfAddrmsg) Len() int {
|
||||||
return syscall.SizeofIfAddrmsg
|
return unix.SizeofIfAddrmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct ifa_cacheinfo {
|
// struct ifa_cacheinfo {
|
||||||
|
4
vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
generated
vendored
@ -11,8 +11,8 @@ const (
|
|||||||
|
|
||||||
/* Bridge Flags */
|
/* Bridge Flags */
|
||||||
const (
|
const (
|
||||||
BRIDGE_FLAGS_MASTER = iota /* Bridge command to/from master */
|
BRIDGE_FLAGS_MASTER = iota + 1 /* Bridge command to/from master */
|
||||||
BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
|
BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Bridge management nested attributes
|
/* Bridge management nested attributes
|
||||||
|
29
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
29
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
@ -76,12 +76,14 @@ const (
|
|||||||
// __CTA_MAX
|
// __CTA_MAX
|
||||||
// };
|
// };
|
||||||
const (
|
const (
|
||||||
CTA_TUPLE_ORIG = 1
|
CTA_TUPLE_ORIG = 1
|
||||||
CTA_TUPLE_REPLY = 2
|
CTA_TUPLE_REPLY = 2
|
||||||
CTA_STATUS = 3
|
CTA_STATUS = 3
|
||||||
CTA_TIMEOUT = 8
|
CTA_TIMEOUT = 7
|
||||||
CTA_MARK = 9
|
CTA_MARK = 8
|
||||||
CTA_PROTOINFO = 4
|
CTA_COUNTERS_ORIG = 9
|
||||||
|
CTA_COUNTERS_REPLY = 10
|
||||||
|
CTA_PROTOINFO = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// enum ctattr_tuple {
|
// enum ctattr_tuple {
|
||||||
@ -163,6 +165,21 @@ const (
|
|||||||
CTA_PROTOINFO_TCP_FLAGS_REPLY = 5
|
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
|
||||||
|
)
|
||||||
|
|
||||||
// /* General form of address family dependent message.
|
// /* General form of address family dependent message.
|
||||||
// */
|
// */
|
||||||
// struct nfgenmsg {
|
// struct nfgenmsg {
|
||||||
|
107
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
107
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
@ -1,35 +1,11 @@
|
|||||||
package nl
|
package nl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEFAULT_CHANGE = 0xFFFFFFFF
|
DEFAULT_CHANGE = 0xFFFFFFFF
|
||||||
// doesn't exist in syscall
|
|
||||||
IFLA_VFINFO_LIST = syscall.IFLA_IFALIAS + 1 + iota
|
|
||||||
IFLA_STATS64
|
|
||||||
IFLA_VF_PORTS
|
|
||||||
IFLA_PORT_SELF
|
|
||||||
IFLA_AF_SPEC
|
|
||||||
IFLA_GROUP
|
|
||||||
IFLA_NET_NS_FD
|
|
||||||
IFLA_EXT_MASK
|
|
||||||
IFLA_PROMISCUITY
|
|
||||||
IFLA_NUM_TX_QUEUES
|
|
||||||
IFLA_NUM_RX_QUEUES
|
|
||||||
IFLA_CARRIER
|
|
||||||
IFLA_PHYS_PORT_ID
|
|
||||||
IFLA_CARRIER_CHANGES
|
|
||||||
IFLA_PHYS_SWITCH_ID
|
|
||||||
IFLA_LINK_NETNSID
|
|
||||||
IFLA_PHYS_PORT_NAME
|
|
||||||
IFLA_PROTO_DOWN
|
|
||||||
IFLA_GSO_MAX_SEGS
|
|
||||||
IFLA_GSO_MAX_SIZE
|
|
||||||
IFLA_PAD
|
|
||||||
IFLA_XDP
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -118,6 +94,10 @@ const (
|
|||||||
IFLA_MACVLAN_UNSPEC = iota
|
IFLA_MACVLAN_UNSPEC = iota
|
||||||
IFLA_MACVLAN_MODE
|
IFLA_MACVLAN_MODE
|
||||||
IFLA_MACVLAN_FLAGS
|
IFLA_MACVLAN_FLAGS
|
||||||
|
IFLA_MACVLAN_MACADDR_MODE
|
||||||
|
IFLA_MACVLAN_MACADDR
|
||||||
|
IFLA_MACVLAN_MACADDR_DATA
|
||||||
|
IFLA_MACVLAN_MACADDR_COUNT
|
||||||
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
|
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,6 +109,13 @@ const (
|
|||||||
MACVLAN_MODE_SOURCE = 16
|
MACVLAN_MODE_SOURCE = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MACVLAN_MACADDR_ADD = iota
|
||||||
|
MACVLAN_MACADDR_DEL
|
||||||
|
MACVLAN_MACADDR_FLUSH
|
||||||
|
MACVLAN_MACADDR_SET
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IFLA_BOND_UNSPEC = iota
|
IFLA_BOND_UNSPEC = iota
|
||||||
IFLA_BOND_MODE
|
IFLA_BOND_MODE
|
||||||
@ -230,8 +217,11 @@ const (
|
|||||||
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
|
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
|
||||||
* on/off switch
|
* on/off switch
|
||||||
*/
|
*/
|
||||||
IFLA_VF_STATS /* network device statistics */
|
IFLA_VF_STATS /* network device statistics */
|
||||||
IFLA_VF_MAX = IFLA_VF_STATS
|
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 (
|
const (
|
||||||
@ -259,6 +249,8 @@ const (
|
|||||||
SizeofVfSpoofchk = 0x08
|
SizeofVfSpoofchk = 0x08
|
||||||
SizeofVfLinkState = 0x08
|
SizeofVfLinkState = 0x08
|
||||||
SizeofVfRssQueryEn = 0x08
|
SizeofVfRssQueryEn = 0x08
|
||||||
|
SizeofVfTrust = 0x08
|
||||||
|
SizeofVfGUID = 0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
// struct ifla_vf_mac {
|
// struct ifla_vf_mac {
|
||||||
@ -419,12 +411,66 @@ func (msg *VfRssQueryEn) Serialize() []byte {
|
|||||||
return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
|
return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct ifla_vf_trust {
|
||||||
|
// __u32 vf;
|
||||||
|
// __u32 setting;
|
||||||
|
// };
|
||||||
|
|
||||||
|
type VfTrust struct {
|
||||||
|
Vf uint32
|
||||||
|
Setting uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *VfTrust) Len() int {
|
||||||
|
return SizeofVfTrust
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeserializeVfTrust(b []byte) *VfTrust {
|
||||||
|
return (*VfTrust)(unsafe.Pointer(&b[0:SizeofVfTrust][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
XDP_FLAGS_DRV_MODE
|
||||||
|
XDP_FLAGS_MASK = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IFLA_XDP_UNSPEC = iota
|
IFLA_XDP_UNSPEC = iota
|
||||||
IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */
|
IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */
|
||||||
IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
|
IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
|
||||||
IFLA_XDP_FLAGS /* xdp prog related flags */
|
IFLA_XDP_FLAGS /* xdp prog related flags */
|
||||||
IFLA_XDP_MAX = IFLA_XDP_FLAGS
|
IFLA_XDP_PROG_ID /* xdp prog id */
|
||||||
|
IFLA_XDP_MAX = IFLA_XDP_PROG_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -443,7 +489,12 @@ const (
|
|||||||
IFLA_IPTUN_6RD_RELAY_PREFIX
|
IFLA_IPTUN_6RD_RELAY_PREFIX
|
||||||
IFLA_IPTUN_6RD_PREFIXLEN
|
IFLA_IPTUN_6RD_PREFIXLEN
|
||||||
IFLA_IPTUN_6RD_RELAY_PREFIXLEN
|
IFLA_IPTUN_6RD_RELAY_PREFIXLEN
|
||||||
IFLA_IPTUN_MAX = IFLA_IPTUN_6RD_RELAY_PREFIXLEN
|
IFLA_IPTUN_ENCAP_TYPE
|
||||||
|
IFLA_IPTUN_ENCAP_FLAGS
|
||||||
|
IFLA_IPTUN_ENCAP_SPORT
|
||||||
|
IFLA_IPTUN_ENCAP_DPORT
|
||||||
|
IFLA_IPTUN_COLLECT_METADATA
|
||||||
|
IFLA_IPTUN_MAX = IFLA_IPTUN_COLLECT_METADATA
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
265
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
265
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
@ -13,18 +13,23 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Family type definitions
|
// Family type definitions
|
||||||
FAMILY_ALL = syscall.AF_UNSPEC
|
FAMILY_ALL = unix.AF_UNSPEC
|
||||||
FAMILY_V4 = syscall.AF_INET
|
FAMILY_V4 = unix.AF_INET
|
||||||
FAMILY_V6 = syscall.AF_INET6
|
FAMILY_V6 = unix.AF_INET6
|
||||||
FAMILY_MPLS = AF_MPLS
|
FAMILY_MPLS = 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
|
||||||
)
|
)
|
||||||
|
|
||||||
// SupportedNlFamilies contains the list of netlink families this netlink package supports
|
// SupportedNlFamilies contains the list of netlink families this netlink package supports
|
||||||
var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM, syscall.NETLINK_NETFILTER}
|
var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER}
|
||||||
|
|
||||||
var nextSeqNr uint32
|
var nextSeqNr uint32
|
||||||
|
|
||||||
@ -77,161 +82,161 @@ type NetlinkRequestData interface {
|
|||||||
|
|
||||||
// IfInfomsg is related to links, but it is used for list requests as well
|
// IfInfomsg is related to links, but it is used for list requests as well
|
||||||
type IfInfomsg struct {
|
type IfInfomsg struct {
|
||||||
syscall.IfInfomsg
|
unix.IfInfomsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an IfInfomsg with family specified
|
// Create an IfInfomsg with family specified
|
||||||
func NewIfInfomsg(family int) *IfInfomsg {
|
func NewIfInfomsg(family int) *IfInfomsg {
|
||||||
return &IfInfomsg{
|
return &IfInfomsg{
|
||||||
IfInfomsg: syscall.IfInfomsg{
|
IfInfomsg: unix.IfInfomsg{
|
||||||
Family: uint8(family),
|
Family: uint8(family),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeserializeIfInfomsg(b []byte) *IfInfomsg {
|
func DeserializeIfInfomsg(b []byte) *IfInfomsg {
|
||||||
return (*IfInfomsg)(unsafe.Pointer(&b[0:syscall.SizeofIfInfomsg][0]))
|
return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfInfomsg) Serialize() []byte {
|
func (msg *IfInfomsg) Serialize() []byte {
|
||||||
return (*(*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
|
return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfInfomsg) Len() int {
|
func (msg *IfInfomsg) Len() int {
|
||||||
return syscall.SizeofIfInfomsg
|
return unix.SizeofIfInfomsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfInfomsg) EncapType() string {
|
func (msg *IfInfomsg) EncapType() string {
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case 0:
|
case 0:
|
||||||
return "generic"
|
return "generic"
|
||||||
case syscall.ARPHRD_ETHER:
|
case unix.ARPHRD_ETHER:
|
||||||
return "ether"
|
return "ether"
|
||||||
case syscall.ARPHRD_EETHER:
|
case unix.ARPHRD_EETHER:
|
||||||
return "eether"
|
return "eether"
|
||||||
case syscall.ARPHRD_AX25:
|
case unix.ARPHRD_AX25:
|
||||||
return "ax25"
|
return "ax25"
|
||||||
case syscall.ARPHRD_PRONET:
|
case unix.ARPHRD_PRONET:
|
||||||
return "pronet"
|
return "pronet"
|
||||||
case syscall.ARPHRD_CHAOS:
|
case unix.ARPHRD_CHAOS:
|
||||||
return "chaos"
|
return "chaos"
|
||||||
case syscall.ARPHRD_IEEE802:
|
case unix.ARPHRD_IEEE802:
|
||||||
return "ieee802"
|
return "ieee802"
|
||||||
case syscall.ARPHRD_ARCNET:
|
case unix.ARPHRD_ARCNET:
|
||||||
return "arcnet"
|
return "arcnet"
|
||||||
case syscall.ARPHRD_APPLETLK:
|
case unix.ARPHRD_APPLETLK:
|
||||||
return "atalk"
|
return "atalk"
|
||||||
case syscall.ARPHRD_DLCI:
|
case unix.ARPHRD_DLCI:
|
||||||
return "dlci"
|
return "dlci"
|
||||||
case syscall.ARPHRD_ATM:
|
case unix.ARPHRD_ATM:
|
||||||
return "atm"
|
return "atm"
|
||||||
case syscall.ARPHRD_METRICOM:
|
case unix.ARPHRD_METRICOM:
|
||||||
return "metricom"
|
return "metricom"
|
||||||
case syscall.ARPHRD_IEEE1394:
|
case unix.ARPHRD_IEEE1394:
|
||||||
return "ieee1394"
|
return "ieee1394"
|
||||||
case syscall.ARPHRD_INFINIBAND:
|
case unix.ARPHRD_INFINIBAND:
|
||||||
return "infiniband"
|
return "infiniband"
|
||||||
case syscall.ARPHRD_SLIP:
|
case unix.ARPHRD_SLIP:
|
||||||
return "slip"
|
return "slip"
|
||||||
case syscall.ARPHRD_CSLIP:
|
case unix.ARPHRD_CSLIP:
|
||||||
return "cslip"
|
return "cslip"
|
||||||
case syscall.ARPHRD_SLIP6:
|
case unix.ARPHRD_SLIP6:
|
||||||
return "slip6"
|
return "slip6"
|
||||||
case syscall.ARPHRD_CSLIP6:
|
case unix.ARPHRD_CSLIP6:
|
||||||
return "cslip6"
|
return "cslip6"
|
||||||
case syscall.ARPHRD_RSRVD:
|
case unix.ARPHRD_RSRVD:
|
||||||
return "rsrvd"
|
return "rsrvd"
|
||||||
case syscall.ARPHRD_ADAPT:
|
case unix.ARPHRD_ADAPT:
|
||||||
return "adapt"
|
return "adapt"
|
||||||
case syscall.ARPHRD_ROSE:
|
case unix.ARPHRD_ROSE:
|
||||||
return "rose"
|
return "rose"
|
||||||
case syscall.ARPHRD_X25:
|
case unix.ARPHRD_X25:
|
||||||
return "x25"
|
return "x25"
|
||||||
case syscall.ARPHRD_HWX25:
|
case unix.ARPHRD_HWX25:
|
||||||
return "hwx25"
|
return "hwx25"
|
||||||
case syscall.ARPHRD_PPP:
|
case unix.ARPHRD_PPP:
|
||||||
return "ppp"
|
return "ppp"
|
||||||
case syscall.ARPHRD_HDLC:
|
case unix.ARPHRD_HDLC:
|
||||||
return "hdlc"
|
return "hdlc"
|
||||||
case syscall.ARPHRD_LAPB:
|
case unix.ARPHRD_LAPB:
|
||||||
return "lapb"
|
return "lapb"
|
||||||
case syscall.ARPHRD_DDCMP:
|
case unix.ARPHRD_DDCMP:
|
||||||
return "ddcmp"
|
return "ddcmp"
|
||||||
case syscall.ARPHRD_RAWHDLC:
|
case unix.ARPHRD_RAWHDLC:
|
||||||
return "rawhdlc"
|
return "rawhdlc"
|
||||||
case syscall.ARPHRD_TUNNEL:
|
case unix.ARPHRD_TUNNEL:
|
||||||
return "ipip"
|
return "ipip"
|
||||||
case syscall.ARPHRD_TUNNEL6:
|
case unix.ARPHRD_TUNNEL6:
|
||||||
return "tunnel6"
|
return "tunnel6"
|
||||||
case syscall.ARPHRD_FRAD:
|
case unix.ARPHRD_FRAD:
|
||||||
return "frad"
|
return "frad"
|
||||||
case syscall.ARPHRD_SKIP:
|
case unix.ARPHRD_SKIP:
|
||||||
return "skip"
|
return "skip"
|
||||||
case syscall.ARPHRD_LOOPBACK:
|
case unix.ARPHRD_LOOPBACK:
|
||||||
return "loopback"
|
return "loopback"
|
||||||
case syscall.ARPHRD_LOCALTLK:
|
case unix.ARPHRD_LOCALTLK:
|
||||||
return "ltalk"
|
return "ltalk"
|
||||||
case syscall.ARPHRD_FDDI:
|
case unix.ARPHRD_FDDI:
|
||||||
return "fddi"
|
return "fddi"
|
||||||
case syscall.ARPHRD_BIF:
|
case unix.ARPHRD_BIF:
|
||||||
return "bif"
|
return "bif"
|
||||||
case syscall.ARPHRD_SIT:
|
case unix.ARPHRD_SIT:
|
||||||
return "sit"
|
return "sit"
|
||||||
case syscall.ARPHRD_IPDDP:
|
case unix.ARPHRD_IPDDP:
|
||||||
return "ip/ddp"
|
return "ip/ddp"
|
||||||
case syscall.ARPHRD_IPGRE:
|
case unix.ARPHRD_IPGRE:
|
||||||
return "gre"
|
return "gre"
|
||||||
case syscall.ARPHRD_PIMREG:
|
case unix.ARPHRD_PIMREG:
|
||||||
return "pimreg"
|
return "pimreg"
|
||||||
case syscall.ARPHRD_HIPPI:
|
case unix.ARPHRD_HIPPI:
|
||||||
return "hippi"
|
return "hippi"
|
||||||
case syscall.ARPHRD_ASH:
|
case unix.ARPHRD_ASH:
|
||||||
return "ash"
|
return "ash"
|
||||||
case syscall.ARPHRD_ECONET:
|
case unix.ARPHRD_ECONET:
|
||||||
return "econet"
|
return "econet"
|
||||||
case syscall.ARPHRD_IRDA:
|
case unix.ARPHRD_IRDA:
|
||||||
return "irda"
|
return "irda"
|
||||||
case syscall.ARPHRD_FCPP:
|
case unix.ARPHRD_FCPP:
|
||||||
return "fcpp"
|
return "fcpp"
|
||||||
case syscall.ARPHRD_FCAL:
|
case unix.ARPHRD_FCAL:
|
||||||
return "fcal"
|
return "fcal"
|
||||||
case syscall.ARPHRD_FCPL:
|
case unix.ARPHRD_FCPL:
|
||||||
return "fcpl"
|
return "fcpl"
|
||||||
case syscall.ARPHRD_FCFABRIC:
|
case unix.ARPHRD_FCFABRIC:
|
||||||
return "fcfb0"
|
return "fcfb0"
|
||||||
case syscall.ARPHRD_FCFABRIC + 1:
|
case unix.ARPHRD_FCFABRIC + 1:
|
||||||
return "fcfb1"
|
return "fcfb1"
|
||||||
case syscall.ARPHRD_FCFABRIC + 2:
|
case unix.ARPHRD_FCFABRIC + 2:
|
||||||
return "fcfb2"
|
return "fcfb2"
|
||||||
case syscall.ARPHRD_FCFABRIC + 3:
|
case unix.ARPHRD_FCFABRIC + 3:
|
||||||
return "fcfb3"
|
return "fcfb3"
|
||||||
case syscall.ARPHRD_FCFABRIC + 4:
|
case unix.ARPHRD_FCFABRIC + 4:
|
||||||
return "fcfb4"
|
return "fcfb4"
|
||||||
case syscall.ARPHRD_FCFABRIC + 5:
|
case unix.ARPHRD_FCFABRIC + 5:
|
||||||
return "fcfb5"
|
return "fcfb5"
|
||||||
case syscall.ARPHRD_FCFABRIC + 6:
|
case unix.ARPHRD_FCFABRIC + 6:
|
||||||
return "fcfb6"
|
return "fcfb6"
|
||||||
case syscall.ARPHRD_FCFABRIC + 7:
|
case unix.ARPHRD_FCFABRIC + 7:
|
||||||
return "fcfb7"
|
return "fcfb7"
|
||||||
case syscall.ARPHRD_FCFABRIC + 8:
|
case unix.ARPHRD_FCFABRIC + 8:
|
||||||
return "fcfb8"
|
return "fcfb8"
|
||||||
case syscall.ARPHRD_FCFABRIC + 9:
|
case unix.ARPHRD_FCFABRIC + 9:
|
||||||
return "fcfb9"
|
return "fcfb9"
|
||||||
case syscall.ARPHRD_FCFABRIC + 10:
|
case unix.ARPHRD_FCFABRIC + 10:
|
||||||
return "fcfb10"
|
return "fcfb10"
|
||||||
case syscall.ARPHRD_FCFABRIC + 11:
|
case unix.ARPHRD_FCFABRIC + 11:
|
||||||
return "fcfb11"
|
return "fcfb11"
|
||||||
case syscall.ARPHRD_FCFABRIC + 12:
|
case unix.ARPHRD_FCFABRIC + 12:
|
||||||
return "fcfb12"
|
return "fcfb12"
|
||||||
case syscall.ARPHRD_IEEE802_TR:
|
case unix.ARPHRD_IEEE802_TR:
|
||||||
return "tr"
|
return "tr"
|
||||||
case syscall.ARPHRD_IEEE80211:
|
case unix.ARPHRD_IEEE80211:
|
||||||
return "ieee802.11"
|
return "ieee802.11"
|
||||||
case syscall.ARPHRD_IEEE80211_PRISM:
|
case unix.ARPHRD_IEEE80211_PRISM:
|
||||||
return "ieee802.11/prism"
|
return "ieee802.11/prism"
|
||||||
case syscall.ARPHRD_IEEE80211_RADIOTAP:
|
case unix.ARPHRD_IEEE80211_RADIOTAP:
|
||||||
return "ieee802.11/radiotap"
|
return "ieee802.11/radiotap"
|
||||||
case syscall.ARPHRD_IEEE802154:
|
case unix.ARPHRD_IEEE802154:
|
||||||
return "ieee802.15.4"
|
return "ieee802.15.4"
|
||||||
|
|
||||||
case 65534:
|
case 65534:
|
||||||
@ -243,7 +248,7 @@ func (msg *IfInfomsg) EncapType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func rtaAlignOf(attrlen int) int {
|
func rtaAlignOf(attrlen int) int {
|
||||||
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
|
return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
||||||
@ -254,7 +259,7 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
|||||||
|
|
||||||
// Extend RtAttr to handle data and children
|
// Extend RtAttr to handle data and children
|
||||||
type RtAttr struct {
|
type RtAttr struct {
|
||||||
syscall.RtAttr
|
unix.RtAttr
|
||||||
Data []byte
|
Data []byte
|
||||||
children []NetlinkRequestData
|
children []NetlinkRequestData
|
||||||
}
|
}
|
||||||
@ -262,7 +267,7 @@ type RtAttr struct {
|
|||||||
// Create a new Extended RtAttr object
|
// Create a new Extended RtAttr object
|
||||||
func NewRtAttr(attrType int, data []byte) *RtAttr {
|
func NewRtAttr(attrType int, data []byte) *RtAttr {
|
||||||
return &RtAttr{
|
return &RtAttr{
|
||||||
RtAttr: syscall.RtAttr{
|
RtAttr: unix.RtAttr{
|
||||||
Type: uint16(attrType),
|
Type: uint16(attrType),
|
||||||
},
|
},
|
||||||
children: []NetlinkRequestData{},
|
children: []NetlinkRequestData{},
|
||||||
@ -270,23 +275,35 @@ 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 {
|
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)
|
attr := NewRtAttr(attrType, data)
|
||||||
parent.children = append(parent.children, attr)
|
a.children = append(a.children, attr)
|
||||||
return attr
|
return attr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddChild adds an existing NetlinkRequestData as a child.
|
||||||
|
func (a *RtAttr) AddChild(attr NetlinkRequestData) {
|
||||||
|
a.children = append(a.children, attr)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *RtAttr) Len() int {
|
func (a *RtAttr) Len() int {
|
||||||
if len(a.children) == 0 {
|
if len(a.children) == 0 {
|
||||||
return (syscall.SizeofRtAttr + len(a.Data))
|
return (unix.SizeofRtAttr + len(a.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
l := 0
|
l := 0
|
||||||
for _, child := range a.children {
|
for _, child := range a.children {
|
||||||
l += rtaAlignOf(child.Len())
|
l += rtaAlignOf(child.Len())
|
||||||
}
|
}
|
||||||
l += syscall.SizeofRtAttr
|
l += unix.SizeofRtAttr
|
||||||
return rtaAlignOf(l + len(a.Data))
|
return rtaAlignOf(l + len(a.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +336,7 @@ func (a *RtAttr) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NetlinkRequest struct {
|
type NetlinkRequest struct {
|
||||||
syscall.NlMsghdr
|
unix.NlMsghdr
|
||||||
Data []NetlinkRequestData
|
Data []NetlinkRequestData
|
||||||
RawData []byte
|
RawData []byte
|
||||||
Sockets map[int]*SocketHandle
|
Sockets map[int]*SocketHandle
|
||||||
@ -327,7 +344,7 @@ type NetlinkRequest struct {
|
|||||||
|
|
||||||
// Serialize the Netlink Request into a byte array
|
// Serialize the Netlink Request into a byte array
|
||||||
func (req *NetlinkRequest) Serialize() []byte {
|
func (req *NetlinkRequest) Serialize() []byte {
|
||||||
length := syscall.SizeofNlMsghdr
|
length := unix.SizeofNlMsghdr
|
||||||
dataBytes := make([][]byte, len(req.Data))
|
dataBytes := make([][]byte, len(req.Data))
|
||||||
for i, data := range req.Data {
|
for i, data := range req.Data {
|
||||||
dataBytes[i] = data.Serialize()
|
dataBytes[i] = data.Serialize()
|
||||||
@ -337,8 +354,8 @@ func (req *NetlinkRequest) Serialize() []byte {
|
|||||||
|
|
||||||
req.Len = uint32(length)
|
req.Len = uint32(length)
|
||||||
b := make([]byte, length)
|
b := make([]byte, length)
|
||||||
hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
|
hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
|
||||||
next := syscall.SizeofNlMsghdr
|
next := unix.SizeofNlMsghdr
|
||||||
copy(b[0:next], hdr)
|
copy(b[0:next], hdr)
|
||||||
for _, data := range dataBytes {
|
for _, data := range dataBytes {
|
||||||
for _, dataByte := range data {
|
for _, dataByte := range data {
|
||||||
@ -354,16 +371,12 @@ func (req *NetlinkRequest) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
|
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
|
// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization
|
||||||
func (req *NetlinkRequest) AddRawData(data []byte) {
|
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.
|
// Execute the request against a the given sockType.
|
||||||
@ -421,10 +434,10 @@ done:
|
|||||||
if m.Header.Pid != pid {
|
if m.Header.Pid != pid {
|
||||||
return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
|
return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
|
||||||
}
|
}
|
||||||
if m.Header.Type == syscall.NLMSG_DONE {
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
break done
|
break done
|
||||||
}
|
}
|
||||||
if m.Header.Type == syscall.NLMSG_ERROR {
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
native := NativeEndian()
|
native := NativeEndian()
|
||||||
error := int32(native.Uint32(m.Data[0:4]))
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
@ -436,7 +449,7 @@ done:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
res = append(res, m.Data)
|
res = append(res, m.Data)
|
||||||
if m.Header.Flags&syscall.NLM_F_MULTI == 0 {
|
if m.Header.Flags&unix.NLM_F_MULTI == 0 {
|
||||||
break done
|
break done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,10 +462,10 @@ done:
|
|||||||
// the message is serialized
|
// the message is serialized
|
||||||
func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
|
func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
|
||||||
return &NetlinkRequest{
|
return &NetlinkRequest{
|
||||||
NlMsghdr: syscall.NlMsghdr{
|
NlMsghdr: unix.NlMsghdr{
|
||||||
Len: uint32(syscall.SizeofNlMsghdr),
|
Len: uint32(unix.SizeofNlMsghdr),
|
||||||
Type: uint16(proto),
|
Type: uint16(proto),
|
||||||
Flags: syscall.NLM_F_REQUEST | uint16(flags),
|
Flags: unix.NLM_F_REQUEST | uint16(flags),
|
||||||
Seq: atomic.AddUint32(&nextSeqNr, 1),
|
Seq: atomic.AddUint32(&nextSeqNr, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -460,21 +473,21 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
|
|||||||
|
|
||||||
type NetlinkSocket struct {
|
type NetlinkSocket struct {
|
||||||
fd int32
|
fd int32
|
||||||
lsa syscall.SockaddrNetlink
|
lsa unix.SockaddrNetlink
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
|
func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
|
||||||
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, protocol)
|
fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s := &NetlinkSocket{
|
s := &NetlinkSocket{
|
||||||
fd: int32(fd),
|
fd: int32(fd),
|
||||||
}
|
}
|
||||||
s.lsa.Family = syscall.AF_NETLINK
|
s.lsa.Family = unix.AF_NETLINK
|
||||||
if err := syscall.Bind(fd, &s.lsa); err != nil {
|
if err := unix.Bind(fd, &s.lsa); err != nil {
|
||||||
syscall.Close(fd)
|
unix.Close(fd)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,21 +564,21 @@ func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
|
|||||||
// Returns the netlink socket on which Receive() method can be called
|
// Returns the netlink socket on which Receive() method can be called
|
||||||
// to retrieve the messages from the kernel.
|
// to retrieve the messages from the kernel.
|
||||||
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
||||||
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
|
fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s := &NetlinkSocket{
|
s := &NetlinkSocket{
|
||||||
fd: int32(fd),
|
fd: int32(fd),
|
||||||
}
|
}
|
||||||
s.lsa.Family = syscall.AF_NETLINK
|
s.lsa.Family = unix.AF_NETLINK
|
||||||
|
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
s.lsa.Groups |= (1 << (g - 1))
|
s.lsa.Groups |= (1 << (g - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Bind(fd, &s.lsa); err != nil {
|
if err := unix.Bind(fd, &s.lsa); err != nil {
|
||||||
syscall.Close(fd)
|
unix.Close(fd)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +599,7 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
|
|||||||
|
|
||||||
func (s *NetlinkSocket) Close() {
|
func (s *NetlinkSocket) Close() {
|
||||||
fd := int(atomic.SwapInt32(&s.fd, -1))
|
fd := int(atomic.SwapInt32(&s.fd, -1))
|
||||||
syscall.Close(fd)
|
unix.Close(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NetlinkSocket) GetFd() int {
|
func (s *NetlinkSocket) GetFd() int {
|
||||||
@ -598,7 +611,7 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
|
|||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return fmt.Errorf("Send called on a closed socket")
|
return fmt.Errorf("Send called on a closed socket")
|
||||||
}
|
}
|
||||||
if err := syscall.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
|
if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -609,26 +622,40 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
|
|||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil, fmt.Errorf("Receive called on a closed socket")
|
return nil, fmt.Errorf("Receive called on a closed socket")
|
||||||
}
|
}
|
||||||
rb := make([]byte, syscall.Getpagesize())
|
rb := make([]byte, RECEIVE_BUFFER_SIZE)
|
||||||
nr, _, err := syscall.Recvfrom(fd, rb, 0)
|
nr, _, err := unix.Recvfrom(fd, rb, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if nr < syscall.NLMSG_HDRLEN {
|
if nr < unix.NLMSG_HDRLEN {
|
||||||
return nil, fmt.Errorf("Got short response from netlink")
|
return nil, fmt.Errorf("Got short response from netlink")
|
||||||
}
|
}
|
||||||
rb = rb[:nr]
|
rb = rb[:nr]
|
||||||
return syscall.ParseNetlinkMessage(rb)
|
return syscall.ParseNetlinkMessage(rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSendTimeout allows to set a send timeout on the socket
|
||||||
|
func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error {
|
||||||
|
// Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine
|
||||||
|
// remains stuck on a send on a closed fd
|
||||||
|
return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReceiveTimeout allows to set a receive timeout on the socket
|
||||||
|
func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
|
||||||
|
// Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine
|
||||||
|
// remains stuck on a recvmsg on a closed fd
|
||||||
|
return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *NetlinkSocket) GetPid() (uint32, error) {
|
func (s *NetlinkSocket) GetPid() (uint32, error) {
|
||||||
fd := int(atomic.LoadInt32(&s.fd))
|
fd := int(atomic.LoadInt32(&s.fd))
|
||||||
lsa, err := syscall.Getsockname(fd)
|
lsa, err := unix.Getsockname(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
switch v := lsa.(type) {
|
switch v := lsa.(type) {
|
||||||
case *syscall.SockaddrNetlink:
|
case *unix.SockaddrNetlink:
|
||||||
return v.Pid, nil
|
return v.Pid, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("Wrong socket type")
|
return 0, fmt.Errorf("Wrong socket type")
|
||||||
@ -683,24 +710,24 @@ func Uint64Attr(v uint64) []byte {
|
|||||||
|
|
||||||
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
||||||
var attrs []syscall.NetlinkRouteAttr
|
var attrs []syscall.NetlinkRouteAttr
|
||||||
for len(b) >= syscall.SizeofRtAttr {
|
for len(b) >= unix.SizeofRtAttr {
|
||||||
a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
|
a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ra := syscall.NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
|
ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]}
|
||||||
attrs = append(attrs, ra)
|
attrs = append(attrs, ra)
|
||||||
b = b[alen:]
|
b = b[alen:]
|
||||||
}
|
}
|
||||||
return attrs, nil
|
return attrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
|
func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
|
||||||
a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
|
a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
|
||||||
if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
|
if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {
|
||||||
return nil, nil, 0, syscall.EINVAL
|
return nil, nil, 0, unix.EINVAL
|
||||||
}
|
}
|
||||||
return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
|
return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SocketHandle contains the netlink socket and the associated
|
// SocketHandle contains the netlink socket and the associated
|
||||||
|
31
vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
generated
vendored
Normal file
31
vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
65
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
65
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
@ -1,65 +1,66 @@
|
|||||||
package nl
|
package nl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RtMsg struct {
|
type RtMsg struct {
|
||||||
syscall.RtMsg
|
unix.RtMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRtMsg() *RtMsg {
|
func NewRtMsg() *RtMsg {
|
||||||
return &RtMsg{
|
return &RtMsg{
|
||||||
RtMsg: syscall.RtMsg{
|
RtMsg: unix.RtMsg{
|
||||||
Table: syscall.RT_TABLE_MAIN,
|
Table: unix.RT_TABLE_MAIN,
|
||||||
Scope: syscall.RT_SCOPE_UNIVERSE,
|
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||||
Protocol: syscall.RTPROT_BOOT,
|
Protocol: unix.RTPROT_BOOT,
|
||||||
Type: syscall.RTN_UNICAST,
|
Type: unix.RTN_UNICAST,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRtDelMsg() *RtMsg {
|
func NewRtDelMsg() *RtMsg {
|
||||||
return &RtMsg{
|
return &RtMsg{
|
||||||
RtMsg: syscall.RtMsg{
|
RtMsg: unix.RtMsg{
|
||||||
Table: syscall.RT_TABLE_MAIN,
|
Table: unix.RT_TABLE_MAIN,
|
||||||
Scope: syscall.RT_SCOPE_NOWHERE,
|
Scope: unix.RT_SCOPE_NOWHERE,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *RtMsg) Len() int {
|
func (msg *RtMsg) Len() int {
|
||||||
return syscall.SizeofRtMsg
|
return unix.SizeofRtMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeserializeRtMsg(b []byte) *RtMsg {
|
func DeserializeRtMsg(b []byte) *RtMsg {
|
||||||
return (*RtMsg)(unsafe.Pointer(&b[0:syscall.SizeofRtMsg][0]))
|
return (*RtMsg)(unsafe.Pointer(&b[0:unix.SizeofRtMsg][0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *RtMsg) Serialize() []byte {
|
func (msg *RtMsg) Serialize() []byte {
|
||||||
return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
|
return (*(*[unix.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
type RtNexthop struct {
|
type RtNexthop struct {
|
||||||
syscall.RtNexthop
|
unix.RtNexthop
|
||||||
Children []NetlinkRequestData
|
Children []NetlinkRequestData
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeserializeRtNexthop(b []byte) *RtNexthop {
|
func DeserializeRtNexthop(b []byte) *RtNexthop {
|
||||||
return (*RtNexthop)(unsafe.Pointer(&b[0:syscall.SizeofRtNexthop][0]))
|
return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *RtNexthop) Len() int {
|
func (msg *RtNexthop) Len() int {
|
||||||
if len(msg.Children) == 0 {
|
if len(msg.Children) == 0 {
|
||||||
return syscall.SizeofRtNexthop
|
return unix.SizeofRtNexthop
|
||||||
}
|
}
|
||||||
|
|
||||||
l := 0
|
l := 0
|
||||||
for _, child := range msg.Children {
|
for _, child := range msg.Children {
|
||||||
l += rtaAlignOf(child.Len())
|
l += rtaAlignOf(child.Len())
|
||||||
}
|
}
|
||||||
l += syscall.SizeofRtNexthop
|
l += unix.SizeofRtNexthop
|
||||||
return rtaAlignOf(l)
|
return rtaAlignOf(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +68,8 @@ func (msg *RtNexthop) Serialize() []byte {
|
|||||||
length := msg.Len()
|
length := msg.Len()
|
||||||
msg.RtNexthop.Len = uint16(length)
|
msg.RtNexthop.Len = uint16(length)
|
||||||
buf := make([]byte, length)
|
buf := make([]byte, length)
|
||||||
copy(buf, (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:])
|
copy(buf, (*(*[unix.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:])
|
||||||
next := rtaAlignOf(syscall.SizeofRtNexthop)
|
next := rtaAlignOf(unix.SizeofRtNexthop)
|
||||||
if len(msg.Children) > 0 {
|
if len(msg.Children) > 0 {
|
||||||
for _, child := range msg.Children {
|
for _, child := range msg.Children {
|
||||||
childBuf := child.Serialize()
|
childBuf := child.Serialize()
|
||||||
@ -78,3 +79,29 @@ func (msg *RtNexthop) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
return buf
|
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
|
||||||
|
}
|
||||||
|
154
vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
generated
vendored
Normal file
154
vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package nl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPv6SrHdr struct {
|
||||||
|
nextHdr uint8
|
||||||
|
hdrLen uint8
|
||||||
|
routingType uint8
|
||||||
|
segmentsLeft uint8
|
||||||
|
firstSegment uint8
|
||||||
|
flags uint8
|
||||||
|
reserved uint16
|
||||||
|
|
||||||
|
Segments []net.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool {
|
||||||
|
if len(s1.Segments) != len(s2.Segments) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range s1.Segments {
|
||||||
|
if s1.Segments[i].Equal(s2.Segments[i]) != true {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s1.nextHdr == s2.nextHdr &&
|
||||||
|
s1.hdrLen == s2.hdrLen &&
|
||||||
|
s1.routingType == s2.routingType &&
|
||||||
|
s1.segmentsLeft == s2.segmentsLeft &&
|
||||||
|
s1.firstSegment == s2.firstSegment &&
|
||||||
|
s1.flags == s2.flags
|
||||||
|
// reserved doesn't need to be identical.
|
||||||
|
}
|
||||||
|
|
||||||
|
// seg6 encap mode
|
||||||
|
const (
|
||||||
|
SEG6_IPTUN_MODE_INLINE = iota
|
||||||
|
SEG6_IPTUN_MODE_ENCAP
|
||||||
|
)
|
||||||
|
|
||||||
|
// number of nested RTATTR
|
||||||
|
// from include/uapi/linux/seg6_iptunnel.h
|
||||||
|
const (
|
||||||
|
SEG6_IPTUNNEL_UNSPEC = iota
|
||||||
|
SEG6_IPTUNNEL_SRH
|
||||||
|
__SEG6_IPTUNNEL_MAX
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) {
|
||||||
|
nsegs := len(segments) // nsegs: number of segments
|
||||||
|
if nsegs == 0 {
|
||||||
|
return nil, errors.New("EncodeSEG6Encap: No Segment in srh")
|
||||||
|
}
|
||||||
|
b := make([]byte, 12, 12+len(segments)*16)
|
||||||
|
native := NativeEndian()
|
||||||
|
native.PutUint32(b, uint32(mode))
|
||||||
|
b[4] = 0 // srh.nextHdr (0 when calling netlink)
|
||||||
|
b[5] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit)
|
||||||
|
b[6] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA)
|
||||||
|
b[7] = uint8(nsegs - 1) // srh.segmentsLeft
|
||||||
|
b[8] = uint8(nsegs - 1) // srh.firstSegment
|
||||||
|
b[9] = 0 // srh.flags (SR6_FLAG1_HMAC for srh_hmac)
|
||||||
|
// srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07
|
||||||
|
native.PutUint16(b[10:], 0) // srh.reserved
|
||||||
|
for _, netIP := range segments {
|
||||||
|
b = append(b, netIP...) // srh.Segments
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
|
||||||
|
native := NativeEndian()
|
||||||
|
mode := int(native.Uint32(buf))
|
||||||
|
srh := IPv6SrHdr{
|
||||||
|
nextHdr: buf[4],
|
||||||
|
hdrLen: buf[5],
|
||||||
|
routingType: buf[6],
|
||||||
|
segmentsLeft: buf[7],
|
||||||
|
firstSegment: buf[8],
|
||||||
|
flags: buf[9],
|
||||||
|
reserved: native.Uint16(buf[10:12]),
|
||||||
|
}
|
||||||
|
buf = buf[12:]
|
||||||
|
if len(buf)%16 != 0 {
|
||||||
|
err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf))
|
||||||
|
return mode, nil, err
|
||||||
|
}
|
||||||
|
for len(buf) > 0 {
|
||||||
|
srh.Segments = append(srh.Segments, net.IP(buf[:16]))
|
||||||
|
buf = buf[16:]
|
||||||
|
}
|
||||||
|
return mode, srh.Segments, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
case SEG6_IPTUN_MODE_INLINE:
|
||||||
|
return "inline"
|
||||||
|
case SEG6_IPTUN_MODE_ENCAP:
|
||||||
|
return "encap"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
76
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
Normal file
76
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
Normal file
@ -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"
|
||||||
|
}
|
11
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
11
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
@ -65,4 +65,15 @@ const (
|
|||||||
LWTUNNEL_ENCAP_IP
|
LWTUNNEL_ENCAP_IP
|
||||||
LWTUNNEL_ENCAP_ILA
|
LWTUNNEL_ENCAP_ILA
|
||||||
LWTUNNEL_ENCAP_IP6
|
LWTUNNEL_ENCAP_IP6
|
||||||
|
LWTUNNEL_ENCAP_SEG6
|
||||||
|
LWTUNNEL_ENCAP_BPF
|
||||||
|
LWTUNNEL_ENCAP_SEG6_LOCAL
|
||||||
|
)
|
||||||
|
|
||||||
|
// routing header types
|
||||||
|
const (
|
||||||
|
IPV6_SRCRT_STRICT = 0x01 // Deprecated; will be removed
|
||||||
|
IPV6_SRCRT_TYPE_0 = 0 // Deprecated; will be removed
|
||||||
|
IPV6_SRCRT_TYPE_2 = 2 // IPv6 type 2 Routing Header
|
||||||
|
IPV6_SRCRT_TYPE_4 = 4 // Segment Routing with IPv6
|
||||||
)
|
)
|
||||||
|
103
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
103
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package nl
|
package nl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,6 +65,15 @@ const (
|
|||||||
TCA_PRIO_MAX = TCA_PRIO_MQ
|
TCA_PRIO_MAX = TCA_PRIO_MQ
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 (
|
const (
|
||||||
SizeofTcMsg = 0x14
|
SizeofTcMsg = 0x14
|
||||||
SizeofTcActionMsg = 0x04
|
SizeofTcActionMsg = 0x04
|
||||||
@ -412,6 +422,57 @@ func (x *TcHtbGlob) Serialize() []byte {
|
|||||||
return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:]
|
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 (
|
const (
|
||||||
TCA_U32_UNSPEC = iota
|
TCA_U32_UNSPEC = iota
|
||||||
TCA_U32_CLASSID
|
TCA_U32_CLASSID
|
||||||
@ -673,3 +734,45 @@ const (
|
|||||||
TCA_FW_MASK
|
TCA_FW_MASK
|
||||||
TCA_FW_MAX = TCA_FW_MASK
|
TCA_FW_MAX = TCA_FW_MASK
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_MATCHALL_UNSPEC = iota
|
||||||
|
TCA_MATCHALL_CLASSID
|
||||||
|
TCA_MATCHALL_ACT
|
||||||
|
TCA_MATCHALL_FLAGS
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_FQ_UNSPEC = iota
|
||||||
|
TCA_FQ_PLIMIT // limit of total number of packets in queue
|
||||||
|
TCA_FQ_FLOW_PLIMIT // limit of packets per flow
|
||||||
|
TCA_FQ_QUANTUM // RR quantum
|
||||||
|
TCA_FQ_INITIAL_QUANTUM // RR quantum for new flow
|
||||||
|
TCA_FQ_RATE_ENABLE // enable/disable rate limiting
|
||||||
|
TCA_FQ_FLOW_DEFAULT_RATE // obsolete do not use
|
||||||
|
TCA_FQ_FLOW_MAX_RATE // per flow max rate
|
||||||
|
TCA_FQ_BUCKETS_LOG // log2(number of buckets)
|
||||||
|
TCA_FQ_FLOW_REFILL_DELAY // flow credit refill delay in usec
|
||||||
|
TCA_FQ_ORPHAN_MASK // mask applied to orphaned skb hashes
|
||||||
|
TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_FQ_CODEL_UNSPEC = iota
|
||||||
|
TCA_FQ_CODEL_TARGET
|
||||||
|
TCA_FQ_CODEL_LIMIT
|
||||||
|
TCA_FQ_CODEL_INTERVAL
|
||||||
|
TCA_FQ_CODEL_ECN
|
||||||
|
TCA_FQ_CODEL_FLOWS
|
||||||
|
TCA_FQ_CODEL_QUANTUM
|
||||||
|
TCA_FQ_CODEL_CE_THRESHOLD
|
||||||
|
TCA_FQ_CODEL_DROP_BATCH_SIZE
|
||||||
|
TCA_FQ_CODEL_MEMORY_LIMIT
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_HFSC_UNSPEC = iota
|
||||||
|
TCA_HFSC_RSC
|
||||||
|
TCA_HFSC_FSC
|
||||||
|
TCA_HFSC_USC
|
||||||
|
)
|
||||||
|
4
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
@ -18,6 +18,10 @@ type Protinfo struct {
|
|||||||
|
|
||||||
// String returns a list of enabled flags
|
// String returns a list of enabled flags
|
||||||
func (prot *Protinfo) String() string {
|
func (prot *Protinfo) String() string {
|
||||||
|
if prot == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
|
||||||
var boolStrings []string
|
var boolStrings []string
|
||||||
if prot.Hairpin {
|
if prot.Hairpin {
|
||||||
boolStrings = append(boolStrings, "Hairpin")
|
boolStrings = append(boolStrings, "Hairpin")
|
||||||
|
16
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
16
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LinkGetProtinfo(link Link) (Protinfo, error) {
|
func LinkGetProtinfo(link Link) (Protinfo, error) {
|
||||||
@ -15,10 +16,10 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
|||||||
base := link.Attrs()
|
base := link.Attrs()
|
||||||
h.ensureIndex(base)
|
h.ensureIndex(base)
|
||||||
var pi Protinfo
|
var pi Protinfo
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
|
||||||
msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pi, err
|
return pi, err
|
||||||
}
|
}
|
||||||
@ -33,14 +34,14 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
|||||||
return pi, err
|
return pi, err
|
||||||
}
|
}
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED {
|
if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
infos, err := nl.ParseRouteAttr(attr.Value)
|
infos, err := nl.ParseRouteAttr(attr.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pi, err
|
return pi, err
|
||||||
}
|
}
|
||||||
pi = *parseProtinfo(infos)
|
pi = parseProtinfo(infos)
|
||||||
|
|
||||||
return pi, nil
|
return pi, nil
|
||||||
}
|
}
|
||||||
@ -48,8 +49,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
|||||||
return pi, fmt.Errorf("Device with index %d not found", base.Index)
|
return pi, fmt.Errorf("Device with index %d not found", base.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
|
func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
|
||||||
var pi Protinfo
|
|
||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
switch info.Attr.Type {
|
switch info.Attr.Type {
|
||||||
case nl.IFLA_BRPORT_MODE:
|
case nl.IFLA_BRPORT_MODE:
|
||||||
@ -70,5 +70,5 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
|
|||||||
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &pi
|
return
|
||||||
}
|
}
|
||||||
|
108
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
108
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
@ -176,6 +176,13 @@ type Netem struct {
|
|||||||
CorruptCorr uint32
|
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 {
|
func (qdisc *Netem) Attrs() *QdiscAttrs {
|
||||||
return &qdisc.QdiscAttrs
|
return &qdisc.QdiscAttrs
|
||||||
}
|
}
|
||||||
@ -230,3 +237,104 @@ func (qdisc *GenericQdisc) Attrs() *QdiscAttrs {
|
|||||||
func (qdisc *GenericQdisc) Type() string {
|
func (qdisc *GenericQdisc) Type() string {
|
||||||
return qdisc.QdiscType
|
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
|
||||||
|
PacketLimit uint32
|
||||||
|
FlowPacketLimit uint32
|
||||||
|
// In bytes
|
||||||
|
Quantum uint32
|
||||||
|
InitialQuantum uint32
|
||||||
|
// called RateEnable under the hood
|
||||||
|
Pacing uint32
|
||||||
|
FlowDefaultRate uint32
|
||||||
|
FlowMaxRate uint32
|
||||||
|
// called BucketsLog under the hood
|
||||||
|
Buckets uint32
|
||||||
|
FlowRefillDelay uint32
|
||||||
|
LowRateThreshold uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fq *Fq) String() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitalQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateTreshold: %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,
|
||||||
|
Pacing: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qdisc *Fq) Attrs() *QdiscAttrs {
|
||||||
|
return &qdisc.QdiscAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qdisc *Fq) Type() string {
|
||||||
|
return "fq"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme.
|
||||||
|
type FqCodel struct {
|
||||||
|
QdiscAttrs
|
||||||
|
Target uint32
|
||||||
|
Limit uint32
|
||||||
|
Interval uint32
|
||||||
|
ECN uint32
|
||||||
|
Flows uint32
|
||||||
|
Quantum uint32
|
||||||
|
// There are some more attributes here, but support for them seems not ubiquitous
|
||||||
|
}
|
||||||
|
|
||||||
|
func (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,
|
||||||
|
ECN: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qdisc *FqCodel) Attrs() *QdiscAttrs {
|
||||||
|
return &qdisc.QdiscAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qdisc *FqCodel) Type() string {
|
||||||
|
return "fq_codel"
|
||||||
|
}
|
||||||
|
247
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
247
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE function is here because it uses other linux functions
|
// NOTE function is here because it uses other linux functions
|
||||||
@ -84,7 +85,7 @@ func QdiscDel(qdisc Qdisc) error {
|
|||||||
// QdiscDel will delete a qdisc from the system.
|
// QdiscDel will delete a qdisc from the system.
|
||||||
// Equivalent to: `tc qdisc del $qdisc`
|
// Equivalent to: `tc qdisc del $qdisc`
|
||||||
func (h *Handle) QdiscDel(qdisc Qdisc) error {
|
func (h *Handle) QdiscDel(qdisc Qdisc) error {
|
||||||
return h.qdiscModify(syscall.RTM_DELQDISC, 0, qdisc)
|
return h.qdiscModify(unix.RTM_DELQDISC, 0, qdisc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QdiscChange will change a qdisc in place
|
// QdiscChange will change a qdisc in place
|
||||||
@ -98,7 +99,7 @@ func QdiscChange(qdisc Qdisc) error {
|
|||||||
// Equivalent to: `tc qdisc change $qdisc`
|
// Equivalent to: `tc qdisc change $qdisc`
|
||||||
// The parent and handle MUST NOT be changed.
|
// The parent and handle MUST NOT be changed.
|
||||||
func (h *Handle) QdiscChange(qdisc Qdisc) error {
|
func (h *Handle) QdiscChange(qdisc Qdisc) error {
|
||||||
return h.qdiscModify(syscall.RTM_NEWQDISC, 0, qdisc)
|
return h.qdiscModify(unix.RTM_NEWQDISC, 0, qdisc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QdiscReplace will replace a qdisc to the system.
|
// QdiscReplace will replace a qdisc to the system.
|
||||||
@ -113,8 +114,8 @@ func QdiscReplace(qdisc Qdisc) error {
|
|||||||
// The handle MUST change.
|
// The handle MUST change.
|
||||||
func (h *Handle) QdiscReplace(qdisc Qdisc) error {
|
func (h *Handle) QdiscReplace(qdisc Qdisc) error {
|
||||||
return h.qdiscModify(
|
return h.qdiscModify(
|
||||||
syscall.RTM_NEWQDISC,
|
unix.RTM_NEWQDISC,
|
||||||
syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE,
|
unix.NLM_F_CREATE|unix.NLM_F_REPLACE,
|
||||||
qdisc)
|
qdisc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,13 +129,13 @@ func QdiscAdd(qdisc Qdisc) error {
|
|||||||
// Equivalent to: `tc qdisc add $qdisc`
|
// Equivalent to: `tc qdisc add $qdisc`
|
||||||
func (h *Handle) QdiscAdd(qdisc Qdisc) error {
|
func (h *Handle) QdiscAdd(qdisc Qdisc) error {
|
||||||
return h.qdiscModify(
|
return h.qdiscModify(
|
||||||
syscall.RTM_NEWQDISC,
|
unix.RTM_NEWQDISC,
|
||||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
|
unix.NLM_F_CREATE|unix.NLM_F_EXCL,
|
||||||
qdisc)
|
qdisc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
||||||
req := h.newNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
|
||||||
base := qdisc.Attrs()
|
base := qdisc.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
@ -145,13 +146,13 @@ func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
|||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
// When deleting don't bother building the rest of the netlink payload
|
// When deleting don't bother building the rest of the netlink payload
|
||||||
if cmd != syscall.RTM_DELQDISC {
|
if cmd != unix.RTM_DELQDISC {
|
||||||
if err := qdiscPayload(req, qdisc); err != nil {
|
if err := qdiscPayload(req, qdisc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,78 +161,130 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
||||||
|
|
||||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||||
if prio, ok := qdisc.(*Prio); ok {
|
|
||||||
|
switch qdisc := qdisc.(type) {
|
||||||
|
case *Prio:
|
||||||
tcmap := nl.TcPrioMap{
|
tcmap := nl.TcPrioMap{
|
||||||
Bands: int32(prio.Bands),
|
Bands: int32(qdisc.Bands),
|
||||||
Priomap: prio.PriorityMap,
|
Priomap: qdisc.PriorityMap,
|
||||||
}
|
}
|
||||||
options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize())
|
options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize())
|
||||||
} else if tbf, ok := qdisc.(*Tbf); ok {
|
case *Tbf:
|
||||||
opt := nl.TcTbfQopt{}
|
opt := nl.TcTbfQopt{}
|
||||||
opt.Rate.Rate = uint32(tbf.Rate)
|
opt.Rate.Rate = uint32(qdisc.Rate)
|
||||||
opt.Peakrate.Rate = uint32(tbf.Peakrate)
|
opt.Peakrate.Rate = uint32(qdisc.Peakrate)
|
||||||
opt.Limit = tbf.Limit
|
opt.Limit = qdisc.Limit
|
||||||
opt.Buffer = tbf.Buffer
|
opt.Buffer = qdisc.Buffer
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize())
|
options.AddRtAttr(nl.TCA_TBF_PARMS, opt.Serialize())
|
||||||
if tbf.Rate >= uint64(1<<32) {
|
if qdisc.Rate >= uint64(1<<32) {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(tbf.Rate))
|
options.AddRtAttr(nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate))
|
||||||
}
|
}
|
||||||
if tbf.Peakrate >= uint64(1<<32) {
|
if qdisc.Peakrate >= uint64(1<<32) {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PRATE64, nl.Uint64Attr(tbf.Peakrate))
|
options.AddRtAttr(nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate))
|
||||||
}
|
}
|
||||||
if tbf.Peakrate > 0 {
|
if qdisc.Peakrate > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PBURST, nl.Uint32Attr(tbf.Minburst))
|
options.AddRtAttr(nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst))
|
||||||
}
|
}
|
||||||
} else if htb, ok := qdisc.(*Htb); ok {
|
case *Htb:
|
||||||
opt := nl.TcHtbGlob{}
|
opt := nl.TcHtbGlob{}
|
||||||
opt.Version = htb.Version
|
opt.Version = qdisc.Version
|
||||||
opt.Rate2Quantum = htb.Rate2Quantum
|
opt.Rate2Quantum = qdisc.Rate2Quantum
|
||||||
opt.Defcls = htb.Defcls
|
opt.Defcls = qdisc.Defcls
|
||||||
// TODO: Handle Debug properly. For now default to 0
|
// TODO: Handle Debug properly. For now default to 0
|
||||||
opt.Debug = htb.Debug
|
opt.Debug = qdisc.Debug
|
||||||
opt.DirectPkts = htb.DirectPkts
|
opt.DirectPkts = qdisc.DirectPkts
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize())
|
options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize())
|
||||||
// nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
|
// options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
|
||||||
} else if netem, ok := qdisc.(*Netem); ok {
|
case *Hfsc:
|
||||||
|
opt := nl.TcHfscOpt{}
|
||||||
|
opt.Defcls = qdisc.Defcls
|
||||||
|
options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
|
||||||
|
case *Netem:
|
||||||
opt := nl.TcNetemQopt{}
|
opt := nl.TcNetemQopt{}
|
||||||
opt.Latency = netem.Latency
|
opt.Latency = qdisc.Latency
|
||||||
opt.Limit = netem.Limit
|
opt.Limit = qdisc.Limit
|
||||||
opt.Loss = netem.Loss
|
opt.Loss = qdisc.Loss
|
||||||
opt.Gap = netem.Gap
|
opt.Gap = qdisc.Gap
|
||||||
opt.Duplicate = netem.Duplicate
|
opt.Duplicate = qdisc.Duplicate
|
||||||
opt.Jitter = netem.Jitter
|
opt.Jitter = qdisc.Jitter
|
||||||
options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
|
options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
|
||||||
// Correlation
|
// Correlation
|
||||||
corr := nl.TcNetemCorr{}
|
corr := nl.TcNetemCorr{}
|
||||||
corr.DelayCorr = netem.DelayCorr
|
corr.DelayCorr = qdisc.DelayCorr
|
||||||
corr.LossCorr = netem.LossCorr
|
corr.LossCorr = qdisc.LossCorr
|
||||||
corr.DupCorr = netem.DuplicateCorr
|
corr.DupCorr = qdisc.DuplicateCorr
|
||||||
|
|
||||||
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
|
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
|
||||||
corruption := nl.TcNetemCorrupt{}
|
corruption := nl.TcNetemCorrupt{}
|
||||||
corruption.Probability = netem.CorruptProb
|
corruption.Probability = qdisc.CorruptProb
|
||||||
corruption.Correlation = netem.CorruptCorr
|
corruption.Correlation = qdisc.CorruptCorr
|
||||||
if corruption.Probability > 0 {
|
if corruption.Probability > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize())
|
options.AddRtAttr(nl.TCA_NETEM_CORRUPT, corruption.Serialize())
|
||||||
}
|
}
|
||||||
// Reorder
|
// Reorder
|
||||||
reorder := nl.TcNetemReorder{}
|
reorder := nl.TcNetemReorder{}
|
||||||
reorder.Probability = netem.ReorderProb
|
reorder.Probability = qdisc.ReorderProb
|
||||||
reorder.Correlation = netem.ReorderCorr
|
reorder.Correlation = qdisc.ReorderCorr
|
||||||
if reorder.Probability > 0 {
|
if reorder.Probability > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize())
|
options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
|
||||||
}
|
}
|
||||||
} else if _, ok := qdisc.(*Ingress); ok {
|
case *Ingress:
|
||||||
// ingress filters must use the proper handle
|
// ingress filters must use the proper handle
|
||||||
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
||||||
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
||||||
}
|
}
|
||||||
|
case *FqCodel:
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN))))
|
||||||
|
if qdisc.Limit > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit))))
|
||||||
|
}
|
||||||
|
if qdisc.Interval > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval))))
|
||||||
|
}
|
||||||
|
if qdisc.Flows > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows))))
|
||||||
|
}
|
||||||
|
if qdisc.Quantum > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
||||||
|
}
|
||||||
|
|
||||||
|
case *Fq:
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
|
||||||
|
|
||||||
|
if qdisc.Buckets > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
|
||||||
|
}
|
||||||
|
if qdisc.LowRateThreshold > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
|
||||||
|
}
|
||||||
|
if qdisc.Quantum > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
||||||
|
}
|
||||||
|
if qdisc.InitialQuantum > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum))))
|
||||||
|
}
|
||||||
|
if qdisc.FlowRefillDelay > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay))))
|
||||||
|
}
|
||||||
|
if qdisc.FlowPacketLimit > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit))))
|
||||||
|
}
|
||||||
|
if qdisc.FlowMaxRate > 0 {
|
||||||
|
options.AddRtAttr(nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate))))
|
||||||
|
}
|
||||||
|
if qdisc.FlowDefaultRate > 0 {
|
||||||
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +299,7 @@ func QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
// Equivalent to: `tc qdisc show`.
|
// Equivalent to: `tc qdisc show`.
|
||||||
// The list can be filtered by link.
|
// The list can be filtered by link.
|
||||||
func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETQDISC, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP)
|
||||||
index := int32(0)
|
index := int32(0)
|
||||||
if link != nil {
|
if link != nil {
|
||||||
base := link.Attrs()
|
base := link.Attrs()
|
||||||
@ -259,7 +312,7 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
}
|
}
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWQDISC)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -301,6 +354,12 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
qdisc = &Ingress{}
|
qdisc = &Ingress{}
|
||||||
case "htb":
|
case "htb":
|
||||||
qdisc = &Htb{}
|
qdisc = &Htb{}
|
||||||
|
case "fq":
|
||||||
|
qdisc = &Fq{}
|
||||||
|
case "hfsc":
|
||||||
|
qdisc = &Hfsc{}
|
||||||
|
case "fq_codel":
|
||||||
|
qdisc = &FqCodel{}
|
||||||
case "netem":
|
case "netem":
|
||||||
qdisc = &Netem{}
|
qdisc = &Netem{}
|
||||||
default:
|
default:
|
||||||
@ -326,6 +385,10 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
if err := parseTbfData(qdisc, data); err != nil {
|
if err := parseTbfData(qdisc, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case "hfsc":
|
||||||
|
if err := parseHfscData(qdisc, attr.Value); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
case "htb":
|
case "htb":
|
||||||
data, err := nl.ParseRouteAttr(attr.Value)
|
data, err := nl.ParseRouteAttr(attr.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -334,6 +397,22 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
if err := parseHtbData(qdisc, data); err != nil {
|
if err := parseHtbData(qdisc, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case "fq":
|
||||||
|
data, err := nl.ParseRouteAttr(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := parseFqData(qdisc, data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case "fq_codel":
|
||||||
|
data, err := nl.ParseRouteAttr(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := parseFqCodelData(qdisc, data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
case "netem":
|
case "netem":
|
||||||
if err := parseNetemData(qdisc, attr.Value); err != nil {
|
if err := parseNetemData(qdisc, attr.Value); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -386,6 +465,68 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||||
|
native = nl.NativeEndian()
|
||||||
|
fqCodel := qdisc.(*FqCodel)
|
||||||
|
for _, datum := range data {
|
||||||
|
|
||||||
|
switch datum.Attr.Type {
|
||||||
|
case nl.TCA_FQ_CODEL_TARGET:
|
||||||
|
fqCodel.Target = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_CODEL_LIMIT:
|
||||||
|
fqCodel.Limit = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_CODEL_INTERVAL:
|
||||||
|
fqCodel.Interval = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_CODEL_ECN:
|
||||||
|
fqCodel.ECN = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_CODEL_FLOWS:
|
||||||
|
fqCodel.Flows = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_CODEL_QUANTUM:
|
||||||
|
fqCodel.Quantum = native.Uint32(datum.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func 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)
|
||||||
|
for _, datum := range data {
|
||||||
|
switch datum.Attr.Type {
|
||||||
|
case nl.TCA_FQ_BUCKETS_LOG:
|
||||||
|
fq.Buckets = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_LOW_RATE_THRESHOLD:
|
||||||
|
fq.LowRateThreshold = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_QUANTUM:
|
||||||
|
fq.Quantum = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_RATE_ENABLE:
|
||||||
|
fq.Pacing = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_INITIAL_QUANTUM:
|
||||||
|
fq.InitialQuantum = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_ORPHAN_MASK:
|
||||||
|
// TODO
|
||||||
|
case nl.TCA_FQ_FLOW_REFILL_DELAY:
|
||||||
|
fq.FlowRefillDelay = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_FLOW_PLIMIT:
|
||||||
|
fq.FlowPacketLimit = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_PLIMIT:
|
||||||
|
fq.PacketLimit = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_FLOW_MAX_RATE:
|
||||||
|
fq.FlowMaxRate = native.Uint32(datum.Value)
|
||||||
|
case nl.TCA_FQ_FLOW_DEFAULT_RATE:
|
||||||
|
fq.FlowDefaultRate = native.Uint32(datum.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseNetemData(qdisc Qdisc, value []byte) error {
|
func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||||
netem := qdisc.(*Netem)
|
netem := qdisc.(*Netem)
|
||||||
opt := nl.DeserializeTcNetemQopt(value)
|
opt := nl.DeserializeTcNetemQopt(value)
|
||||||
|
145
vendor/github.com/vishvananda/netlink/rdma_link_linux.go
generated
vendored
Normal file
145
vendor/github.com/vishvananda/netlink/rdma_link_linux.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
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)
|
||||||
|
}
|
66
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
66
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
@ -16,6 +16,7 @@ type Destination interface {
|
|||||||
Decode([]byte) error
|
Decode([]byte) error
|
||||||
Encode() ([]byte, error)
|
Encode() ([]byte, error)
|
||||||
String() string
|
String() string
|
||||||
|
Equal(Destination) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Encap interface {
|
type Encap interface {
|
||||||
@ -23,6 +24,7 @@ type Encap interface {
|
|||||||
Decode([]byte) error
|
Decode([]byte) error
|
||||||
Encode() ([]byte, error)
|
Encode() ([]byte, error)
|
||||||
String() string
|
String() string
|
||||||
|
Equal(Encap) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route represents a netlink route.
|
// Route represents a netlink route.
|
||||||
@ -43,6 +45,9 @@ type Route struct {
|
|||||||
MPLSDst *int
|
MPLSDst *int
|
||||||
NewDst Destination
|
NewDst Destination
|
||||||
Encap Encap
|
Encap Encap
|
||||||
|
MTU int
|
||||||
|
AdvMSS int
|
||||||
|
Hoplimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Route) String() string {
|
func (r Route) String() string {
|
||||||
@ -72,6 +77,26 @@ func (r Route) String() string {
|
|||||||
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r Route) Equal(x Route) bool {
|
||||||
|
return r.LinkIndex == x.LinkIndex &&
|
||||||
|
r.ILinkIndex == x.ILinkIndex &&
|
||||||
|
r.Scope == x.Scope &&
|
||||||
|
ipNetEqual(r.Dst, x.Dst) &&
|
||||||
|
r.Src.Equal(x.Src) &&
|
||||||
|
r.Gw.Equal(x.Gw) &&
|
||||||
|
nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
|
||||||
|
r.Protocol == x.Protocol &&
|
||||||
|
r.Priority == x.Priority &&
|
||||||
|
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))) &&
|
||||||
|
(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Route) SetFlag(flag NextHopFlag) {
|
func (r *Route) SetFlag(flag NextHopFlag) {
|
||||||
r.Flags |= int(flag)
|
r.Flags |= int(flag)
|
||||||
}
|
}
|
||||||
@ -110,7 +135,46 @@ func (n *NexthopInfo) String() string {
|
|||||||
elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
|
elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
|
||||||
}
|
}
|
||||||
elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
|
elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
|
||||||
elems = append(elems, fmt.Sprintf("Gw: %d", n.Gw))
|
elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
|
||||||
elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
|
elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
|
||||||
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n NexthopInfo) Equal(x NexthopInfo) bool {
|
||||||
|
return n.LinkIndex == x.LinkIndex &&
|
||||||
|
n.Hops == x.Hops &&
|
||||||
|
n.Gw.Equal(x.Gw) &&
|
||||||
|
n.Flags == x.Flags &&
|
||||||
|
(n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
|
||||||
|
(n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
|
||||||
|
}
|
||||||
|
|
||||||
|
type nexthopInfoSlice []*NexthopInfo
|
||||||
|
|
||||||
|
func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
|
||||||
|
if len(n) != len(x) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range n {
|
||||||
|
if n[i] == nil || x[i] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !n[i].Equal(*x[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipNetEqual returns true iff both IPNet are equal
|
||||||
|
func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
|
||||||
|
if ipn1 == ipn2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ipn1 == nil || ipn2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
m1, _ := ipn1.Mask.Size()
|
||||||
|
m2, _ := ipn2.Mask.Size()
|
||||||
|
return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
|
||||||
|
}
|
||||||
|
535
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
535
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
@ -8,16 +8,17 @@ import (
|
|||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RtAttr is shared so it is in netlink_linux.go
|
// RtAttr is shared so it is in netlink_linux.go
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE
|
SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE
|
||||||
SCOPE_SITE Scope = syscall.RT_SCOPE_SITE
|
SCOPE_SITE Scope = unix.RT_SCOPE_SITE
|
||||||
SCOPE_LINK Scope = syscall.RT_SCOPE_LINK
|
SCOPE_LINK Scope = unix.RT_SCOPE_LINK
|
||||||
SCOPE_HOST Scope = syscall.RT_SCOPE_HOST
|
SCOPE_HOST Scope = unix.RT_SCOPE_HOST
|
||||||
SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE
|
SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -31,11 +32,12 @@ const (
|
|||||||
RT_FILTER_SRC
|
RT_FILTER_SRC
|
||||||
RT_FILTER_GW
|
RT_FILTER_GW
|
||||||
RT_FILTER_TABLE
|
RT_FILTER_TABLE
|
||||||
|
RT_FILTER_HOPLIMIT
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK
|
FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK
|
||||||
FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
|
FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
|
||||||
)
|
)
|
||||||
|
|
||||||
var testFlags = []flagString{
|
var testFlags = []flagString{
|
||||||
@ -86,6 +88,34 @@ func (d *MPLSDestination) String() string {
|
|||||||
return strings.Join(s, "/")
|
return strings.Join(s, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *MPLSDestination) Equal(x Destination) bool {
|
||||||
|
o, ok := x.(*MPLSDestination)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if d == nil && o == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if d == nil || o == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if d.Labels == nil && o.Labels == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if d.Labels == nil || o.Labels == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(d.Labels) != len(o.Labels) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range d.Labels {
|
||||||
|
if d.Labels[i] != o.Labels[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type MPLSEncap struct {
|
type MPLSEncap struct {
|
||||||
Labels []int
|
Labels []int
|
||||||
}
|
}
|
||||||
@ -96,17 +126,17 @@ func (e *MPLSEncap) Type() int {
|
|||||||
|
|
||||||
func (e *MPLSEncap) Decode(buf []byte) error {
|
func (e *MPLSEncap) Decode(buf []byte) error {
|
||||||
if len(buf) < 4 {
|
if len(buf) < 4 {
|
||||||
return fmt.Errorf("Lack of bytes")
|
return fmt.Errorf("lack of bytes")
|
||||||
}
|
}
|
||||||
native := nl.NativeEndian()
|
native := nl.NativeEndian()
|
||||||
l := native.Uint16(buf)
|
l := native.Uint16(buf)
|
||||||
if len(buf) < int(l) {
|
if len(buf) < int(l) {
|
||||||
return fmt.Errorf("Lack of bytes")
|
return fmt.Errorf("lack of bytes")
|
||||||
}
|
}
|
||||||
buf = buf[:l]
|
buf = buf[:l]
|
||||||
typ := native.Uint16(buf[2:])
|
typ := native.Uint16(buf[2:])
|
||||||
if typ != nl.MPLS_IPTUNNEL_DST {
|
if typ != nl.MPLS_IPTUNNEL_DST {
|
||||||
return fmt.Errorf("Unknown MPLS Encap Type: %d", typ)
|
return fmt.Errorf("unknown MPLS Encap Type: %d", typ)
|
||||||
}
|
}
|
||||||
e.Labels = nl.DecodeMPLSStack(buf[4:])
|
e.Labels = nl.DecodeMPLSStack(buf[4:])
|
||||||
return nil
|
return nil
|
||||||
@ -129,6 +159,290 @@ func (e *MPLSEncap) String() string {
|
|||||||
return strings.Join(s, "/")
|
return strings.Join(s, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *MPLSEncap) Equal(x Encap) bool {
|
||||||
|
o, ok := x.(*MPLSEncap)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e == nil && o == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e == nil || o == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e.Labels == nil && o.Labels == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e.Labels == nil || o.Labels == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(e.Labels) != len(o.Labels) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range e.Labels {
|
||||||
|
if e.Labels[i] != o.Labels[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// SEG6 definitions
|
||||||
|
type SEG6Encap struct {
|
||||||
|
Mode int
|
||||||
|
Segments []net.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SEG6Encap) Type() int {
|
||||||
|
return nl.LWTUNNEL_ENCAP_SEG6
|
||||||
|
}
|
||||||
|
func (e *SEG6Encap) Decode(buf []byte) error {
|
||||||
|
if len(buf) < 4 {
|
||||||
|
return fmt.Errorf("lack of bytes")
|
||||||
|
}
|
||||||
|
native := nl.NativeEndian()
|
||||||
|
// Get Length(l) & Type(typ) : 2 + 2 bytes
|
||||||
|
l := native.Uint16(buf)
|
||||||
|
if len(buf) < int(l) {
|
||||||
|
return fmt.Errorf("lack of bytes")
|
||||||
|
}
|
||||||
|
buf = buf[:l] // make sure buf size upper limit is Length
|
||||||
|
typ := native.Uint16(buf[2:])
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:])
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (e *SEG6Encap) Encode() ([]byte, error) {
|
||||||
|
s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments)
|
||||||
|
native := nl.NativeEndian()
|
||||||
|
hdr := make([]byte, 4)
|
||||||
|
native.PutUint16(hdr, uint16(len(s)+4))
|
||||||
|
native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH)
|
||||||
|
return append(hdr, s...), err
|
||||||
|
}
|
||||||
|
func (e *SEG6Encap) String() string {
|
||||||
|
segs := make([]string, 0, len(e.Segments))
|
||||||
|
// append segment backwards (from n to 0) since seg#0 is the last segment.
|
||||||
|
for i := len(e.Segments); i > 0; i-- {
|
||||||
|
segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
|
||||||
|
}
|
||||||
|
str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode),
|
||||||
|
len(e.Segments), strings.Join(segs, " "))
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
func (e *SEG6Encap) Equal(x Encap) bool {
|
||||||
|
o, ok := x.(*SEG6Encap)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e == o {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e == nil || o == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e.Mode != o.Mode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(e.Segments) != len(o.Segments) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range e.Segments {
|
||||||
|
if !e.Segments[i].Equal(o.Segments[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// SEG6Local 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.
|
// RouteAdd will add a route to the system.
|
||||||
// Equivalent to: `ip route add $route`
|
// Equivalent to: `ip route add $route`
|
||||||
func RouteAdd(route *Route) error {
|
func RouteAdd(route *Route) error {
|
||||||
@ -138,8 +452,8 @@ func RouteAdd(route *Route) error {
|
|||||||
// RouteAdd will add a route to the system.
|
// RouteAdd will add a route to the system.
|
||||||
// Equivalent to: `ip route add $route`
|
// Equivalent to: `ip route add $route`
|
||||||
func (h *Handle) RouteAdd(route *Route) error {
|
func (h *Handle) RouteAdd(route *Route) error {
|
||||||
flags := syscall.NLM_F_CREATE | syscall.NLM_F_EXCL | syscall.NLM_F_ACK
|
flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
|
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +466,8 @@ func RouteReplace(route *Route) error {
|
|||||||
// RouteReplace will add a route to the system.
|
// RouteReplace will add a route to the system.
|
||||||
// Equivalent to: `ip route replace $route`
|
// Equivalent to: `ip route replace $route`
|
||||||
func (h *Handle) RouteReplace(route *Route) error {
|
func (h *Handle) RouteReplace(route *Route) error {
|
||||||
flags := syscall.NLM_F_CREATE | syscall.NLM_F_REPLACE | syscall.NLM_F_ACK
|
flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWROUTE, flags)
|
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +480,7 @@ func RouteDel(route *Route) error {
|
|||||||
// RouteDel will delete a route from the system.
|
// RouteDel will delete a route from the system.
|
||||||
// Equivalent to: `ip route del $route`
|
// Equivalent to: `ip route del $route`
|
||||||
func (h *Handle) RouteDel(route *Route) error {
|
func (h *Handle) RouteDel(route *Route) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK)
|
||||||
return h.routeHandle(route, req, nl.NewRtDelMsg())
|
return h.routeHandle(route, req, nl.NewRtDelMsg())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,12 +503,12 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
} else {
|
} else {
|
||||||
dstData = route.Dst.IP.To16()
|
dstData = route.Dst.IP.To16()
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
|
||||||
} else if route.MPLSDst != nil {
|
} else if route.MPLSDst != nil {
|
||||||
family = nl.FAMILY_MPLS
|
family = nl.FAMILY_MPLS
|
||||||
msg.Dst_len = uint8(20)
|
msg.Dst_len = uint8(20)
|
||||||
msg.Type = syscall.RTN_UNICAST
|
msg.Type = unix.RTN_UNICAST
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.NewDst != nil {
|
if route.NewDst != nil {
|
||||||
@ -232,7 +546,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
srcData = route.Src.To16()
|
srcData = route.Src.To16()
|
||||||
}
|
}
|
||||||
// The commonly used src ip for routes is actually PREFSRC
|
// The commonly used src ip for routes is actually PREFSRC
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PREFSRC, srcData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData))
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.Gw != nil {
|
if route.Gw != nil {
|
||||||
@ -247,14 +561,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
} else {
|
} else {
|
||||||
gwData = route.Gw.To16()
|
gwData = route.Gw.To16()
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(route.MultiPath) > 0 {
|
if len(route.MultiPath) > 0 {
|
||||||
buf := []byte{}
|
buf := []byte{}
|
||||||
for _, nh := range route.MultiPath {
|
for _, nh := range route.MultiPath {
|
||||||
rtnh := &nl.RtNexthop{
|
rtnh := &nl.RtNexthop{
|
||||||
RtNexthop: syscall.RtNexthop{
|
RtNexthop: unix.RtNexthop{
|
||||||
Hops: uint8(nh.Hops),
|
Hops: uint8(nh.Hops),
|
||||||
Ifindex: int32(nh.LinkIndex),
|
Ifindex: int32(nh.LinkIndex),
|
||||||
Flags: uint8(nh.Flags),
|
Flags: uint8(nh.Flags),
|
||||||
@ -267,9 +581,9 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
|
return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
|
||||||
}
|
}
|
||||||
if gwFamily == FAMILY_V4 {
|
if gwFamily == FAMILY_V4 {
|
||||||
children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4())))
|
children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4())))
|
||||||
} else {
|
} else {
|
||||||
children = append(children, nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())))
|
children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nh.NewDst != nil {
|
if nh.NewDst != nil {
|
||||||
@ -295,15 +609,15 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
rtnh.Children = children
|
rtnh.Children = children
|
||||||
buf = append(buf, rtnh.Serialize()...)
|
buf = append(buf, rtnh.Serialize()...)
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_MULTIPATH, buf))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.Table > 0 {
|
if route.Table > 0 {
|
||||||
if route.Table >= 256 {
|
if route.Table >= 256 {
|
||||||
msg.Table = syscall.RT_TABLE_UNSPEC
|
msg.Table = unix.RT_TABLE_UNSPEC
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, uint32(route.Table))
|
native.PutUint32(b, uint32(route.Table))
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b))
|
||||||
} else {
|
} else {
|
||||||
msg.Table = uint8(route.Table)
|
msg.Table = uint8(route.Table)
|
||||||
}
|
}
|
||||||
@ -312,7 +626,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
if route.Priority > 0 {
|
if route.Priority > 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, uint32(route.Priority))
|
native.PutUint32(b, uint32(route.Priority))
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b))
|
||||||
}
|
}
|
||||||
if route.Tos > 0 {
|
if route.Tos > 0 {
|
||||||
msg.Tos = uint8(route.Tos)
|
msg.Tos = uint8(route.Tos)
|
||||||
@ -324,6 +638,29 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
msg.Type = uint8(route.Type)
|
msg.Type = uint8(route.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var metrics []*nl.RtAttr
|
||||||
|
// TODO: support other rta_metric values
|
||||||
|
if route.MTU > 0 {
|
||||||
|
b := nl.Uint32Attr(uint32(route.MTU))
|
||||||
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
|
||||||
|
}
|
||||||
|
if route.AdvMSS > 0 {
|
||||||
|
b := nl.Uint32Attr(uint32(route.AdvMSS))
|
||||||
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
|
||||||
|
}
|
||||||
|
if 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)
|
||||||
|
for _, metric := range metrics {
|
||||||
|
attr.AddChild(metric)
|
||||||
|
}
|
||||||
|
rtAttrs = append(rtAttrs, attr)
|
||||||
|
}
|
||||||
|
|
||||||
msg.Flags = uint32(route.Flags)
|
msg.Flags = uint32(route.Flags)
|
||||||
msg.Scope = uint8(route.Scope)
|
msg.Scope = uint8(route.Scope)
|
||||||
msg.Family = uint8(family)
|
msg.Family = uint8(family)
|
||||||
@ -338,9 +675,9 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
)
|
)
|
||||||
native.PutUint32(b, uint32(route.LinkIndex))
|
native.PutUint32(b, uint32(route.LinkIndex))
|
||||||
|
|
||||||
req.AddData(nl.NewRtAttr(syscall.RTA_OIF, b))
|
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,11 +710,11 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
|
|||||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
||||||
// All rules must be defined in RouteFilter struct
|
// All rules must be defined in RouteFilter struct
|
||||||
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
|
||||||
infmsg := nl.NewIfInfomsg(family)
|
infmsg := nl.NewIfInfomsg(family)
|
||||||
req.AddData(infmsg)
|
req.AddData(infmsg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -385,11 +722,11 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
|
|||||||
var res []Route
|
var res []Route
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
msg := nl.DeserializeRtMsg(m)
|
msg := nl.DeserializeRtMsg(m)
|
||||||
if msg.Flags&syscall.RTM_F_CLONED != 0 {
|
if msg.Flags&unix.RTM_F_CLONED != 0 {
|
||||||
// Ignore cloned routes
|
// Ignore cloned routes
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if msg.Table != syscall.RT_TABLE_MAIN {
|
if msg.Table != unix.RT_TABLE_MAIN {
|
||||||
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
|
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
|
||||||
// Ignore non-main tables
|
// Ignore non-main tables
|
||||||
continue
|
continue
|
||||||
@ -401,7 +738,7 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
|
|||||||
}
|
}
|
||||||
if filter != nil {
|
if filter != nil {
|
||||||
switch {
|
switch {
|
||||||
case filterMask&RT_FILTER_TABLE != 0 && filter.Table != syscall.RT_TABLE_UNSPEC && route.Table != filter.Table:
|
case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
|
||||||
continue
|
continue
|
||||||
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
|
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
|
||||||
continue
|
continue
|
||||||
@ -421,21 +758,12 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
|
|||||||
continue
|
continue
|
||||||
case filterMask&RT_FILTER_DST != 0:
|
case filterMask&RT_FILTER_DST != 0:
|
||||||
if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
|
if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
|
||||||
if filter.Dst == nil {
|
if !ipNetEqual(route.Dst, filter.Dst) {
|
||||||
if route.Dst != nil {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if route.Dst == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
aMaskLen, aMaskBits := route.Dst.Mask.Size()
|
|
||||||
bMaskLen, bMaskBits := filter.Dst.Mask.Size()
|
|
||||||
if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = append(res, route)
|
res = append(res, route)
|
||||||
@ -463,11 +791,11 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
var encap, encapType syscall.NetlinkRouteAttr
|
var encap, encapType syscall.NetlinkRouteAttr
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case syscall.RTA_GATEWAY:
|
case unix.RTA_GATEWAY:
|
||||||
route.Gw = net.IP(attr.Value)
|
route.Gw = net.IP(attr.Value)
|
||||||
case syscall.RTA_PREFSRC:
|
case unix.RTA_PREFSRC:
|
||||||
route.Src = net.IP(attr.Value)
|
route.Src = net.IP(attr.Value)
|
||||||
case syscall.RTA_DST:
|
case unix.RTA_DST:
|
||||||
if msg.Family == nl.FAMILY_MPLS {
|
if msg.Family == nl.FAMILY_MPLS {
|
||||||
stack := nl.DecodeMPLSStack(attr.Value)
|
stack := nl.DecodeMPLSStack(attr.Value)
|
||||||
if len(stack) == 0 || len(stack) > 1 {
|
if len(stack) == 0 || len(stack) > 1 {
|
||||||
@ -480,36 +808,36 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
|
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case syscall.RTA_OIF:
|
case unix.RTA_OIF:
|
||||||
route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
|
route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
|
||||||
case syscall.RTA_IIF:
|
case unix.RTA_IIF:
|
||||||
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
|
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
|
||||||
case syscall.RTA_PRIORITY:
|
case unix.RTA_PRIORITY:
|
||||||
route.Priority = int(native.Uint32(attr.Value[0:4]))
|
route.Priority = int(native.Uint32(attr.Value[0:4]))
|
||||||
case syscall.RTA_TABLE:
|
case unix.RTA_TABLE:
|
||||||
route.Table = int(native.Uint32(attr.Value[0:4]))
|
route.Table = int(native.Uint32(attr.Value[0:4]))
|
||||||
case syscall.RTA_MULTIPATH:
|
case unix.RTA_MULTIPATH:
|
||||||
parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
|
parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
|
||||||
if len(value) < syscall.SizeofRtNexthop {
|
if len(value) < unix.SizeofRtNexthop {
|
||||||
return nil, nil, fmt.Errorf("Lack of bytes")
|
return nil, nil, fmt.Errorf("lack of bytes")
|
||||||
}
|
}
|
||||||
nh := nl.DeserializeRtNexthop(value)
|
nh := nl.DeserializeRtNexthop(value)
|
||||||
if len(value) < int(nh.RtNexthop.Len) {
|
if len(value) < int(nh.RtNexthop.Len) {
|
||||||
return nil, nil, fmt.Errorf("Lack of bytes")
|
return nil, nil, fmt.Errorf("lack of bytes")
|
||||||
}
|
}
|
||||||
info := &NexthopInfo{
|
info := &NexthopInfo{
|
||||||
LinkIndex: int(nh.RtNexthop.Ifindex),
|
LinkIndex: int(nh.RtNexthop.Ifindex),
|
||||||
Hops: int(nh.RtNexthop.Hops),
|
Hops: int(nh.RtNexthop.Hops),
|
||||||
Flags: int(nh.RtNexthop.Flags),
|
Flags: int(nh.RtNexthop.Flags),
|
||||||
}
|
}
|
||||||
attrs, err := nl.ParseRouteAttr(value[syscall.SizeofRtNexthop:int(nh.RtNexthop.Len)])
|
attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
var encap, encapType syscall.NetlinkRouteAttr
|
var encap, encapType syscall.NetlinkRouteAttr
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case syscall.RTA_GATEWAY:
|
case unix.RTA_GATEWAY:
|
||||||
info.Gw = net.IP(attr.Value)
|
info.Gw = net.IP(attr.Value)
|
||||||
case nl.RTA_NEWDST:
|
case nl.RTA_NEWDST:
|
||||||
var d Destination
|
var d Destination
|
||||||
@ -566,6 +894,21 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
encapType = attr
|
encapType = attr
|
||||||
case nl.RTA_ENCAP:
|
case nl.RTA_ENCAP:
|
||||||
encap = attr
|
encap = attr
|
||||||
|
case unix.RTA_METRICS:
|
||||||
|
metrics, err := nl.ParseRouteAttr(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return route, err
|
||||||
|
}
|
||||||
|
for _, metric := range metrics {
|
||||||
|
switch metric.Attr.Type {
|
||||||
|
case unix.RTAX_MTU:
|
||||||
|
route.MTU = int(native.Uint32(metric.Value[0:4]))
|
||||||
|
case unix.RTAX_ADVMSS:
|
||||||
|
route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
|
||||||
|
case unix.RTAX_HOPLIMIT:
|
||||||
|
route.Hoplimit = int(native.Uint32(metric.Value[0:4]))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,6 +921,16 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
if err := e.Decode(encap.Value); err != nil {
|
if err := e.Decode(encap.Value); err != nil {
|
||||||
return route, err
|
return route, err
|
||||||
}
|
}
|
||||||
|
case nl.LWTUNNEL_ENCAP_SEG6:
|
||||||
|
e = &SEG6Encap{}
|
||||||
|
if err := e.Decode(encap.Value); err != nil {
|
||||||
|
return route, err
|
||||||
|
}
|
||||||
|
case nl.LWTUNNEL_ENCAP_SEG6_LOCAL:
|
||||||
|
e = &SEG6LocalEncap{}
|
||||||
|
if err := e.Decode(encap.Value); err != nil {
|
||||||
|
return route, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
route.Encap = e
|
route.Encap = e
|
||||||
}
|
}
|
||||||
@ -594,7 +947,7 @@ func RouteGet(destination net.IP) ([]Route, error) {
|
|||||||
// RouteGet gets a route to a specific destination from the host system.
|
// RouteGet gets a route to a specific destination from the host system.
|
||||||
// Equivalent to: 'ip route get'.
|
// Equivalent to: 'ip route get'.
|
||||||
func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_REQUEST)
|
req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST)
|
||||||
family := nl.GetIPFamily(destination)
|
family := nl.GetIPFamily(destination)
|
||||||
var destinationData []byte
|
var destinationData []byte
|
||||||
var bitlen uint8
|
var bitlen uint8
|
||||||
@ -610,10 +963,10 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
|||||||
msg.Dst_len = bitlen
|
msg.Dst_len = bitlen
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
rtaDst := nl.NewRtAttr(syscall.RTA_DST, destinationData)
|
rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
|
||||||
req.AddData(rtaDst)
|
req.AddData(rtaDst)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -633,17 +986,36 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
|||||||
// RouteSubscribe takes a chan down which notifications will be sent
|
// RouteSubscribe takes a chan down which notifications will be sent
|
||||||
// when routes are added or deleted. Close the 'done' chan to stop subscription.
|
// when routes are added or deleted. Close the 'done' chan to stop subscription.
|
||||||
func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
|
func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
|
||||||
return routeSubscribeAt(netns.None(), netns.None(), ch, done)
|
return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
|
// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
|
||||||
// to choose the network namespace in which to subscribe (ns).
|
// to choose the network namespace in which to subscribe (ns).
|
||||||
func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
|
func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
|
||||||
return routeSubscribeAt(ns, netns.None(), ch, done)
|
return routeSubscribeAt(ns, netns.None(), ch, done, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
|
// RouteSubscribeOptions contains a set of options to use with
|
||||||
s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
|
// RouteSubscribeWithOptions.
|
||||||
|
type RouteSubscribeOptions struct {
|
||||||
|
Namespace *netns.NsHandle
|
||||||
|
ErrorCallback func(error)
|
||||||
|
ListExisting bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// RouteSubscribeWithOptions work like RouteSubscribe but enable to
|
||||||
|
// provide additional options to modify the behavior. Currently, the
|
||||||
|
// namespace can be provided as well as an error callback.
|
||||||
|
func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error {
|
||||||
|
if options.Namespace == nil {
|
||||||
|
none := netns.None()
|
||||||
|
options.Namespace = &none
|
||||||
|
}
|
||||||
|
return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||||
|
}
|
||||||
|
|
||||||
|
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||||
|
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -653,16 +1025,45 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
|
|||||||
s.Close()
|
s.Close()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if listExisting {
|
||||||
|
req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE,
|
||||||
|
unix.NLM_F_DUMP)
|
||||||
|
infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
|
req.AddData(infmsg)
|
||||||
|
if err := s.Send(req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
|
native := nl.NativeEndian()
|
||||||
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
|
if error == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(syscall.Errno(-error))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
route, err := deserializeRoute(m.Data)
|
route, err := deserializeRoute(m.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if cberr != nil {
|
||||||
|
cberr(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
|
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
|
||||||
|
2
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
// Rule represents a netlink rule.
|
// Rule represents a netlink rule.
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
Priority int
|
Priority int
|
||||||
|
Family int
|
||||||
Table int
|
Table int
|
||||||
Mark int
|
Mark int
|
||||||
Mask int
|
Mask int
|
||||||
@ -20,6 +21,7 @@ type Rule struct {
|
|||||||
OifName string
|
OifName string
|
||||||
SuppressIfgroup int
|
SuppressIfgroup int
|
||||||
SuppressPrefixlen int
|
SuppressPrefixlen int
|
||||||
|
Invert bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Rule) String() string {
|
func (r Rule) String() string {
|
||||||
|
53
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
53
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
@ -3,11 +3,13 @@ package netlink
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const FibRuleInvert = 0x2
|
||||||
|
|
||||||
// RuleAdd adds a rule to the system.
|
// RuleAdd adds a rule to the system.
|
||||||
// Equivalent to: ip rule add
|
// Equivalent to: ip rule add
|
||||||
func RuleAdd(rule *Rule) error {
|
func RuleAdd(rule *Rule) error {
|
||||||
@ -17,7 +19,7 @@ func RuleAdd(rule *Rule) error {
|
|||||||
// RuleAdd adds a rule to the system.
|
// RuleAdd adds a rule to the system.
|
||||||
// Equivalent to: ip rule add
|
// Equivalent to: ip rule add
|
||||||
func (h *Handle) RuleAdd(rule *Rule) error {
|
func (h *Handle) RuleAdd(rule *Rule) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_NEWRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
return ruleHandle(rule, req)
|
return ruleHandle(rule, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,15 +32,31 @@ func RuleDel(rule *Rule) error {
|
|||||||
// RuleDel deletes a rule from the system.
|
// RuleDel deletes a rule from the system.
|
||||||
// Equivalent to: ip rule del
|
// Equivalent to: ip rule del
|
||||||
func (h *Handle) RuleDel(rule *Rule) error {
|
func (h *Handle) RuleDel(rule *Rule) error {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_DELRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK)
|
||||||
return ruleHandle(rule, req)
|
return ruleHandle(rule, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||||
msg := nl.NewRtMsg()
|
msg := nl.NewRtMsg()
|
||||||
msg.Family = syscall.AF_INET
|
msg.Family = unix.AF_INET
|
||||||
var dstFamily uint8
|
msg.Protocol = unix.RTPROT_BOOT
|
||||||
|
msg.Scope = unix.RT_SCOPE_UNIVERSE
|
||||||
|
msg.Table = unix.RT_TABLE_UNSPEC
|
||||||
|
msg.Type = unix.RTN_UNSPEC
|
||||||
|
if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
|
||||||
|
msg.Type = unix.RTN_UNICAST
|
||||||
|
}
|
||||||
|
if rule.Invert {
|
||||||
|
msg.Flags |= FibRuleInvert
|
||||||
|
}
|
||||||
|
if rule.Family != 0 {
|
||||||
|
msg.Family = uint8(rule.Family)
|
||||||
|
}
|
||||||
|
if rule.Table >= 0 && rule.Table < 256 {
|
||||||
|
msg.Table = uint8(rule.Table)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dstFamily uint8
|
||||||
var rtAttrs []*nl.RtAttr
|
var rtAttrs []*nl.RtAttr
|
||||||
if rule.Dst != nil && rule.Dst.IP != nil {
|
if rule.Dst != nil && rule.Dst.IP != nil {
|
||||||
dstLen, _ := rule.Dst.Mask.Size()
|
dstLen, _ := rule.Dst.Mask.Size()
|
||||||
@ -46,12 +64,12 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||||||
msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
|
msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
|
||||||
dstFamily = msg.Family
|
dstFamily = msg.Family
|
||||||
var dstData []byte
|
var dstData []byte
|
||||||
if msg.Family == syscall.AF_INET {
|
if msg.Family == unix.AF_INET {
|
||||||
dstData = rule.Dst.IP.To4()
|
dstData = rule.Dst.IP.To4()
|
||||||
} else {
|
} else {
|
||||||
dstData = rule.Dst.IP.To16()
|
dstData = rule.Dst.IP.To16()
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rule.Src != nil && rule.Src.IP != nil {
|
if rule.Src != nil && rule.Src.IP != nil {
|
||||||
@ -62,19 +80,12 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||||||
srcLen, _ := rule.Src.Mask.Size()
|
srcLen, _ := rule.Src.Mask.Size()
|
||||||
msg.Src_len = uint8(srcLen)
|
msg.Src_len = uint8(srcLen)
|
||||||
var srcData []byte
|
var srcData []byte
|
||||||
if msg.Family == syscall.AF_INET {
|
if msg.Family == unix.AF_INET {
|
||||||
srcData = rule.Src.IP.To4()
|
srcData = rule.Src.IP.To4()
|
||||||
} else {
|
} else {
|
||||||
srcData = rule.Src.IP.To16()
|
srcData = rule.Src.IP.To16()
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_SRC, srcData))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData))
|
||||||
}
|
|
||||||
|
|
||||||
if rule.Table >= 0 {
|
|
||||||
msg.Table = uint8(rule.Table)
|
|
||||||
if rule.Table >= 256 {
|
|
||||||
msg.Table = syscall.RT_TABLE_UNSPEC
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
@ -139,7 +150,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,11 +163,11 @@ func RuleList(family int) ([]Rule, error) {
|
|||||||
// RuleList lists rules in the system.
|
// RuleList lists rules in the system.
|
||||||
// Equivalent to: ip rule list
|
// Equivalent to: ip rule list
|
||||||
func (h *Handle) RuleList(family int) ([]Rule, error) {
|
func (h *Handle) RuleList(family int) ([]Rule, error) {
|
||||||
req := h.newNetlinkRequest(syscall.RTM_GETRULE, syscall.NLM_F_DUMP|syscall.NLM_F_REQUEST)
|
req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST)
|
||||||
msg := nl.NewIfInfomsg(family)
|
msg := nl.NewIfInfomsg(family)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWRULE)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -172,9 +183,11 @@ func (h *Handle) RuleList(family int) ([]Rule, error) {
|
|||||||
|
|
||||||
rule := NewRule()
|
rule := NewRule()
|
||||||
|
|
||||||
|
rule.Invert = msg.Flags&FibRuleInvert > 0
|
||||||
|
|
||||||
for j := range attrs {
|
for j := range attrs {
|
||||||
switch attrs[j].Attr.Type {
|
switch attrs[j].Attr.Type {
|
||||||
case syscall.RTA_TABLE:
|
case unix.RTA_TABLE:
|
||||||
rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
|
rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
|
||||||
case nl.FRA_SRC:
|
case nl.FRA_SRC:
|
||||||
rule.Src = &net.IPNet{
|
rule.Src = &net.IPNet{
|
||||||
|
8
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
8
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
@ -4,9 +4,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -123,15 +123,15 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
|
|||||||
return nil, ErrNotImplemented
|
return nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := nl.Subscribe(syscall.NETLINK_INET_DIAG)
|
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
|
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
|
||||||
req.AddData(&socketRequest{
|
req.AddData(&socketRequest{
|
||||||
Family: syscall.AF_INET,
|
Family: unix.AF_INET,
|
||||||
Protocol: syscall.IPPROTO_TCP,
|
Protocol: unix.IPPROTO_TCP,
|
||||||
ID: SocketID{
|
ID: SocketID{
|
||||||
SourcePort: uint16(localTCP.Port),
|
SourcePort: uint16(localTCP.Port),
|
||||||
DestinationPort: uint16(remoteTCP.Port),
|
DestinationPort: uint16(remoteTCP.Port),
|
||||||
|
13
vendor/github.com/vishvananda/netlink/xfrm.go
generated
vendored
13
vendor/github.com/vishvananda/netlink/xfrm.go
generated
vendored
@ -2,19 +2,20 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Proto is an enum representing an ipsec protocol.
|
// Proto is an enum representing an ipsec protocol.
|
||||||
type Proto uint8
|
type Proto uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XFRM_PROTO_ROUTE2 Proto = syscall.IPPROTO_ROUTING
|
XFRM_PROTO_ROUTE2 Proto = unix.IPPROTO_ROUTING
|
||||||
XFRM_PROTO_ESP Proto = syscall.IPPROTO_ESP
|
XFRM_PROTO_ESP Proto = unix.IPPROTO_ESP
|
||||||
XFRM_PROTO_AH Proto = syscall.IPPROTO_AH
|
XFRM_PROTO_AH Proto = unix.IPPROTO_AH
|
||||||
XFRM_PROTO_HAO Proto = syscall.IPPROTO_DSTOPTS
|
XFRM_PROTO_HAO Proto = unix.IPPROTO_DSTOPTS
|
||||||
XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin
|
XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin
|
||||||
XFRM_PROTO_IPSEC_ANY Proto = syscall.IPPROTO_RAW
|
XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Proto) String() string {
|
func (p Proto) String() string {
|
||||||
|
7
vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
generated
vendored
7
vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
generated
vendored
@ -2,11 +2,10 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netns"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"github.com/vishvananda/netns"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type XfrmMsg interface {
|
type XfrmMsg interface {
|
||||||
@ -39,7 +38,7 @@ func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s, err := nl.SubscribeAt(netns.None(), netns.None(), syscall.NETLINK_XFRM, groups...)
|
s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
25
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
25
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
@ -35,6 +35,25 @@ func (d Dir) String() string {
|
|||||||
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
|
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
|
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
|
||||||
// policy. These rules are matched with XfrmState to determine encryption
|
// policy. These rules are matched with XfrmState to determine encryption
|
||||||
// and authentication algorithms.
|
// and authentication algorithms.
|
||||||
@ -64,11 +83,13 @@ type XfrmPolicy struct {
|
|||||||
Dir Dir
|
Dir Dir
|
||||||
Priority int
|
Priority int
|
||||||
Index int
|
Index int
|
||||||
|
Action PolicyAction
|
||||||
|
Ifindex int
|
||||||
Mark *XfrmMark
|
Mark *XfrmMark
|
||||||
Tmpls []XfrmPolicyTmpl
|
Tmpls []XfrmPolicyTmpl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p XfrmPolicy) String() string {
|
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}",
|
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %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)
|
p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Mark, p.Tmpls)
|
||||||
}
|
}
|
||||||
|
30
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
30
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
@ -1,9 +1,8 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
||||||
@ -28,6 +27,7 @@ func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
|||||||
if sel.Sport != 0 {
|
if sel.Sport != 0 {
|
||||||
sel.SportMask = ^uint16(0)
|
sel.SportMask = ^uint16(0)
|
||||||
}
|
}
|
||||||
|
sel.Ifindex = int32(policy.Ifindex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XfrmPolicyAdd will add an xfrm policy to the system.
|
// XfrmPolicyAdd will add an xfrm policy to the system.
|
||||||
@ -55,13 +55,14 @@ func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
||||||
req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := &nl.XfrmUserpolicyInfo{}
|
msg := &nl.XfrmUserpolicyInfo{}
|
||||||
selFromPolicy(&msg.Sel, policy)
|
selFromPolicy(&msg.Sel, policy)
|
||||||
msg.Priority = uint32(policy.Priority)
|
msg.Priority = uint32(policy.Priority)
|
||||||
msg.Index = uint32(policy.Index)
|
msg.Index = uint32(policy.Index)
|
||||||
msg.Dir = uint8(policy.Dir)
|
msg.Dir = uint8(policy.Dir)
|
||||||
|
msg.Action = uint8(policy.Action)
|
||||||
msg.Lft.SoftByteLimit = nl.XFRM_INF
|
msg.Lft.SoftByteLimit = nl.XFRM_INF
|
||||||
msg.Lft.HardByteLimit = nl.XFRM_INF
|
msg.Lft.HardByteLimit = nl.XFRM_INF
|
||||||
msg.Lft.SoftPacketLimit = nl.XFRM_INF
|
msg.Lft.SoftPacketLimit = nl.XFRM_INF
|
||||||
@ -91,7 +92,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
|||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,12 +122,12 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
|
|||||||
// Equivalent to: `ip xfrm policy show`.
|
// Equivalent to: `ip xfrm policy show`.
|
||||||
// The list can be filtered by ip family.
|
// The list can be filtered by ip family.
|
||||||
func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
|
func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) {
|
||||||
req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP)
|
||||||
|
|
||||||
msg := nl.NewIfInfomsg(family)
|
msg := nl.NewIfInfomsg(family)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
|
msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -165,13 +166,13 @@ func XfrmPolicyFlush() error {
|
|||||||
// XfrmPolicyFlush will flush the policies on the system.
|
// XfrmPolicyFlush will flush the policies on the system.
|
||||||
// Equivalent to: `ip xfrm policy flush`
|
// Equivalent to: `ip xfrm policy flush`
|
||||||
func (h *Handle) XfrmPolicyFlush() error {
|
func (h *Handle) XfrmPolicyFlush() error {
|
||||||
req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK)
|
||||||
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
|
func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) {
|
||||||
req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := &nl.XfrmUserpolicyId{}
|
msg := &nl.XfrmUserpolicyId{}
|
||||||
selFromPolicy(&msg.Sel, policy)
|
selFromPolicy(&msg.Sel, policy)
|
||||||
@ -189,7 +190,7 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
|
|||||||
resType = 0
|
resType = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
|
msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -198,12 +199,7 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := parseXfrmPolicy(msgs[0], FAMILY_ALL)
|
return parseXfrmPolicy(msgs[0], FAMILY_ALL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
||||||
@ -221,9 +217,11 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
|||||||
policy.Proto = Proto(msg.Sel.Proto)
|
policy.Proto = Proto(msg.Sel.Proto)
|
||||||
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
||||||
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
||||||
|
policy.Ifindex = int(msg.Sel.Ifindex)
|
||||||
policy.Priority = int(msg.Priority)
|
policy.Priority = int(msg.Priority)
|
||||||
policy.Index = int(msg.Index)
|
policy.Index = int(msg.Index)
|
||||||
policy.Dir = Dir(msg.Dir)
|
policy.Dir = Dir(msg.Dir)
|
||||||
|
policy.Action = PolicyAction(msg.Action)
|
||||||
|
|
||||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
27
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
27
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
@ -3,6 +3,7 @@ package netlink
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
|
// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
|
||||||
@ -67,6 +68,19 @@ type XfrmStateLimits struct {
|
|||||||
TimeUseHard uint64
|
TimeUseHard uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XfrmStateStats represents the current number of bytes/packets
|
||||||
|
// processed by this State, the State's installation and first use
|
||||||
|
// time and the replay window counters.
|
||||||
|
type XfrmStateStats struct {
|
||||||
|
ReplayWindow uint32
|
||||||
|
Replay uint32
|
||||||
|
Failed uint32
|
||||||
|
Bytes uint64
|
||||||
|
Packets uint64
|
||||||
|
AddTime uint64
|
||||||
|
UseTime uint64
|
||||||
|
}
|
||||||
|
|
||||||
// XfrmState represents the state of an ipsec policy. It optionally
|
// XfrmState represents the state of an ipsec policy. It optionally
|
||||||
// contains an XfrmStateAlgo for encryption and one for authentication.
|
// contains an XfrmStateAlgo for encryption and one for authentication.
|
||||||
type XfrmState struct {
|
type XfrmState struct {
|
||||||
@ -78,6 +92,7 @@ type XfrmState struct {
|
|||||||
Reqid int
|
Reqid int
|
||||||
ReplayWindow int
|
ReplayWindow int
|
||||||
Limits XfrmStateLimits
|
Limits XfrmStateLimits
|
||||||
|
Statistics XfrmStateStats
|
||||||
Mark *XfrmMark
|
Mark *XfrmMark
|
||||||
Auth *XfrmStateAlgo
|
Auth *XfrmStateAlgo
|
||||||
Crypt *XfrmStateAlgo
|
Crypt *XfrmStateAlgo
|
||||||
@ -94,10 +109,16 @@ func (sa XfrmState) Print(stats bool) string {
|
|||||||
if !stats {
|
if !stats {
|
||||||
return sa.String()
|
return sa.String()
|
||||||
}
|
}
|
||||||
|
at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate)
|
||||||
return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d",
|
ut := "-"
|
||||||
|
if sa.Statistics.UseTime > 0 {
|
||||||
|
ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+
|
||||||
|
"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d",
|
||||||
sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
|
sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
|
||||||
sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard)
|
sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut,
|
||||||
|
sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printLimit(lmt uint64) string {
|
func printLimit(lmt uint64) string {
|
||||||
|
52
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
52
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
@ -2,10 +2,10 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeStateAlgo(a *XfrmStateAlgo) []byte {
|
func writeStateAlgo(a *XfrmStateAlgo) []byte {
|
||||||
@ -69,8 +69,10 @@ func writeReplayEsn(replayWindow int) []byte {
|
|||||||
ReplayWindow: uint32(replayWindow),
|
ReplayWindow: uint32(replayWindow),
|
||||||
}
|
}
|
||||||
|
|
||||||
// taken from iproute2/ip/xfrm_state.c:
|
// Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements.
|
||||||
replayEsn.BmpLen = uint32((replayWindow + (4 * 8) - 1) / (4 * 8))
|
// Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation.
|
||||||
|
bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this
|
||||||
|
replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8))
|
||||||
|
|
||||||
return replayEsn.Serialize()
|
return replayEsn.Serialize()
|
||||||
}
|
}
|
||||||
@ -111,7 +113,7 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
|||||||
if state.Spi == 0 {
|
if state.Spi == 0 {
|
||||||
return fmt.Errorf("Spi must be set when adding xfrm state.")
|
return fmt.Errorf("Spi must be set when adding xfrm state.")
|
||||||
}
|
}
|
||||||
req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := xfrmUsersaInfoFromXfrmState(state)
|
msg := xfrmUsersaInfoFromXfrmState(state)
|
||||||
|
|
||||||
@ -157,13 +159,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
|||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
||||||
req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI,
|
req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI,
|
||||||
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := &nl.XfrmUserSpiInfo{}
|
msg := &nl.XfrmUserSpiInfo{}
|
||||||
msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state))
|
msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state))
|
||||||
@ -177,17 +179,12 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
|||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, 0)
|
msgs, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := parseXfrmState(msgs[0], FAMILY_ALL)
|
return parseXfrmState(msgs[0], FAMILY_ALL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XfrmStateDel will delete an xfrm state from the system. Note that
|
// XfrmStateDel will delete an xfrm state from the system. Note that
|
||||||
@ -216,9 +213,9 @@ func XfrmStateList(family int) ([]XfrmState, error) {
|
|||||||
// Equivalent to: `ip xfrm state show`.
|
// Equivalent to: `ip xfrm state show`.
|
||||||
// The list can be filtered by ip family.
|
// The list can be filtered by ip family.
|
||||||
func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) {
|
func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) {
|
||||||
req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)
|
req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP)
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
|
msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -255,7 +252,7 @@ func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) {
|
func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) {
|
||||||
req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK)
|
||||||
|
|
||||||
msg := &nl.XfrmUsersaId{}
|
msg := &nl.XfrmUsersaId{}
|
||||||
msg.Family = uint16(nl.GetIPFamily(state.Dst))
|
msg.Family = uint16(nl.GetIPFamily(state.Dst))
|
||||||
@ -278,7 +275,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
|
|||||||
resType = 0
|
resType = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
|
msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -308,6 +305,7 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
|
|||||||
state.Reqid = int(msg.Reqid)
|
state.Reqid = int(msg.Reqid)
|
||||||
state.ReplayWindow = int(msg.ReplayWindow)
|
state.ReplayWindow = int(msg.ReplayWindow)
|
||||||
lftToLimits(&msg.Lft, &state.Limits)
|
lftToLimits(&msg.Lft, &state.Limits)
|
||||||
|
curToStats(&msg.Curlft, &msg.Stats, &state.Statistics)
|
||||||
|
|
||||||
return &state
|
return &state
|
||||||
}
|
}
|
||||||
@ -386,16 +384,12 @@ func XfrmStateFlush(proto Proto) error {
|
|||||||
// proto = 0 means any transformation protocols
|
// proto = 0 means any transformation protocols
|
||||||
// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
|
// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
|
||||||
func (h *Handle) XfrmStateFlush(proto Proto) error {
|
func (h *Handle) XfrmStateFlush(proto Proto) error {
|
||||||
req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, syscall.NLM_F_ACK)
|
req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK)
|
||||||
|
|
||||||
req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
|
req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
|
||||||
|
|
||||||
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
|
func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
|
||||||
@ -429,6 +423,16 @@ func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) {
|
|||||||
*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
|
*lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) {
|
||||||
|
stats.Bytes = cur.Bytes
|
||||||
|
stats.Packets = cur.Packets
|
||||||
|
stats.AddTime = cur.AddTime
|
||||||
|
stats.UseTime = cur.UseTime
|
||||||
|
stats.ReplayWindow = wstats.ReplayWindow
|
||||||
|
stats.Replay = wstats.Replay
|
||||||
|
stats.Failed = wstats.IntegrityFailed
|
||||||
|
}
|
||||||
|
|
||||||
func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
|
func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
|
||||||
msg := &nl.XfrmUsersaInfo{}
|
msg := &nl.XfrmUsersaInfo{}
|
||||||
msg.Family = uint16(nl.GetIPFamily(state.Dst))
|
msg.Family = uint16(nl.GetIPFamily(state.Dst))
|
||||||
|
10
vendor/github.com/vishvananda/netns/netns_linux.go
generated
vendored
10
vendor/github.com/vishvananda/netns/netns_linux.go
generated
vendored
@ -138,7 +138,9 @@ func getThisCgroup(cgroupType string) (string, error) {
|
|||||||
return "", fmt.Errorf("docker pid not found in /var/run/docker.pid")
|
return "", fmt.Errorf("docker pid not found in /var/run/docker.pid")
|
||||||
}
|
}
|
||||||
pid, err := strconv.Atoi(result[0])
|
pid, err := strconv.Atoi(result[0])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
|
output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -186,6 +188,12 @@ func getPidForContainer(id string) (int, error) {
|
|||||||
filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"),
|
filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"),
|
||||||
// Even more recent docker versions under cgroup/systemd/docker/<id>/
|
// Even more recent docker versions under cgroup/systemd/docker/<id>/
|
||||||
filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"),
|
filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"),
|
||||||
|
// Kubernetes with docker and CNI is even more different
|
||||||
|
filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, "tasks"),
|
||||||
|
// Another flavor of containers location in recent kubernetes 1.11+
|
||||||
|
filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
|
||||||
|
// When runs inside of a container with recent kubernetes 1.11+
|
||||||
|
filepath.Join(cgroupRoot, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
|
||||||
}
|
}
|
||||||
|
|
||||||
var filename string
|
var filename string
|
||||||
|
4
vendor/golang.org/x/crypto/ssh/terminal/util.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/terminal/util.go
generated
vendored
@ -108,9 +108,7 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
|
||||||
unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return readPasswordLine(passwordReader(fd))
|
return readPasswordLine(passwordReader(fd))
|
||||||
}
|
}
|
||||||
|
36
vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
generated
vendored
36
vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
generated
vendored
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// State contains the state of a terminal.
|
// State contains the state of a terminal.
|
||||||
type State struct {
|
type State struct {
|
||||||
state *unix.Termios
|
termios unix.Termios
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
@ -75,47 +75,43 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||||||
// restored.
|
// restored.
|
||||||
// see http://cr.illumos.org/~webrev/andy_js/1060/
|
// see http://cr.illumos.org/~webrev/andy_js/1060/
|
||||||
func MakeRaw(fd int) (*State, error) {
|
func MakeRaw(fd int) (*State, error) {
|
||||||
oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
oldTermios := *oldTermiosPtr
|
|
||||||
|
|
||||||
newTermios := oldTermios
|
oldState := State{termios: *termios}
|
||||||
newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
|
||||||
newTermios.Oflag &^= syscall.OPOST
|
|
||||||
newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
|
||||||
newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
|
|
||||||
newTermios.Cflag |= syscall.CS8
|
|
||||||
newTermios.Cc[unix.VMIN] = 1
|
|
||||||
newTermios.Cc[unix.VTIME] = 0
|
|
||||||
|
|
||||||
if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
|
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
||||||
|
termios.Oflag &^= unix.OPOST
|
||||||
|
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
||||||
|
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
||||||
|
termios.Cflag |= unix.CS8
|
||||||
|
termios.Cc[unix.VMIN] = 1
|
||||||
|
termios.Cc[unix.VTIME] = 0
|
||||||
|
|
||||||
|
if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{
|
return &oldState, nil
|
||||||
state: oldTermiosPtr,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, oldState *State) error {
|
func Restore(fd int, oldState *State) error {
|
||||||
return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
|
return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetState returns the current state of a terminal which may be useful to
|
// GetState returns the current state of a terminal which may be useful to
|
||||||
// restore the terminal after a signal.
|
// restore the terminal after a signal.
|
||||||
func GetState(fd int) (*State, error) {
|
func GetState(fd int) (*State, error) {
|
||||||
oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{
|
return &State{termios: *termios}, nil
|
||||||
state: oldTermiosPtr,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
|
14
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
generated
vendored
14
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
generated
vendored
@ -89,9 +89,15 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer windows.SetConsoleMode(windows.Handle(fd), old)
|
||||||
windows.SetConsoleMode(windows.Handle(fd), old)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
|
var h windows.Handle
|
||||||
|
p, _ := windows.GetCurrentProcess()
|
||||||
|
if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f := os.NewFile(uintptr(h), "stdin")
|
||||||
|
defer f.Close()
|
||||||
|
return readPasswordLine(f)
|
||||||
}
|
}
|
||||||
|
57
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
57
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
@ -38,6 +38,7 @@ const (
|
|||||||
type JumpTest uint16
|
type JumpTest uint16
|
||||||
|
|
||||||
// Supported operators for conditional jumps.
|
// Supported operators for conditional jumps.
|
||||||
|
// K can be RegX for JumpIfX
|
||||||
const (
|
const (
|
||||||
// K == A
|
// K == A
|
||||||
JumpEqual JumpTest = iota
|
JumpEqual JumpTest = iota
|
||||||
@ -70,57 +71,60 @@ type Extension int
|
|||||||
|
|
||||||
// Extension functions available in the Linux kernel.
|
// Extension functions available in the Linux kernel.
|
||||||
const (
|
const (
|
||||||
|
// extOffset is the negative maximum number of instructions used
|
||||||
|
// to load instructions by overloading the K argument.
|
||||||
|
extOffset = -0x1000
|
||||||
// ExtLen returns the length of the packet.
|
// ExtLen returns the length of the packet.
|
||||||
ExtLen Extension = 1
|
ExtLen Extension = 1
|
||||||
// ExtProto returns the packet's L3 protocol type.
|
// ExtProto returns the packet's L3 protocol type.
|
||||||
ExtProto = 0
|
ExtProto Extension = 0
|
||||||
// ExtType returns the packet's type (skb->pkt_type in the kernel)
|
// ExtType returns the packet's type (skb->pkt_type in the kernel)
|
||||||
//
|
//
|
||||||
// TODO: better documentation. How nice an API do we want to
|
// TODO: better documentation. How nice an API do we want to
|
||||||
// provide for these esoteric extensions?
|
// provide for these esoteric extensions?
|
||||||
ExtType = 4
|
ExtType Extension = 4
|
||||||
// ExtPayloadOffset returns the offset of the packet payload, or
|
// ExtPayloadOffset returns the offset of the packet payload, or
|
||||||
// the first protocol header that the kernel does not know how to
|
// the first protocol header that the kernel does not know how to
|
||||||
// parse.
|
// parse.
|
||||||
ExtPayloadOffset = 52
|
ExtPayloadOffset Extension = 52
|
||||||
// ExtInterfaceIndex returns the index of the interface on which
|
// ExtInterfaceIndex returns the index of the interface on which
|
||||||
// the packet was received.
|
// the packet was received.
|
||||||
ExtInterfaceIndex = 8
|
ExtInterfaceIndex Extension = 8
|
||||||
// ExtNetlinkAttr returns the netlink attribute of type X at
|
// ExtNetlinkAttr returns the netlink attribute of type X at
|
||||||
// offset A.
|
// offset A.
|
||||||
ExtNetlinkAttr = 12
|
ExtNetlinkAttr Extension = 12
|
||||||
// ExtNetlinkAttrNested returns the nested netlink attribute of
|
// ExtNetlinkAttrNested returns the nested netlink attribute of
|
||||||
// type X at offset A.
|
// type X at offset A.
|
||||||
ExtNetlinkAttrNested = 16
|
ExtNetlinkAttrNested Extension = 16
|
||||||
// ExtMark returns the packet's mark value.
|
// ExtMark returns the packet's mark value.
|
||||||
ExtMark = 20
|
ExtMark Extension = 20
|
||||||
// ExtQueue returns the packet's assigned hardware queue.
|
// ExtQueue returns the packet's assigned hardware queue.
|
||||||
ExtQueue = 24
|
ExtQueue Extension = 24
|
||||||
// ExtLinkLayerType returns the packet's hardware address type
|
// ExtLinkLayerType returns the packet's hardware address type
|
||||||
// (e.g. Ethernet, Infiniband).
|
// (e.g. Ethernet, Infiniband).
|
||||||
ExtLinkLayerType = 28
|
ExtLinkLayerType Extension = 28
|
||||||
// ExtRXHash returns the packets receive hash.
|
// ExtRXHash returns the packets receive hash.
|
||||||
//
|
//
|
||||||
// TODO: figure out what this rxhash actually is.
|
// TODO: figure out what this rxhash actually is.
|
||||||
ExtRXHash = 32
|
ExtRXHash Extension = 32
|
||||||
// ExtCPUID returns the ID of the CPU processing the current
|
// ExtCPUID returns the ID of the CPU processing the current
|
||||||
// packet.
|
// packet.
|
||||||
ExtCPUID = 36
|
ExtCPUID Extension = 36
|
||||||
// ExtVLANTag returns the packet's VLAN tag.
|
// ExtVLANTag returns the packet's VLAN tag.
|
||||||
ExtVLANTag = 44
|
ExtVLANTag Extension = 44
|
||||||
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
|
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
|
||||||
// tag.
|
// tag.
|
||||||
//
|
//
|
||||||
// TODO: I think this might be a lie: it reads bit 0x1000 of the
|
// TODO: I think this might be a lie: it reads bit 0x1000 of the
|
||||||
// VLAN header, which changed meaning in recent revisions of the
|
// VLAN header, which changed meaning in recent revisions of the
|
||||||
// spec - this extension may now return meaningless information.
|
// spec - this extension may now return meaningless information.
|
||||||
ExtVLANTagPresent = 48
|
ExtVLANTagPresent Extension = 48
|
||||||
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
|
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
|
||||||
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
|
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
|
||||||
// other value if no VLAN information is present.
|
// other value if no VLAN information is present.
|
||||||
ExtVLANProto = 60
|
ExtVLANProto Extension = 60
|
||||||
// ExtRand returns a uniformly random uint32.
|
// ExtRand returns a uniformly random uint32.
|
||||||
ExtRand = 56
|
ExtRand Extension = 56
|
||||||
)
|
)
|
||||||
|
|
||||||
// The following gives names to various bit patterns used in opcode construction.
|
// The following gives names to various bit patterns used in opcode construction.
|
||||||
@ -131,12 +135,9 @@ const (
|
|||||||
opMaskLoadDest = 0x01
|
opMaskLoadDest = 0x01
|
||||||
opMaskLoadWidth = 0x18
|
opMaskLoadWidth = 0x18
|
||||||
opMaskLoadMode = 0xe0
|
opMaskLoadMode = 0xe0
|
||||||
// opClsALU
|
// opClsALU & opClsJump
|
||||||
opMaskOperandSrc = 0x08
|
opMaskOperand = 0x08
|
||||||
opMaskOperator = 0xf0
|
opMaskOperator = 0xf0
|
||||||
// opClsJump
|
|
||||||
opMaskJumpConst = 0x0f
|
|
||||||
opMaskJumpCond = 0xf0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -189,15 +190,21 @@ const (
|
|||||||
opLoadWidth1
|
opLoadWidth1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operator defined by ALUOp*
|
// Operand for ALU and Jump instructions
|
||||||
|
type opOperand uint16
|
||||||
|
|
||||||
|
// Supported operand sources.
|
||||||
const (
|
const (
|
||||||
opALUSrcConstant uint16 = iota << 3
|
opOperandConstant opOperand = iota << 3
|
||||||
opALUSrcX
|
opOperandX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// An jumpOp is a conditional jump condition.
|
||||||
|
type jumpOp uint16
|
||||||
|
|
||||||
|
// Supported jump conditions.
|
||||||
const (
|
const (
|
||||||
opJumpAlways = iota << 4
|
opJumpAlways jumpOp = iota << 4
|
||||||
opJumpEqual
|
opJumpEqual
|
||||||
opJumpGT
|
opJumpGT
|
||||||
opJumpGE
|
opJumpGE
|
||||||
|
378
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
378
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
@ -57,6 +57,9 @@ func (ri RawInstruction) Disassemble() Instruction {
|
|||||||
}
|
}
|
||||||
return LoadScratch{Dst: reg, N: int(ri.K)}
|
return LoadScratch{Dst: reg, N: int(ri.K)}
|
||||||
case opAddrModeAbsolute:
|
case opAddrModeAbsolute:
|
||||||
|
if ri.K > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(-extOffset + ri.K)}
|
||||||
|
}
|
||||||
return LoadAbsolute{Size: sz, Off: ri.K}
|
return LoadAbsolute{Size: sz, Off: ri.K}
|
||||||
case opAddrModeIndirect:
|
case opAddrModeIndirect:
|
||||||
return LoadIndirect{Size: sz, Off: ri.K}
|
return LoadIndirect{Size: sz, Off: ri.K}
|
||||||
@ -86,10 +89,14 @@ func (ri RawInstruction) Disassemble() Instruction {
|
|||||||
case opClsALU:
|
case opClsALU:
|
||||||
switch op := ALUOp(ri.Op & opMaskOperator); op {
|
switch op := ALUOp(ri.Op & opMaskOperator); op {
|
||||||
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
|
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
|
||||||
if ri.Op&opMaskOperandSrc != 0 {
|
switch operand := opOperand(ri.Op & opMaskOperand); operand {
|
||||||
|
case opOperandX:
|
||||||
return ALUOpX{Op: op}
|
return ALUOpX{Op: op}
|
||||||
|
case opOperandConstant:
|
||||||
|
return ALUOpConstant{Op: op, Val: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
}
|
}
|
||||||
return ALUOpConstant{Op: op, Val: ri.K}
|
|
||||||
case aluOpNeg:
|
case aluOpNeg:
|
||||||
return NegateA{}
|
return NegateA{}
|
||||||
default:
|
default:
|
||||||
@ -97,39 +104,18 @@ func (ri RawInstruction) Disassemble() Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case opClsJump:
|
case opClsJump:
|
||||||
if ri.Op&opMaskJumpConst != opClsJump {
|
switch op := jumpOp(ri.Op & opMaskOperator); op {
|
||||||
return ri
|
|
||||||
}
|
|
||||||
switch ri.Op & opMaskJumpCond {
|
|
||||||
case opJumpAlways:
|
case opJumpAlways:
|
||||||
return Jump{Skip: ri.K}
|
return Jump{Skip: ri.K}
|
||||||
case opJumpEqual:
|
case opJumpEqual, opJumpGT, opJumpGE, opJumpSet:
|
||||||
return JumpIf{
|
cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf)
|
||||||
Cond: JumpEqual,
|
switch operand := opOperand(ri.Op & opMaskOperand); operand {
|
||||||
Val: ri.K,
|
case opOperandX:
|
||||||
SkipTrue: ri.Jt,
|
return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse}
|
||||||
SkipFalse: ri.Jf,
|
case opOperandConstant:
|
||||||
}
|
return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse}
|
||||||
case opJumpGT:
|
default:
|
||||||
return JumpIf{
|
return ri
|
||||||
Cond: JumpGreaterThan,
|
|
||||||
Val: ri.K,
|
|
||||||
SkipTrue: ri.Jt,
|
|
||||||
SkipFalse: ri.Jf,
|
|
||||||
}
|
|
||||||
case opJumpGE:
|
|
||||||
return JumpIf{
|
|
||||||
Cond: JumpGreaterOrEqual,
|
|
||||||
Val: ri.K,
|
|
||||||
SkipTrue: ri.Jt,
|
|
||||||
SkipFalse: ri.Jf,
|
|
||||||
}
|
|
||||||
case opJumpSet:
|
|
||||||
return JumpIf{
|
|
||||||
Cond: JumpBitsSet,
|
|
||||||
Val: ri.K,
|
|
||||||
SkipTrue: ri.Jt,
|
|
||||||
SkipFalse: ri.Jf,
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ri
|
return ri
|
||||||
@ -160,6 +146,41 @@ func (ri RawInstruction) Disassemble() Instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) {
|
||||||
|
var test JumpTest
|
||||||
|
|
||||||
|
// Decode "fake" jump conditions that don't appear in machine code
|
||||||
|
// Ensures the Assemble -> Disassemble stage recreates the same instructions
|
||||||
|
// See https://github.com/golang/go/issues/18470
|
||||||
|
if skipTrue == 0 {
|
||||||
|
switch op {
|
||||||
|
case opJumpEqual:
|
||||||
|
test = JumpNotEqual
|
||||||
|
case opJumpGT:
|
||||||
|
test = JumpLessOrEqual
|
||||||
|
case opJumpGE:
|
||||||
|
test = JumpLessThan
|
||||||
|
case opJumpSet:
|
||||||
|
test = JumpBitsNotSet
|
||||||
|
}
|
||||||
|
|
||||||
|
return test, skipFalse, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case opJumpEqual:
|
||||||
|
test = JumpEqual
|
||||||
|
case opJumpGT:
|
||||||
|
test = JumpGreaterThan
|
||||||
|
case opJumpGE:
|
||||||
|
test = JumpGreaterOrEqual
|
||||||
|
case opJumpSet:
|
||||||
|
test = JumpBitsSet
|
||||||
|
}
|
||||||
|
|
||||||
|
return test, skipTrue, skipFalse
|
||||||
|
}
|
||||||
|
|
||||||
// LoadConstant loads Val into register Dst.
|
// LoadConstant loads Val into register Dst.
|
||||||
type LoadConstant struct {
|
type LoadConstant struct {
|
||||||
Dst Register
|
Dst Register
|
||||||
@ -171,6 +192,18 @@ func (a LoadConstant) Assemble() (RawInstruction, error) {
|
|||||||
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadConstant) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld #%d", a.Val)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadScratch loads scratch[N] into register Dst.
|
// LoadScratch loads scratch[N] into register Dst.
|
||||||
type LoadScratch struct {
|
type LoadScratch struct {
|
||||||
Dst Register
|
Dst Register
|
||||||
@ -185,6 +218,18 @@ func (a LoadScratch) Assemble() (RawInstruction, error) {
|
|||||||
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadScratch) String() string {
|
||||||
|
switch a.Dst {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("ld M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("ldx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
||||||
// register A.
|
// register A.
|
||||||
type LoadAbsolute struct {
|
type LoadAbsolute struct {
|
||||||
@ -197,6 +242,23 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) {
|
|||||||
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadAbsolute) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [%d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [%d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
if a.Off > extOffset+0xffffffff {
|
||||||
|
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ld [%d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
||||||
// into register A.
|
// into register A.
|
||||||
type LoadIndirect struct {
|
type LoadIndirect struct {
|
||||||
@ -209,6 +271,20 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) {
|
|||||||
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadIndirect) String() string {
|
||||||
|
switch a.Size {
|
||||||
|
case 1: // byte
|
||||||
|
return fmt.Sprintf("ldb [x + %d]", a.Off)
|
||||||
|
case 2: // half word
|
||||||
|
return fmt.Sprintf("ldh [x + %d]", a.Off)
|
||||||
|
case 4: // word
|
||||||
|
return fmt.Sprintf("ld [x + %d]", a.Off)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
||||||
// by 4 and stores the result in register X.
|
// by 4 and stores the result in register X.
|
||||||
//
|
//
|
||||||
@ -224,6 +300,11 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) {
|
|||||||
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadMemShift) String() string {
|
||||||
|
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
// LoadExtension invokes a linux-specific extension and stores the
|
// LoadExtension invokes a linux-specific extension and stores the
|
||||||
// result in register A.
|
// result in register A.
|
||||||
type LoadExtension struct {
|
type LoadExtension struct {
|
||||||
@ -235,7 +316,47 @@ func (a LoadExtension) Assemble() (RawInstruction, error) {
|
|||||||
if a.Num == ExtLen {
|
if a.Num == ExtLen {
|
||||||
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
||||||
}
|
}
|
||||||
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
|
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a LoadExtension) String() string {
|
||||||
|
switch a.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return "ld #len"
|
||||||
|
case ExtProto:
|
||||||
|
return "ld #proto"
|
||||||
|
case ExtType:
|
||||||
|
return "ld #type"
|
||||||
|
case ExtPayloadOffset:
|
||||||
|
return "ld #poff"
|
||||||
|
case ExtInterfaceIndex:
|
||||||
|
return "ld #ifidx"
|
||||||
|
case ExtNetlinkAttr:
|
||||||
|
return "ld #nla"
|
||||||
|
case ExtNetlinkAttrNested:
|
||||||
|
return "ld #nlan"
|
||||||
|
case ExtMark:
|
||||||
|
return "ld #mark"
|
||||||
|
case ExtQueue:
|
||||||
|
return "ld #queue"
|
||||||
|
case ExtLinkLayerType:
|
||||||
|
return "ld #hatype"
|
||||||
|
case ExtRXHash:
|
||||||
|
return "ld #rxhash"
|
||||||
|
case ExtCPUID:
|
||||||
|
return "ld #cpu"
|
||||||
|
case ExtVLANTag:
|
||||||
|
return "ld #vlan_tci"
|
||||||
|
case ExtVLANTagPresent:
|
||||||
|
return "ld #vlan_avail"
|
||||||
|
case ExtVLANProto:
|
||||||
|
return "ld #vlan_tpid"
|
||||||
|
case ExtRand:
|
||||||
|
return "ld #rand"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreScratch stores register Src into scratch[N].
|
// StoreScratch stores register Src into scratch[N].
|
||||||
@ -265,6 +386,18 @@ func (a StoreScratch) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a StoreScratch) String() string {
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
return fmt.Sprintf("st M[%d]", a.N)
|
||||||
|
case RegX:
|
||||||
|
return fmt.Sprintf("stx M[%d]", a.N)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ALUOpConstant executes A = A <Op> Val.
|
// ALUOpConstant executes A = A <Op> Val.
|
||||||
type ALUOpConstant struct {
|
type ALUOpConstant struct {
|
||||||
Op ALUOp
|
Op ALUOp
|
||||||
@ -274,11 +407,39 @@ type ALUOpConstant struct {
|
|||||||
// Assemble implements the Instruction Assemble method.
|
// Assemble implements the Instruction Assemble method.
|
||||||
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
||||||
return RawInstruction{
|
return RawInstruction{
|
||||||
Op: opClsALU | opALUSrcConstant | uint16(a.Op),
|
Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op),
|
||||||
K: a.Val,
|
K: a.Val,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a ALUOpConstant) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return fmt.Sprintf("add #%d", a.Val)
|
||||||
|
case ALUOpSub:
|
||||||
|
return fmt.Sprintf("sub #%d", a.Val)
|
||||||
|
case ALUOpMul:
|
||||||
|
return fmt.Sprintf("mul #%d", a.Val)
|
||||||
|
case ALUOpDiv:
|
||||||
|
return fmt.Sprintf("div #%d", a.Val)
|
||||||
|
case ALUOpMod:
|
||||||
|
return fmt.Sprintf("mod #%d", a.Val)
|
||||||
|
case ALUOpAnd:
|
||||||
|
return fmt.Sprintf("and #%d", a.Val)
|
||||||
|
case ALUOpOr:
|
||||||
|
return fmt.Sprintf("or #%d", a.Val)
|
||||||
|
case ALUOpXor:
|
||||||
|
return fmt.Sprintf("xor #%d", a.Val)
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return fmt.Sprintf("lsh #%d", a.Val)
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return fmt.Sprintf("rsh #%d", a.Val)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ALUOpX executes A = A <Op> X
|
// ALUOpX executes A = A <Op> X
|
||||||
type ALUOpX struct {
|
type ALUOpX struct {
|
||||||
Op ALUOp
|
Op ALUOp
|
||||||
@ -287,10 +448,38 @@ type ALUOpX struct {
|
|||||||
// Assemble implements the Instruction Assemble method.
|
// Assemble implements the Instruction Assemble method.
|
||||||
func (a ALUOpX) Assemble() (RawInstruction, error) {
|
func (a ALUOpX) Assemble() (RawInstruction, error) {
|
||||||
return RawInstruction{
|
return RawInstruction{
|
||||||
Op: opClsALU | opALUSrcX | uint16(a.Op),
|
Op: opClsALU | uint16(opOperandX) | uint16(a.Op),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a ALUOpX) String() string {
|
||||||
|
switch a.Op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return "add x"
|
||||||
|
case ALUOpSub:
|
||||||
|
return "sub x"
|
||||||
|
case ALUOpMul:
|
||||||
|
return "mul x"
|
||||||
|
case ALUOpDiv:
|
||||||
|
return "div x"
|
||||||
|
case ALUOpMod:
|
||||||
|
return "mod x"
|
||||||
|
case ALUOpAnd:
|
||||||
|
return "and x"
|
||||||
|
case ALUOpOr:
|
||||||
|
return "or x"
|
||||||
|
case ALUOpXor:
|
||||||
|
return "xor x"
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return "lsh x"
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return "rsh x"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown instruction: %#v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NegateA executes A = -A.
|
// NegateA executes A = -A.
|
||||||
type NegateA struct{}
|
type NegateA struct{}
|
||||||
|
|
||||||
@ -301,6 +490,11 @@ func (a NegateA) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a NegateA) String() string {
|
||||||
|
return fmt.Sprintf("neg")
|
||||||
|
}
|
||||||
|
|
||||||
// Jump skips the following Skip instructions in the program.
|
// Jump skips the following Skip instructions in the program.
|
||||||
type Jump struct {
|
type Jump struct {
|
||||||
Skip uint32
|
Skip uint32
|
||||||
@ -309,11 +503,16 @@ type Jump struct {
|
|||||||
// Assemble implements the Instruction Assemble method.
|
// Assemble implements the Instruction Assemble method.
|
||||||
func (a Jump) Assemble() (RawInstruction, error) {
|
func (a Jump) Assemble() (RawInstruction, error) {
|
||||||
return RawInstruction{
|
return RawInstruction{
|
||||||
Op: opClsJump | opJumpAlways,
|
Op: opClsJump | uint16(opJumpAlways),
|
||||||
K: a.Skip,
|
K: a.Skip,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a Jump) String() string {
|
||||||
|
return fmt.Sprintf("ja %d", a.Skip)
|
||||||
|
}
|
||||||
|
|
||||||
// JumpIf skips the following Skip instructions in the program if A
|
// JumpIf skips the following Skip instructions in the program if A
|
||||||
// <Cond> Val is true.
|
// <Cond> Val is true.
|
||||||
type JumpIf struct {
|
type JumpIf struct {
|
||||||
@ -325,11 +524,39 @@ type JumpIf struct {
|
|||||||
|
|
||||||
// Assemble implements the Instruction Assemble method.
|
// Assemble implements the Instruction Assemble method.
|
||||||
func (a JumpIf) Assemble() (RawInstruction, error) {
|
func (a JumpIf) Assemble() (RawInstruction, error) {
|
||||||
|
return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a JumpIf) String() string {
|
||||||
|
return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JumpIfX skips the following Skip instructions in the program if A
|
||||||
|
// <Cond> X is true.
|
||||||
|
type JumpIfX struct {
|
||||||
|
Cond JumpTest
|
||||||
|
SkipTrue uint8
|
||||||
|
SkipFalse uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a JumpIfX) Assemble() (RawInstruction, error) {
|
||||||
|
return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a JumpIfX) String() string {
|
||||||
|
return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jumpToRaw assembles a jump instruction into a RawInstruction
|
||||||
|
func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) {
|
||||||
var (
|
var (
|
||||||
cond uint16
|
cond jumpOp
|
||||||
flip bool
|
flip bool
|
||||||
)
|
)
|
||||||
switch a.Cond {
|
switch test {
|
||||||
case JumpEqual:
|
case JumpEqual:
|
||||||
cond = opJumpEqual
|
cond = opJumpEqual
|
||||||
case JumpNotEqual:
|
case JumpNotEqual:
|
||||||
@ -347,20 +574,65 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
|
|||||||
case JumpBitsNotSet:
|
case JumpBitsNotSet:
|
||||||
cond, flip = opJumpSet, true
|
cond, flip = opJumpSet, true
|
||||||
default:
|
default:
|
||||||
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond)
|
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test)
|
||||||
}
|
}
|
||||||
jt, jf := a.SkipTrue, a.SkipFalse
|
jt, jf := skipTrue, skipFalse
|
||||||
if flip {
|
if flip {
|
||||||
jt, jf = jf, jt
|
jt, jf = jf, jt
|
||||||
}
|
}
|
||||||
return RawInstruction{
|
return RawInstruction{
|
||||||
Op: opClsJump | cond,
|
Op: opClsJump | uint16(cond) | uint16(operand),
|
||||||
Jt: jt,
|
Jt: jt,
|
||||||
Jf: jf,
|
Jf: jf,
|
||||||
K: a.Val,
|
K: k,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jumpToString converts a jump instruction to assembler notation
|
||||||
|
func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string {
|
||||||
|
switch cond {
|
||||||
|
// K == A
|
||||||
|
case JumpEqual:
|
||||||
|
return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq")
|
||||||
|
// K != A
|
||||||
|
case JumpNotEqual:
|
||||||
|
return fmt.Sprintf("jneq %s,%d", operand, skipTrue)
|
||||||
|
// K > A
|
||||||
|
case JumpGreaterThan:
|
||||||
|
return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle")
|
||||||
|
// K < A
|
||||||
|
case JumpLessThan:
|
||||||
|
return fmt.Sprintf("jlt %s,%d", operand, skipTrue)
|
||||||
|
// K >= A
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt")
|
||||||
|
// K <= A
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
return fmt.Sprintf("jle %s,%d", operand, skipTrue)
|
||||||
|
// K & A != 0
|
||||||
|
case JumpBitsSet:
|
||||||
|
if skipFalse > 0 {
|
||||||
|
return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("jset %s,%d", operand, skipTrue)
|
||||||
|
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("unknown JumpTest %#v", cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string {
|
||||||
|
if skipTrue > 0 {
|
||||||
|
if skipFalse > 0 {
|
||||||
|
return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
// RetA exits the BPF program, returning the value of register A.
|
// RetA exits the BPF program, returning the value of register A.
|
||||||
type RetA struct{}
|
type RetA struct{}
|
||||||
|
|
||||||
@ -371,6 +643,11 @@ func (a RetA) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a RetA) String() string {
|
||||||
|
return fmt.Sprintf("ret a")
|
||||||
|
}
|
||||||
|
|
||||||
// RetConstant exits the BPF program, returning a constant value.
|
// RetConstant exits the BPF program, returning a constant value.
|
||||||
type RetConstant struct {
|
type RetConstant struct {
|
||||||
Val uint32
|
Val uint32
|
||||||
@ -384,6 +661,11 @@ func (a RetConstant) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a RetConstant) String() string {
|
||||||
|
return fmt.Sprintf("ret #%d", a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
// TXA copies the value of register X to register A.
|
// TXA copies the value of register X to register A.
|
||||||
type TXA struct{}
|
type TXA struct{}
|
||||||
|
|
||||||
@ -394,6 +676,11 @@ func (a TXA) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a TXA) String() string {
|
||||||
|
return fmt.Sprintf("txa")
|
||||||
|
}
|
||||||
|
|
||||||
// TAX copies the value of register A to register X.
|
// TAX copies the value of register A to register X.
|
||||||
type TAX struct{}
|
type TAX struct{}
|
||||||
|
|
||||||
@ -404,6 +691,11 @@ func (a TAX) Assemble() (RawInstruction, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the instruction in assembler notation.
|
||||||
|
func (a TAX) String() string {
|
||||||
|
return fmt.Sprintf("tax")
|
||||||
|
}
|
||||||
|
|
||||||
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
||||||
var (
|
var (
|
||||||
cls uint16
|
cls uint16
|
||||||
|
10
vendor/golang.org/x/net/bpf/setter.go
generated
vendored
Normal file
10
vendor/golang.org/x/net/bpf/setter.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
// A Setter is a type which can attach a compiled BPF filter to itself.
|
||||||
|
type Setter interface {
|
||||||
|
SetBPF(filter []RawInstruction) error
|
||||||
|
}
|
10
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
10
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
@ -35,6 +35,13 @@ func NewVM(filter []Instruction) (*VM, error) {
|
|||||||
if check <= int(ins.SkipFalse) {
|
if check <= int(ins.SkipFalse) {
|
||||||
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
||||||
}
|
}
|
||||||
|
case JumpIfX:
|
||||||
|
if check <= int(ins.SkipTrue) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
||||||
|
}
|
||||||
|
if check <= int(ins.SkipFalse) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
||||||
|
}
|
||||||
// Check for division or modulus by zero
|
// Check for division or modulus by zero
|
||||||
case ALUOpConstant:
|
case ALUOpConstant:
|
||||||
if ins.Val != 0 {
|
if ins.Val != 0 {
|
||||||
@ -109,6 +116,9 @@ func (v *VM) Run(in []byte) (int, error) {
|
|||||||
case JumpIf:
|
case JumpIf:
|
||||||
jump := jumpIf(ins, regA)
|
jump := jumpIf(ins, regA)
|
||||||
i += jump
|
i += jump
|
||||||
|
case JumpIfX:
|
||||||
|
jump := jumpIfX(ins, regA, regX)
|
||||||
|
i += jump
|
||||||
case LoadAbsolute:
|
case LoadAbsolute:
|
||||||
regA, ok = loadAbsolute(ins, in)
|
regA, ok = loadAbsolute(ins, in)
|
||||||
case LoadConstant:
|
case LoadConstant:
|
||||||
|
35
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
35
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
@ -55,34 +55,41 @@ func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func jumpIf(ins JumpIf, value uint32) int {
|
func jumpIf(ins JumpIf, regA uint32) int {
|
||||||
var ok bool
|
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
|
||||||
inV := uint32(ins.Val)
|
}
|
||||||
|
|
||||||
switch ins.Cond {
|
func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
|
||||||
|
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
|
||||||
|
}
|
||||||
|
|
||||||
|
func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
switch cond {
|
||||||
case JumpEqual:
|
case JumpEqual:
|
||||||
ok = value == inV
|
ok = regA == value
|
||||||
case JumpNotEqual:
|
case JumpNotEqual:
|
||||||
ok = value != inV
|
ok = regA != value
|
||||||
case JumpGreaterThan:
|
case JumpGreaterThan:
|
||||||
ok = value > inV
|
ok = regA > value
|
||||||
case JumpLessThan:
|
case JumpLessThan:
|
||||||
ok = value < inV
|
ok = regA < value
|
||||||
case JumpGreaterOrEqual:
|
case JumpGreaterOrEqual:
|
||||||
ok = value >= inV
|
ok = regA >= value
|
||||||
case JumpLessOrEqual:
|
case JumpLessOrEqual:
|
||||||
ok = value <= inV
|
ok = regA <= value
|
||||||
case JumpBitsSet:
|
case JumpBitsSet:
|
||||||
ok = (value & inV) != 0
|
ok = (regA & value) != 0
|
||||||
case JumpBitsNotSet:
|
case JumpBitsNotSet:
|
||||||
ok = (value & inV) == 0
|
ok = (regA & value) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
return int(ins.SkipTrue)
|
return int(skipTrue)
|
||||||
}
|
}
|
||||||
|
|
||||||
return int(ins.SkipFalse)
|
return int(skipFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
||||||
|
109
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
109
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
@ -1,44 +1,40 @@
|
|||||||
// go generate gen.go
|
// go generate gen.go
|
||||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
|
|
||||||
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
||||||
package iana
|
package iana
|
||||||
|
|
||||||
// Differentiated Services Field Codepoints (DSCP), Updated: 2013-06-25
|
// Differentiated Services Field Codepoints (DSCP), Updated: 2018-05-04
|
||||||
const (
|
const (
|
||||||
DiffServCS0 = 0x0 // CS0
|
DiffServCS0 = 0x00 // CS0
|
||||||
DiffServCS1 = 0x20 // CS1
|
DiffServCS1 = 0x20 // CS1
|
||||||
DiffServCS2 = 0x40 // CS2
|
DiffServCS2 = 0x40 // CS2
|
||||||
DiffServCS3 = 0x60 // CS3
|
DiffServCS3 = 0x60 // CS3
|
||||||
DiffServCS4 = 0x80 // CS4
|
DiffServCS4 = 0x80 // CS4
|
||||||
DiffServCS5 = 0xa0 // CS5
|
DiffServCS5 = 0xa0 // CS5
|
||||||
DiffServCS6 = 0xc0 // CS6
|
DiffServCS6 = 0xc0 // CS6
|
||||||
DiffServCS7 = 0xe0 // CS7
|
DiffServCS7 = 0xe0 // CS7
|
||||||
DiffServAF11 = 0x28 // AF11
|
DiffServAF11 = 0x28 // AF11
|
||||||
DiffServAF12 = 0x30 // AF12
|
DiffServAF12 = 0x30 // AF12
|
||||||
DiffServAF13 = 0x38 // AF13
|
DiffServAF13 = 0x38 // AF13
|
||||||
DiffServAF21 = 0x48 // AF21
|
DiffServAF21 = 0x48 // AF21
|
||||||
DiffServAF22 = 0x50 // AF22
|
DiffServAF22 = 0x50 // AF22
|
||||||
DiffServAF23 = 0x58 // AF23
|
DiffServAF23 = 0x58 // AF23
|
||||||
DiffServAF31 = 0x68 // AF31
|
DiffServAF31 = 0x68 // AF31
|
||||||
DiffServAF32 = 0x70 // AF32
|
DiffServAF32 = 0x70 // AF32
|
||||||
DiffServAF33 = 0x78 // AF33
|
DiffServAF33 = 0x78 // AF33
|
||||||
DiffServAF41 = 0x88 // AF41
|
DiffServAF41 = 0x88 // AF41
|
||||||
DiffServAF42 = 0x90 // AF42
|
DiffServAF42 = 0x90 // AF42
|
||||||
DiffServAF43 = 0x98 // AF43
|
DiffServAF43 = 0x98 // AF43
|
||||||
DiffServEFPHB = 0xb8 // EF PHB
|
DiffServEF = 0xb8 // EF
|
||||||
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
||||||
|
NotECNTransport = 0x00 // Not-ECT (Not ECN-Capable Transport)
|
||||||
|
ECNTransport1 = 0x01 // ECT(1) (ECN-Capable Transport(1))
|
||||||
|
ECNTransport0 = 0x02 // ECT(0) (ECN-Capable Transport(0))
|
||||||
|
CongestionExperienced = 0x03 // CE (Congestion Experienced)
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
|
// Protocol Numbers, Updated: 2017-10-13
|
||||||
const (
|
|
||||||
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
|
|
||||||
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
|
|
||||||
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
|
|
||||||
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Protocol Numbers, Updated: 2015-10-06
|
|
||||||
const (
|
const (
|
||||||
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
||||||
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||||
@ -178,3 +174,50 @@ const (
|
|||||||
ProtocolROHC = 142 // Robust Header Compression
|
ProtocolROHC = 142 // Robust Header Compression
|
||||||
ProtocolReserved = 255 // Reserved
|
ProtocolReserved = 255 // Reserved
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Address Family Numbers, Updated: 2018-04-02
|
||||||
|
const (
|
||||||
|
AddrFamilyIPv4 = 1 // IP (IP version 4)
|
||||||
|
AddrFamilyIPv6 = 2 // IP6 (IP version 6)
|
||||||
|
AddrFamilyNSAP = 3 // NSAP
|
||||||
|
AddrFamilyHDLC = 4 // HDLC (8-bit multidrop)
|
||||||
|
AddrFamilyBBN1822 = 5 // BBN 1822
|
||||||
|
AddrFamily802 = 6 // 802 (includes all 802 media plus Ethernet "canonical format")
|
||||||
|
AddrFamilyE163 = 7 // E.163
|
||||||
|
AddrFamilyE164 = 8 // E.164 (SMDS, Frame Relay, ATM)
|
||||||
|
AddrFamilyF69 = 9 // F.69 (Telex)
|
||||||
|
AddrFamilyX121 = 10 // X.121 (X.25, Frame Relay)
|
||||||
|
AddrFamilyIPX = 11 // IPX
|
||||||
|
AddrFamilyAppletalk = 12 // Appletalk
|
||||||
|
AddrFamilyDecnetIV = 13 // Decnet IV
|
||||||
|
AddrFamilyBanyanVines = 14 // Banyan Vines
|
||||||
|
AddrFamilyE164withSubaddress = 15 // E.164 with NSAP format subaddress
|
||||||
|
AddrFamilyDNS = 16 // DNS (Domain Name System)
|
||||||
|
AddrFamilyDistinguishedName = 17 // Distinguished Name
|
||||||
|
AddrFamilyASNumber = 18 // AS Number
|
||||||
|
AddrFamilyXTPoverIPv4 = 19 // XTP over IP version 4
|
||||||
|
AddrFamilyXTPoverIPv6 = 20 // XTP over IP version 6
|
||||||
|
AddrFamilyXTPnativemodeXTP = 21 // XTP native mode XTP
|
||||||
|
AddrFamilyFibreChannelWorldWidePortName = 22 // Fibre Channel World-Wide Port Name
|
||||||
|
AddrFamilyFibreChannelWorldWideNodeName = 23 // Fibre Channel World-Wide Node Name
|
||||||
|
AddrFamilyGWID = 24 // GWID
|
||||||
|
AddrFamilyL2VPN = 25 // AFI for L2VPN information
|
||||||
|
AddrFamilyMPLSTPSectionEndpointID = 26 // MPLS-TP Section Endpoint Identifier
|
||||||
|
AddrFamilyMPLSTPLSPEndpointID = 27 // MPLS-TP LSP Endpoint Identifier
|
||||||
|
AddrFamilyMPLSTPPseudowireEndpointID = 28 // MPLS-TP Pseudowire Endpoint Identifier
|
||||||
|
AddrFamilyMTIPv4 = 29 // MT IP: Multi-Topology IP version 4
|
||||||
|
AddrFamilyMTIPv6 = 30 // MT IPv6: Multi-Topology IP version 6
|
||||||
|
AddrFamilyEIGRPCommonServiceFamily = 16384 // EIGRP Common Service Family
|
||||||
|
AddrFamilyEIGRPIPv4ServiceFamily = 16385 // EIGRP IPv4 Service Family
|
||||||
|
AddrFamilyEIGRPIPv6ServiceFamily = 16386 // EIGRP IPv6 Service Family
|
||||||
|
AddrFamilyLISPCanonicalAddressFormat = 16387 // LISP Canonical Address Format (LCAF)
|
||||||
|
AddrFamilyBGPLS = 16388 // BGP-LS
|
||||||
|
AddrFamily48bitMAC = 16389 // 48-bit MAC
|
||||||
|
AddrFamily64bitMAC = 16390 // 64-bit MAC
|
||||||
|
AddrFamilyOUI = 16391 // OUI
|
||||||
|
AddrFamilyMACFinal24bits = 16392 // MAC/24
|
||||||
|
AddrFamilyMACFinal40bits = 16393 // MAC/40
|
||||||
|
AddrFamilyIPv6Initial64bits = 16394 // IPv6/64
|
||||||
|
AddrFamilyRBridgePortID = 16395 // RBridge Port ID
|
||||||
|
AddrFamilyTRILLNickname = 16396 // TRILL Nickname
|
||||||
|
)
|
||||||
|
286
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
286
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@ -28,23 +28,23 @@ var registries = []struct {
|
|||||||
parse func(io.Writer, io.Reader) error
|
parse func(io.Writer, io.Reader) error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
||||||
parseDSCPRegistry,
|
parseDSCPRegistry,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
|
"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||||
parseTOSTCByte,
|
parseProtocolNumbers,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
|
||||||
parseProtocolNumbers,
|
parseAddrFamilyNumbers,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var bb bytes.Buffer
|
var bb bytes.Buffer
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||||
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
||||||
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
||||||
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
||||||
for _, r := range registries {
|
for _, r := range registries {
|
||||||
@ -81,31 +81,39 @@ func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
|||||||
if err := dec.Decode(&dr); err != nil {
|
if err := dec.Decode(&dr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
drs := dr.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
||||||
fmt.Fprintf(w, "const (\n")
|
fmt.Fprintf(w, "const (\n")
|
||||||
for _, dr := range drs {
|
for _, dr := range dr.escapeDSCP() {
|
||||||
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
|
fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
|
||||||
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
||||||
}
|
}
|
||||||
|
for _, er := range dr.escapeECN() {
|
||||||
|
fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", er.OrigDescr)
|
||||||
|
}
|
||||||
fmt.Fprintf(w, ")\n")
|
fmt.Fprintf(w, ")\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type dscpRegistry struct {
|
type dscpRegistry struct {
|
||||||
XMLName xml.Name `xml:"registry"`
|
XMLName xml.Name `xml:"registry"`
|
||||||
Title string `xml:"title"`
|
Title string `xml:"title"`
|
||||||
Updated string `xml:"updated"`
|
Updated string `xml:"updated"`
|
||||||
Note string `xml:"note"`
|
Note string `xml:"note"`
|
||||||
RegTitle string `xml:"registry>title"`
|
Registries []struct {
|
||||||
PoolRecords []struct {
|
Title string `xml:"title"`
|
||||||
Name string `xml:"name"`
|
Registries []struct {
|
||||||
Space string `xml:"space"`
|
Title string `xml:"title"`
|
||||||
} `xml:"registry>record"`
|
Records []struct {
|
||||||
Records []struct {
|
Name string `xml:"name"`
|
||||||
Name string `xml:"name"`
|
Space string `xml:"space"`
|
||||||
Space string `xml:"space"`
|
} `xml:"record"`
|
||||||
} `xml:"registry>registry>record"`
|
} `xml:"registry"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"record"`
|
||||||
|
} `xml:"registry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type canonDSCPRecord struct {
|
type canonDSCPRecord struct {
|
||||||
@ -114,92 +122,84 @@ type canonDSCPRecord struct {
|
|||||||
Value int
|
Value int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (drr *dscpRegistry) escape() []canonDSCPRecord {
|
func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
|
||||||
drs := make([]canonDSCPRecord, len(drr.Records))
|
var drs []canonDSCPRecord
|
||||||
sr := strings.NewReplacer(
|
for _, preg := range drr.Registries {
|
||||||
"+", "",
|
if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, dr := range drr.Records {
|
|
||||||
s := strings.TrimSpace(dr.Name)
|
|
||||||
drs[i].OrigName = s
|
|
||||||
drs[i].Name = sr.Replace(s)
|
|
||||||
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
drs[i].Value = int(n) << 2
|
for _, reg := range preg.Registries {
|
||||||
|
if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
drs = make([]canonDSCPRecord, len(reg.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, dr := range reg.Records {
|
||||||
|
s := strings.TrimSpace(dr.Name)
|
||||||
|
drs[i].OrigName = s
|
||||||
|
drs[i].Name = sr.Replace(s)
|
||||||
|
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
drs[i].Value = int(n) << 2
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return drs
|
return drs
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTOSTCByte(w io.Writer, r io.Reader) error {
|
type canonECNRecord struct {
|
||||||
dec := xml.NewDecoder(r)
|
OrigDescr string
|
||||||
var ttb tosTCByte
|
Descr string
|
||||||
if err := dec.Decode(&ttb); err != nil {
|
Value int
|
||||||
return err
|
|
||||||
}
|
|
||||||
trs := ttb.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, tr := range trs {
|
|
||||||
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type tosTCByte struct {
|
func (drr *dscpRegistry) escapeECN() []canonECNRecord {
|
||||||
XMLName xml.Name `xml:"registry"`
|
var ers []canonECNRecord
|
||||||
Title string `xml:"title"`
|
for _, reg := range drr.Registries {
|
||||||
Updated string `xml:"updated"`
|
if !strings.Contains(reg.Title, "ECN Field") {
|
||||||
Note string `xml:"note"`
|
|
||||||
RegTitle string `xml:"registry>title"`
|
|
||||||
Records []struct {
|
|
||||||
Binary string `xml:"binary"`
|
|
||||||
Keyword string `xml:"keyword"`
|
|
||||||
} `xml:"registry>record"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonTOSTCByteRecord struct {
|
|
||||||
OrigKeyword string
|
|
||||||
Keyword string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
|
|
||||||
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Capable", "",
|
|
||||||
"(", "",
|
|
||||||
")", "",
|
|
||||||
"+", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, tr := range ttb.Records {
|
|
||||||
s := strings.TrimSpace(tr.Keyword)
|
|
||||||
trs[i].OrigKeyword = s
|
|
||||||
ss := strings.Split(s, " ")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
trs[i].Keyword = strings.Join(ss[1:], " ")
|
|
||||||
} else {
|
|
||||||
trs[i].Keyword = ss[0]
|
|
||||||
}
|
|
||||||
trs[i].Keyword = sr.Replace(trs[i].Keyword)
|
|
||||||
n, err := strconv.ParseUint(tr.Binary, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
trs[i].Value = int(n)
|
ers = make([]canonECNRecord, len(reg.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"Capable", "",
|
||||||
|
"Not-ECT", "",
|
||||||
|
"ECT(1)", "",
|
||||||
|
"ECT(0)", "",
|
||||||
|
"CE", "",
|
||||||
|
"(", "",
|
||||||
|
")", "",
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, er := range reg.Records {
|
||||||
|
s := strings.TrimSpace(er.Descr)
|
||||||
|
ers[i].OrigDescr = s
|
||||||
|
ss := strings.Split(s, " ")
|
||||||
|
if len(ss) > 1 {
|
||||||
|
ers[i].Descr = strings.Join(ss[1:], " ")
|
||||||
|
} else {
|
||||||
|
ers[i].Descr = ss[0]
|
||||||
|
}
|
||||||
|
ers[i].Descr = sr.Replace(er.Descr)
|
||||||
|
n, err := strconv.ParseUint(er.Value, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ers[i].Value = int(n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return trs
|
return ers
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||||
@ -291,3 +291,93 @@ func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
|||||||
}
|
}
|
||||||
return prs
|
return prs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var afn addrFamilylNumbers
|
||||||
|
if err := dec.Decode(&afn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
afrs := afn.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, afr := range afrs {
|
||||||
|
if afr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", afr.Descr)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type addrFamilylNumbers struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Note string `xml:"registry>note"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonAddrFamilyRecord struct {
|
||||||
|
Name string
|
||||||
|
Descr string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
|
||||||
|
afrs := make([]canonAddrFamilyRecord, len(afn.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"IP version 4", "IPv4",
|
||||||
|
"IP version 6", "IPv6",
|
||||||
|
"Identifier", "ID",
|
||||||
|
"-", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, afr := range afn.Records {
|
||||||
|
if strings.Contains(afr.Descr, "Unassigned") ||
|
||||||
|
strings.Contains(afr.Descr, "Reserved") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
afrs[i].Descr = afr.Descr
|
||||||
|
s := strings.TrimSpace(afr.Descr)
|
||||||
|
switch s {
|
||||||
|
case "IP (IP version 4)":
|
||||||
|
afrs[i].Name = "IPv4"
|
||||||
|
case "IP6 (IP version 6)":
|
||||||
|
afrs[i].Name = "IPv6"
|
||||||
|
case "AFI for L2VPN information":
|
||||||
|
afrs[i].Name = "L2VPN"
|
||||||
|
case "E.164 with NSAP format subaddress":
|
||||||
|
afrs[i].Name = "E164withSubaddress"
|
||||||
|
case "MT IP: Multi-Topology IP version 4":
|
||||||
|
afrs[i].Name = "MTIPv4"
|
||||||
|
case "MAC/24":
|
||||||
|
afrs[i].Name = "MACFinal24bits"
|
||||||
|
case "MAC/40":
|
||||||
|
afrs[i].Name = "MACFinal40bits"
|
||||||
|
case "IPv6/64":
|
||||||
|
afrs[i].Name = "IPv6Initial64bits"
|
||||||
|
default:
|
||||||
|
n := strings.Index(s, "(")
|
||||||
|
if n > 0 {
|
||||||
|
s = s[:n]
|
||||||
|
}
|
||||||
|
n = strings.Index(s, ":")
|
||||||
|
if n > 0 {
|
||||||
|
s = s[:n]
|
||||||
|
}
|
||||||
|
afrs[i].Name = sr.Replace(s)
|
||||||
|
}
|
||||||
|
afrs[i].Value, _ = strconv.Atoi(afr.Value)
|
||||||
|
}
|
||||||
|
return afrs
|
||||||
|
}
|
||||||
|
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return int(h.Len) }
|
||||||
|
func (h *cmsghdr) lvl() int { return int(h.Level) }
|
||||||
|
func (h *cmsghdr) typ() int { return int(h.Type) }
|
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
13
vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint64(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct{}
|
||||||
|
|
||||||
|
const sizeofCmsghdr = 0
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return 0 }
|
||||||
|
func (h *cmsghdr) lvl() int { return 0 }
|
||||||
|
func (h *cmsghdr) typ() int { return 0 }
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {}
|
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/in6.h>
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <sys/socket.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type mmsghdr C.struct_mmsghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = C.AF_UNSPEC
|
||||||
|
sysAF_INET = C.AF_INET
|
||||||
|
sysAF_INET6 = C.AF_INET6
|
||||||
|
|
||||||
|
sysSOCK_RAW = C.SOCK_RAW
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec C.struct_iovec
|
||||||
|
|
||||||
|
type msghdr C.struct_msghdr
|
||||||
|
|
||||||
|
type cmsghdr C.struct_cmsghdr
|
||||||
|
|
||||||
|
type sockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sockaddrInet6 C.struct_sockaddr_in6
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = C.sizeof_struct_iovec
|
||||||
|
sizeofMsghdr = C.sizeof_struct_msghdr
|
||||||
|
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||||
|
|
||||||
|
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||||
|
)
|
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
31
vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errEAGAIN error = syscall.EAGAIN
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
errENOENT error = syscall.ENOENT
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.EAGAIN:
|
||||||
|
return errEAGAIN
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
case syscall.ENOENT:
|
||||||
|
return errENOENT
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/internal/socket/error_windows.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING
|
||||||
|
errEINVAL error = syscall.EINVAL
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent allocations
|
||||||
|
// at runtime.
|
||||||
|
func errnoErr(errno syscall.Errno) error {
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case syscall.ERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
case syscall.EINVAL:
|
||||||
|
return errEINVAL
|
||||||
|
}
|
||||||
|
return errno
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint32(l)
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(l)
|
||||||
|
}
|
19
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
19
vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {
|
||||||
|
l := len(b)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.Base = (*int8)(unsafe.Pointer(&b[0]))
|
||||||
|
v.Len = uint64(l)
|
||||||
|
}
|
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type iovec struct{}
|
||||||
|
|
||||||
|
func (v *iovec) set(b []byte) {}
|
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !linux,!netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdr struct{}
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
return nil
|
||||||
|
}
|
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
42
vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build linux netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type mmsghdrs []mmsghdr
|
||||||
|
|
||||||
|
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
|
||||||
|
for i := range hs {
|
||||||
|
vs := make([]iovec, len(ms[i].Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if parseFn != nil {
|
||||||
|
sa = make([]byte, sizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
if marshalFn != nil {
|
||||||
|
sa = marshalFn(ms[i].Addr)
|
||||||
|
}
|
||||||
|
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
|
||||||
|
for i := range hs {
|
||||||
|
ms[i].N = int(hs[i].Len)
|
||||||
|
ms[i].NN = hs[i].Hdr.controllen()
|
||||||
|
ms[i].Flags = hs[i].Hdr.flags()
|
||||||
|
if parseFn != nil {
|
||||||
|
var err error
|
||||||
|
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
39
vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.setIov(vs)
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||||
|
h.Controllen = uint32(len(oob))
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) name() []byte {
|
||||||
|
if h.Name != nil && h.Namelen > 0 {
|
||||||
|
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Controllen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(h.Flags)
|
||||||
|
}
|
16
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
l := len(vs)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = int32(l)
|
||||||
|
}
|
36
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
Normal file
36
vendor/golang.org/x/net/internal/socket/msghdr_linux.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
h.setIov(vs)
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.setControl(oob)
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) name() []byte {
|
||||||
|
if h.Name != nil && h.Namelen > 0 {
|
||||||
|
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Controllen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(h.Flags)
|
||||||
|
}
|
24
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
Normal file
24
vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
l := len(vs)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint32(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) setControl(b []byte) {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
h.Controllen = uint32(len(b))
|
||||||
|
}
|
24
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
Normal file
24
vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
l := len(vs)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint64(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) setControl(b []byte) {
|
||||||
|
h.Control = (*byte)(unsafe.Pointer(&b[0]))
|
||||||
|
h.Controllen = uint64(len(b))
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *msghdr) setIov(vs []iovec) {
|
||||||
|
l := len(vs)
|
||||||
|
if l == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = uint32(l)
|
||||||
|
}
|
36
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
Normal file
36
vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
|
for i := range vs {
|
||||||
|
vs[i].set(bs[i])
|
||||||
|
}
|
||||||
|
if len(vs) > 0 {
|
||||||
|
h.Iov = &vs[0]
|
||||||
|
h.Iovlen = int32(len(vs))
|
||||||
|
}
|
||||||
|
if len(oob) > 0 {
|
||||||
|
h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
|
||||||
|
h.Accrightslen = int32(len(oob))
|
||||||
|
}
|
||||||
|
if sa != nil {
|
||||||
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
|
h.Namelen = uint32(len(sa))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) controllen() int {
|
||||||
|
return int(h.Accrightslen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *msghdr) flags() int {
|
||||||
|
return int(NativeEndian.Uint32(h.Pad_cgo_2[:]))
|
||||||
|
}
|
14
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
Normal file
14
vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type msghdr struct{}
|
||||||
|
|
||||||
|
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {}
|
||||||
|
func (h *msghdr) name() []byte { return nil }
|
||||||
|
func (h *msghdr) controllen() int { return 0 }
|
||||||
|
func (h *msghdr) flags() int { return 0 }
|
66
vendor/golang.org/x/net/internal/socket/rawconn.go
generated
vendored
Normal file
66
vendor/golang.org/x/net/internal/socket/rawconn.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Conn represents a raw connection.
|
||||||
|
type Conn struct {
|
||||||
|
network string
|
||||||
|
c syscall.RawConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn returns a new raw connection.
|
||||||
|
func NewConn(c net.Conn) (*Conn, error) {
|
||||||
|
var err error
|
||||||
|
var cc Conn
|
||||||
|
switch c := c.(type) {
|
||||||
|
case *net.TCPConn:
|
||||||
|
cc.network = "tcp"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
case *net.UDPConn:
|
||||||
|
cc.network = "udp"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
case *net.IPConn:
|
||||||
|
cc.network = "ip"
|
||||||
|
cc.c, err = c.SyscallConn()
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown connection type")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) get(c *Conn, b []byte) (int, error) {
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) {
|
||||||
|
n, operr = getsockopt(s, o.Level, o.Name, b)
|
||||||
|
}
|
||||||
|
if err := c.c.Control(fn); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return n, os.NewSyscallError("getsockopt", operr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Option) set(c *Conn, b []byte) error {
|
||||||
|
var operr error
|
||||||
|
fn := func(s uintptr) {
|
||||||
|
operr = setsockopt(s, o.Level, o.Name, b)
|
||||||
|
}
|
||||||
|
if err := c.c.Control(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", operr)
|
||||||
|
}
|
74
vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
Normal file
74
vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
hs := make(mmsghdrs, len(ms))
|
||||||
|
var parseFn func([]byte, string) (net.Addr, error)
|
||||||
|
if c.network != "tcp" {
|
||||||
|
parseFn = parseInetAddr
|
||||||
|
}
|
||||||
|
if err := hs.pack(ms, parseFn, nil); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = recvmmsg(s, hs, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Read(fn); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return n, os.NewSyscallError("recvmmsg", operr)
|
||||||
|
}
|
||||||
|
if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
hs := make(mmsghdrs, len(ms))
|
||||||
|
var marshalFn func(net.Addr) []byte
|
||||||
|
if c.network != "tcp" {
|
||||||
|
marshalFn = marshalInetAddr
|
||||||
|
}
|
||||||
|
if err := hs.pack(ms, nil, marshalFn); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = sendmmsg(s, hs, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Write(fn); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return n, os.NewSyscallError("sendmmsg", operr)
|
||||||
|
}
|
||||||
|
if err := hs[:n].unpack(ms[:n], nil, ""); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
77
vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Conn) recvMsg(m *Message, flags int) error {
|
||||||
|
var h msghdr
|
||||||
|
vs := make([]iovec, len(m.Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if c.network != "tcp" {
|
||||||
|
sa = make([]byte, sizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
h.pack(vs, m.Buffers, m.OOB, sa)
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = recvmsg(s, &h, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Read(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return os.NewSyscallError("recvmsg", operr)
|
||||||
|
}
|
||||||
|
if c.network != "tcp" {
|
||||||
|
var err error
|
||||||
|
m.Addr, err = parseInetAddr(sa[:], c.network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.N = n
|
||||||
|
m.NN = h.controllen()
|
||||||
|
m.Flags = h.flags()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsg(m *Message, flags int) error {
|
||||||
|
var h msghdr
|
||||||
|
vs := make([]iovec, len(m.Buffers))
|
||||||
|
var sa []byte
|
||||||
|
if m.Addr != nil {
|
||||||
|
sa = marshalInetAddr(m.Addr)
|
||||||
|
}
|
||||||
|
h.pack(vs, m.Buffers, m.OOB, sa)
|
||||||
|
var operr error
|
||||||
|
var n int
|
||||||
|
fn := func(s uintptr) bool {
|
||||||
|
n, operr = sendmsg(s, &h, flags)
|
||||||
|
if operr == syscall.EAGAIN {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := c.c.Write(fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if operr != nil {
|
||||||
|
return os.NewSyscallError("sendmsg", operr)
|
||||||
|
}
|
||||||
|
m.N = n
|
||||||
|
m.NN = len(m.OOB)
|
||||||
|
return nil
|
||||||
|
}
|
18
vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
Normal file
18
vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.9
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
|
||||||
|
return 0, errors.New("not implemented")
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user