build: update github.com/vishvananda/netlink to 1.3.0
This includes a breaking change:
acdc658b86
route.Dst is now a zero IPNet instead of nil
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
This commit is contained in:
parent
5188dc8a19
commit
d924f05e12
4
go.mod
4
go.mod
@ -1,6 +1,6 @@
|
||||
module github.com/containernetworking/plugins
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.12.4
|
||||
@ -19,7 +19,7 @@ require (
|
||||
github.com/onsi/gomega v1.33.1
|
||||
github.com/opencontainers/selinux v1.11.0
|
||||
github.com/safchain/ethtool v0.4.1
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
golang.org/x/sys v0.21.0
|
||||
)
|
||||
|
||||
|
10
go.sum
10
go.sum
@ -121,9 +121,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -167,9 +167,7 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -177,6 +175,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
@ -50,3 +50,16 @@ func AddDefaultRoute(gw net.IP, dev netlink.Link) error {
|
||||
}
|
||||
return AddRoute(defNet, gw, dev)
|
||||
}
|
||||
|
||||
// IsIPNetZero check if the IPNet is "0.0.0.0/0" or "::/0"
|
||||
// This is needed as go-netlink replaces nil Dst with a '0' IPNet since
|
||||
// https://github.com/vishvananda/netlink/commit/acdc658b8613655ddb69f978e9fb4cf413e2b830
|
||||
func IsIPNetZero(ipnet *net.IPNet) bool {
|
||||
if ipnet == nil {
|
||||
return true
|
||||
}
|
||||
if ones, _ := ipnet.Mask.Size(); ones != 0 {
|
||||
return false
|
||||
}
|
||||
return ipnet.IP.Equal(net.IPv4zero) || ipnet.IP.Equal(net.IPv6zero)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func DeleteConntrackEntriesForDstIP(dstIP string, protocol uint8) error {
|
||||
filter.AddIP(netlink.ConntrackOrigDstIP, ip)
|
||||
filter.AddProtocol(protocol)
|
||||
|
||||
_, err := netlink.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter)
|
||||
_, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting connection tracking state for protocol: %d IP: %s, error: %v", protocol, ip, err)
|
||||
}
|
||||
@ -65,7 +65,7 @@ func DeleteConntrackEntriesForDstPort(port uint16, protocol uint8, family netlin
|
||||
filter.AddProtocol(protocol)
|
||||
filter.AddPort(netlink.ConntrackOrigDstPort, port)
|
||||
|
||||
_, err := netlink.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter)
|
||||
_, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting connection tracking state for protocol: %d Port: %d, error: %v", protocol, port, err)
|
||||
}
|
||||
|
@ -724,7 +724,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -809,7 +809,7 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, _ string) {
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1059,7 +1059,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1143,7 +1143,7 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, _ string) {
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1391,7 +1391,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1612,7 +1612,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
}
|
||||
|
||||
for _, v := range routeToDstIP {
|
||||
if v.Dst == nil {
|
||||
if ip.IsIPNetZero(v.Dst) {
|
||||
l, err := netlink.LinkByIndex(v.LinkIndex)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -67,7 +67,7 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
}
|
||||
|
||||
for _, v := range routeToDstIP {
|
||||
if v.Dst == nil {
|
||||
if ip.IsIPNetZero(v.Dst) {
|
||||
l, err := netlink.LinkByIndex(v.LinkIndex)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -291,6 +291,7 @@ var _ = Describe("sbr test", func() {
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Gw: net.IPv4(192, 168, 1, 1),
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Table: 100,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
})
|
||||
@ -491,6 +492,7 @@ var _ = Describe("sbr test", func() {
|
||||
}
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Gw: net.IPv4(192, 168, 1, 1),
|
||||
Table: 100,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
@ -498,6 +500,7 @@ var _ = Describe("sbr test", func() {
|
||||
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Gw: net.IPv4(192, 168, 101, 1),
|
||||
Table: 101,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
|
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
@ -1 +1,2 @@
|
||||
.idea/
|
||||
.vscode/
|
||||
|
52
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
52
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@ -74,17 +74,19 @@ func (h *Handle) AddrDel(link Link, addr *Addr) error {
|
||||
}
|
||||
|
||||
func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
|
||||
base := link.Attrs()
|
||||
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
|
||||
return fmt.Errorf("label must begin with interface name")
|
||||
}
|
||||
h.ensureIndex(base)
|
||||
|
||||
family := nl.GetIPFamily(addr.IP)
|
||||
|
||||
msg := nl.NewIfAddrmsg(family)
|
||||
msg.Index = uint32(base.Index)
|
||||
msg.Scope = uint8(addr.Scope)
|
||||
if link == nil {
|
||||
msg.Index = uint32(addr.LinkIndex)
|
||||
} else {
|
||||
base := link.Attrs()
|
||||
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
|
||||
return fmt.Errorf("label must begin with interface name")
|
||||
}
|
||||
h.ensureIndex(base)
|
||||
msg.Index = uint32(base.Index)
|
||||
}
|
||||
mask := addr.Mask
|
||||
if addr.Peer != nil {
|
||||
mask = addr.Peer.Mask
|
||||
@ -296,23 +298,24 @@ type AddrUpdate struct {
|
||||
// AddrSubscribe takes a chan down which notifications will be sent
|
||||
// when addresses change. Close the 'done' chan to stop subscription.
|
||||
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil)
|
||||
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
|
||||
// to choose the network namespace in which to subscribe (ns).
|
||||
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil)
|
||||
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// AddrSubscribeOptions contains a set of options to use with
|
||||
// AddrSubscribeWithOptions.
|
||||
type AddrSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveTimeout *unix.Timeval
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
|
||||
@ -323,10 +326,12 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize, options.ReceiveTimeout)
|
||||
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int, rcvTimeout *unix.Timeval) error {
|
||||
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvBufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -336,19 +341,18 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvBufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
s.Close()
|
||||
}()
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if listExisting {
|
||||
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
|
||||
unix.NLM_F_DUMP)
|
||||
|
45
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
45
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
@ -63,7 +63,19 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||
// BridgeVlanAdd adds a new vlan filter entry
|
||||
// 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 {
|
||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master)
|
||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanAddRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanAddRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanDel adds a new vlan filter entry
|
||||
@ -75,10 +87,22 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||
// BridgeVlanDel adds a new vlan filter entry
|
||||
// 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 {
|
||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master)
|
||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||
// BridgeVlanDelRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanDelRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
||||
@ -105,7 +129,20 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
||||
if untagged {
|
||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
||||
}
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
|
||||
if vidEnd != 0 {
|
||||
vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
|
||||
vlanEndInfo.Flags = vlanInfo.Flags
|
||||
|
||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
|
||||
vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize())
|
||||
} else {
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
}
|
||||
|
||||
req.AddData(br)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
|
22
vendor/github.com/vishvananda/netlink/chain.go
generated
vendored
Normal file
22
vendor/github.com/vishvananda/netlink/chain.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Chain contains the attributes of a Chain
|
||||
type Chain struct {
|
||||
Parent uint32
|
||||
Chain uint32
|
||||
}
|
||||
|
||||
func (c Chain) String() string {
|
||||
return fmt.Sprintf("{Parent: %d, Chain: %d}", c.Parent, c.Chain)
|
||||
}
|
||||
|
||||
func NewChain(parent uint32, chain uint32) Chain {
|
||||
return Chain{
|
||||
Parent: parent,
|
||||
Chain: chain,
|
||||
}
|
||||
}
|
112
vendor/github.com/vishvananda/netlink/chain_linux.go
generated
vendored
Normal file
112
vendor/github.com/vishvananda/netlink/chain_linux.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ChainDel will delete a chain from the system.
|
||||
func ChainDel(link Link, chain Chain) error {
|
||||
// Equivalent to: `tc chain del $chain`
|
||||
return pkgHandle.ChainDel(link, chain)
|
||||
}
|
||||
|
||||
// ChainDel will delete a chain from the system.
|
||||
// Equivalent to: `tc chain del $chain`
|
||||
func (h *Handle) ChainDel(link Link, chain Chain) error {
|
||||
return h.chainModify(unix.RTM_DELCHAIN, 0, link, chain)
|
||||
}
|
||||
|
||||
// ChainAdd will add a chain to the system.
|
||||
// Equivalent to: `tc chain add`
|
||||
func ChainAdd(link Link, chain Chain) error {
|
||||
return pkgHandle.ChainAdd(link, chain)
|
||||
}
|
||||
|
||||
// ChainAdd will add a chain to the system.
|
||||
// Equivalent to: `tc chain add`
|
||||
func (h *Handle) ChainAdd(link Link, chain Chain) error {
|
||||
return h.chainModify(
|
||||
unix.RTM_NEWCHAIN,
|
||||
unix.NLM_F_CREATE|unix.NLM_F_EXCL,
|
||||
link,
|
||||
chain)
|
||||
}
|
||||
|
||||
func (h *Handle) chainModify(cmd, flags int, link Link, chain Chain) error {
|
||||
req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
|
||||
index := int32(0)
|
||||
if link != nil {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
index = int32(base.Index)
|
||||
}
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
Ifindex: index,
|
||||
Parent: chain.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(chain.Chain)))
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ChainList gets a list of chains in the system.
|
||||
// Equivalent to: `tc chain list`.
|
||||
// The list can be filtered by link.
|
||||
func ChainList(link Link, parent uint32) ([]Chain, error) {
|
||||
return pkgHandle.ChainList(link, parent)
|
||||
}
|
||||
|
||||
// ChainList gets a list of chains in the system.
|
||||
// Equivalent to: `tc chain list`.
|
||||
// The list can be filtered by link.
|
||||
func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) {
|
||||
req := h.newNetlinkRequest(unix.RTM_GETCHAIN, unix.NLM_F_DUMP)
|
||||
index := int32(0)
|
||||
if link != nil {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
index = int32(base.Index)
|
||||
}
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
Ifindex: index,
|
||||
Parent: parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res []Chain
|
||||
for _, m := range msgs {
|
||||
msg := nl.DeserializeTcMsg(m)
|
||||
|
||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip chains from other interfaces
|
||||
if link != nil && msg.Ifindex != index {
|
||||
continue
|
||||
}
|
||||
|
||||
var chain Chain
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.TCA_CHAIN:
|
||||
chain.Chain = native.Uint32(attr.Value)
|
||||
chain.Parent = parent
|
||||
}
|
||||
}
|
||||
res = append(res, chain)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
2
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
@ -47,6 +47,7 @@ type ClassStatistics struct {
|
||||
Basic *GnetStatsBasic
|
||||
Queue *GnetStatsQueue
|
||||
RateEst *GnetStatsRateEst
|
||||
BasicHw *GnetStatsBasic // Hardward statistics added in kernel 4.20
|
||||
}
|
||||
|
||||
// NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0.
|
||||
@ -55,6 +56,7 @@ func NewClassStatistics() *ClassStatistics {
|
||||
Basic: &GnetStatsBasic{},
|
||||
Queue: &GnetStatsQueue{},
|
||||
RateEst: &GnetStatsRateEst{},
|
||||
BasicHw: &GnetStatsBasic{},
|
||||
}
|
||||
}
|
||||
|
||||
|
5
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
5
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
@ -388,6 +388,11 @@ func parseTcStats2(data []byte) (*ClassStatistics, error) {
|
||||
return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s",
|
||||
err, hex.Dump(datum.Value))
|
||||
}
|
||||
case nl.TCA_STATS_BASIC_HW:
|
||||
if err := parseGnetStats(datum.Value, stats.BasicHw); err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse ClassStatistics.BasicHw with: %v\n%s",
|
||||
err, hex.Dump(datum.Value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@ -55,10 +55,30 @@ func ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return pkgHandle.ConntrackTableFlush(table)
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackCreate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackUpdate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [ConntrackDeleteFilter] instead.
|
||||
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilter(table, family, filter)
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filters...)
|
||||
}
|
||||
|
||||
// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed
|
||||
@ -87,9 +107,51 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table using the handle
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func (h *Handle) ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_CREATE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func (h *Handle) ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_REPLACE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [Handle.ConntrackDeleteFilters] instead.
|
||||
func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return h.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
res, err := h.dumpConntrackTable(table, family)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -98,12 +160,16 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
|
||||
var matched uint
|
||||
for _, dataRaw := range res {
|
||||
flow := parseRawData(dataRaw)
|
||||
if match := filter.MatchConntrackFlow(flow); match {
|
||||
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
|
||||
req2.AddRawData(dataRaw[4:])
|
||||
req2.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
matched++
|
||||
for _, filter := range filters {
|
||||
if match := filter.MatchConntrackFlow(flow); match {
|
||||
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
|
||||
req2.AddRawData(dataRaw[4:])
|
||||
req2.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
matched++
|
||||
// flow is already deleted, no need to match on other filters and continue to the next flow.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,10 +194,44 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
|
||||
return req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
}
|
||||
|
||||
// ProtoInfo wraps an L4-protocol structure - roughly corresponds to the
|
||||
// __nfct_protoinfo union found in libnetfilter_conntrack/include/internal/object.h.
|
||||
// Currently, only protocol names, and TCP state is supported.
|
||||
type ProtoInfo interface {
|
||||
Protocol() string
|
||||
}
|
||||
|
||||
// ProtoInfoTCP corresponds to the `tcp` struct of the __nfct_protoinfo union.
|
||||
// Only TCP state is currently supported.
|
||||
type ProtoInfoTCP struct {
|
||||
State uint8
|
||||
}
|
||||
// Protocol returns "tcp".
|
||||
func (*ProtoInfoTCP) Protocol() string {return "tcp"}
|
||||
func (p *ProtoInfoTCP) toNlData() ([]*nl.RtAttr, error) {
|
||||
ctProtoInfo := nl.NewRtAttr(unix.NLA_F_NESTED | nl.CTA_PROTOINFO, []byte{})
|
||||
ctProtoInfoTCP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_PROTOINFO_TCP, []byte{})
|
||||
ctProtoInfoTCPState := nl.NewRtAttr(nl.CTA_PROTOINFO_TCP_STATE, nl.Uint8Attr(p.State))
|
||||
ctProtoInfoTCP.AddChild(ctProtoInfoTCPState)
|
||||
ctProtoInfo.AddChild(ctProtoInfoTCP)
|
||||
|
||||
return []*nl.RtAttr{ctProtoInfo}, nil
|
||||
}
|
||||
|
||||
// ProtoInfoSCTP only supports the protocol name.
|
||||
type ProtoInfoSCTP struct {}
|
||||
// Protocol returns "sctp".
|
||||
func (*ProtoInfoSCTP) Protocol() string {return "sctp"}
|
||||
|
||||
// ProtoInfoDCCP only supports the protocol name.
|
||||
type ProtoInfoDCCP struct {}
|
||||
// Protocol returns "dccp".
|
||||
func (*ProtoInfoDCCP) Protocol() string {return "dccp"}
|
||||
|
||||
// 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
|
||||
// For the time being, the structure below allows to parse and extract the base information of a flow
|
||||
type ipTuple struct {
|
||||
type IPTuple struct {
|
||||
Bytes uint64
|
||||
DstIP net.IP
|
||||
DstPort uint16
|
||||
@ -141,28 +241,150 @@ type ipTuple struct {
|
||||
SrcPort uint16
|
||||
}
|
||||
|
||||
// toNlData generates the inner fields of a nested tuple netlink datastructure
|
||||
// does not generate the "nested"-flagged outer message.
|
||||
func (t *IPTuple) toNlData(family uint8) ([]*nl.RtAttr, error) {
|
||||
|
||||
var srcIPsFlag, dstIPsFlag int
|
||||
if family == nl.FAMILY_V4 {
|
||||
srcIPsFlag = nl.CTA_IP_V4_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V4_DST
|
||||
} else if family == nl.FAMILY_V6 {
|
||||
srcIPsFlag = nl.CTA_IP_V6_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V6_DST
|
||||
} else {
|
||||
return []*nl.RtAttr{}, fmt.Errorf("couldn't generate netlink message for tuple due to unrecognized FamilyType '%d'", family)
|
||||
}
|
||||
|
||||
ctTupleIP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_IP, nil)
|
||||
ctTupleIPSrc := nl.NewRtAttr(srcIPsFlag, t.SrcIP)
|
||||
ctTupleIP.AddChild(ctTupleIPSrc)
|
||||
ctTupleIPDst := nl.NewRtAttr(dstIPsFlag, t.DstIP)
|
||||
ctTupleIP.AddChild(ctTupleIPDst)
|
||||
|
||||
ctTupleProto := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_PROTO, nil)
|
||||
ctTupleProtoNum := nl.NewRtAttr(nl.CTA_PROTO_NUM, []byte{t.Protocol})
|
||||
ctTupleProto.AddChild(ctTupleProtoNum)
|
||||
ctTupleProtoSrcPort := nl.NewRtAttr(nl.CTA_PROTO_SRC_PORT, nl.BEUint16Attr(t.SrcPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoSrcPort)
|
||||
ctTupleProtoDstPort := nl.NewRtAttr(nl.CTA_PROTO_DST_PORT, nl.BEUint16Attr(t.DstPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoDstPort, )
|
||||
|
||||
return []*nl.RtAttr{ctTupleIP, ctTupleProto}, nil
|
||||
}
|
||||
|
||||
type ConntrackFlow struct {
|
||||
FamilyType uint8
|
||||
Forward ipTuple
|
||||
Reverse ipTuple
|
||||
Forward IPTuple
|
||||
Reverse IPTuple
|
||||
Mark uint32
|
||||
Zone uint16
|
||||
TimeStart uint64
|
||||
TimeStop uint64
|
||||
TimeOut uint32
|
||||
Labels []byte
|
||||
ProtoInfo ProtoInfo
|
||||
}
|
||||
|
||||
func (s *ConntrackFlow) String() string {
|
||||
// conntrack cmd output:
|
||||
// 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
|
||||
// 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 labels=0x00000000050012ac4202010000000000 zone=100
|
||||
// start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
|
||||
start := time.Unix(0, int64(s.TimeStart))
|
||||
stop := time.Unix(0, int64(s.TimeStop))
|
||||
timeout := int32(s.TimeOut)
|
||||
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=0x%x start=%v stop=%v timeout=%d(sec)",
|
||||
res := 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=0x%x ",
|
||||
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
||||
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
|
||||
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
|
||||
s.Mark, start, stop, timeout)
|
||||
s.Mark)
|
||||
if len(s.Labels) > 0 {
|
||||
res += fmt.Sprintf("labels=0x%x ", s.Labels)
|
||||
}
|
||||
if s.Zone != 0 {
|
||||
res += fmt.Sprintf("zone=%d ", s.Zone)
|
||||
}
|
||||
res += fmt.Sprintf("start=%v stop=%v timeout=%d(sec)", start, stop, timeout)
|
||||
return res
|
||||
}
|
||||
|
||||
// toNlData generates netlink messages representing the flow.
|
||||
func (s *ConntrackFlow) toNlData() ([]*nl.RtAttr, error) {
|
||||
var payload []*nl.RtAttr
|
||||
// The message structure is built as follows:
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_ORIG>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_REPLY>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_STATUS>
|
||||
// <uint64>
|
||||
// <len, CTA_MARK>
|
||||
// <BEuint64>
|
||||
// <len, CTA_TIMEOUT>
|
||||
// <BEuint64>
|
||||
// <len, NLA_F_NESTED|CTA_PROTOINFO>
|
||||
|
||||
// CTA_TUPLE_ORIG
|
||||
ctTupleOrig := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_ORIG, nil)
|
||||
forwardFlowAttrs, err := s.Forward.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack forward flow: %w", err)
|
||||
}
|
||||
for _, a := range forwardFlowAttrs {
|
||||
ctTupleOrig.AddChild(a)
|
||||
}
|
||||
|
||||
// CTA_TUPLE_REPLY
|
||||
ctTupleReply := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_REPLY, nil)
|
||||
reverseFlowAttrs, err := s.Reverse.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack reverse flow: %w", err)
|
||||
}
|
||||
for _, a := range reverseFlowAttrs {
|
||||
ctTupleReply.AddChild(a)
|
||||
}
|
||||
|
||||
ctMark := nl.NewRtAttr(nl.CTA_MARK, nl.BEUint32Attr(s.Mark))
|
||||
ctTimeout := nl.NewRtAttr(nl.CTA_TIMEOUT, nl.BEUint32Attr(s.TimeOut))
|
||||
|
||||
payload = append(payload, ctTupleOrig, ctTupleReply, ctMark, ctTimeout)
|
||||
|
||||
if s.ProtoInfo != nil {
|
||||
switch p := s.ProtoInfo.(type) {
|
||||
case *ProtoInfoTCP:
|
||||
attrs, err := p.toNlData()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack flow's TCP protoinfo: %w", err)
|
||||
}
|
||||
payload = append(payload, attrs...)
|
||||
default:
|
||||
return nil, errors.New("couldn't generate netlink data for conntrack: field 'ProtoInfo' only supports TCP or nil")
|
||||
}
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// This method parse the ip tuple structure
|
||||
@ -172,7 +394,7 @@ func (s *ConntrackFlow) String() string {
|
||||
// <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_DST_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *IPTuple) uint8 {
|
||||
for i := 0; i < 2; i++ {
|
||||
_, t, _, v := parseNfAttrTLV(reader)
|
||||
switch t {
|
||||
@ -191,7 +413,7 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
tpl.Protocol = uint8(v[0])
|
||||
}
|
||||
// We only parse TCP & UDP headers. Skip the others.
|
||||
if tpl.Protocol != 6 && tpl.Protocol != 17 {
|
||||
if tpl.Protocol != unix.IPPROTO_TCP && tpl.Protocol != unix.IPPROTO_UDP {
|
||||
// skip the rest
|
||||
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
|
||||
reader.Seek(int64(bytesRemaining), seekCurrent)
|
||||
@ -240,9 +462,13 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
|
||||
return isNested, attrType, len
|
||||
}
|
||||
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) {
|
||||
// skipNfAttrValue seeks `r` past attr of length `len`.
|
||||
// Maintains buffer alignment.
|
||||
// Returns length of the seek performed.
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) uint16 {
|
||||
len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
|
||||
r.Seek(int64(len), seekCurrent)
|
||||
return len
|
||||
}
|
||||
|
||||
func parseBERaw16(r *bytes.Reader, v *uint16) {
|
||||
@ -257,6 +483,10 @@ func parseBERaw64(r *bytes.Reader, v *uint64) {
|
||||
binary.Read(r, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
func parseRaw32(r *bytes.Reader, v *uint32) {
|
||||
binary.Read(r, nl.NativeEndian(), v)
|
||||
}
|
||||
|
||||
func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
|
||||
for i := 0; i < 2; i++ {
|
||||
switch _, t, _ := parseNfAttrTL(r); t {
|
||||
@ -296,6 +526,60 @@ func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
|
||||
|
||||
}
|
||||
|
||||
func parseProtoInfoTCPState(r *bytes.Reader) (s uint8) {
|
||||
binary.Read(r, binary.BigEndian, &s)
|
||||
r.Seek(nl.SizeofNfattr - 1, seekCurrent)
|
||||
return s
|
||||
}
|
||||
|
||||
// parseProtoInfoTCP reads the entire nested protoinfo structure, but only parses the state attr.
|
||||
func parseProtoInfoTCP(r *bytes.Reader, attrLen uint16) (*ProtoInfoTCP) {
|
||||
p := new(ProtoInfoTCP)
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP_STATE:
|
||||
p.State = parseProtoInfoTCPState(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
default:
|
||||
bytesRead += int(skipNfAttrValue(r, l))
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseProtoInfo(r *bytes.Reader, attrLen uint16) (p ProtoInfo) {
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP:
|
||||
p = parseProtoInfoTCP(r, l)
|
||||
bytesRead += int(l)
|
||||
// No inner fields of DCCP / SCTP currently supported.
|
||||
case nl.CTA_PROTOINFO_DCCP:
|
||||
p = new(ProtoInfoDCCP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
case nl.CTA_PROTOINFO_SCTP:
|
||||
p = new(ProtoInfoSCTP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
default:
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
|
||||
parseBERaw32(r, &ttimeout)
|
||||
return
|
||||
@ -306,6 +590,18 @@ func parseConnectionMark(r *bytes.Reader) (mark uint32) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionLabels(r *bytes.Reader) (label []byte) {
|
||||
label = make([]byte, 16) // netfilter defines 128 bit labels value
|
||||
binary.Read(r, nl.NativeEndian(), &label)
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionZone(r *bytes.Reader) (zone uint16) {
|
||||
parseBERaw16(r, &zone)
|
||||
r.Seek(2, seekCurrent)
|
||||
return
|
||||
}
|
||||
|
||||
func parseRawData(data []byte) *ConntrackFlow {
|
||||
s := &ConntrackFlow{}
|
||||
// First there is the Nfgenmsg header
|
||||
@ -343,7 +639,7 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
case nl.CTA_TIMESTAMP:
|
||||
s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
|
||||
case nl.CTA_PROTOINFO:
|
||||
skipNfAttrValue(reader, l)
|
||||
s.ProtoInfo = parseProtoInfo(reader, l)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@ -351,10 +647,14 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
switch t {
|
||||
case nl.CTA_MARK:
|
||||
s.Mark = parseConnectionMark(reader)
|
||||
case nl.CTA_LABELS:
|
||||
s.Labels = parseConnectionLabels(reader)
|
||||
case nl.CTA_TIMEOUT:
|
||||
s.TimeOut = parseTimeOut(reader)
|
||||
case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
|
||||
case nl.CTA_ID, nl.CTA_STATUS, nl.CTA_USE:
|
||||
skipNfAttrValue(reader, l)
|
||||
case nl.CTA_ZONE:
|
||||
s.Zone = parseConnectionZone(reader)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@ -399,16 +699,18 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
type ConntrackFilterType uint8
|
||||
|
||||
const (
|
||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||
ConntrackReplyAnyIP // Match source or destination reply IP
|
||||
ConntrackOrigSrcPort // --orig-port-src port Source port in original direction
|
||||
ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction
|
||||
ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
|
||||
ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
|
||||
ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP
|
||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||
ConntrackReplyAnyIP // Match source or destination reply IP
|
||||
ConntrackOrigSrcPort // --orig-port-src port Source port in original direction
|
||||
ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction
|
||||
ConntrackMatchLabels // --label label1,label2 Labels used in entry
|
||||
ConntrackUnmatchLabels // --label label1,label2 Labels not used in entry
|
||||
ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
|
||||
ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
|
||||
ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP
|
||||
)
|
||||
|
||||
type CustomConntrackFilter interface {
|
||||
@ -421,6 +723,8 @@ type ConntrackFilter struct {
|
||||
ipNetFilter map[ConntrackFilterType]*net.IPNet
|
||||
portFilter map[ConntrackFilterType]uint16
|
||||
protoFilter uint8
|
||||
labelFilter map[ConntrackFilterType][][]byte
|
||||
zoneFilter *uint16
|
||||
}
|
||||
|
||||
// AddIPNet adds a IP subnet to the conntrack filter
|
||||
@ -474,10 +778,43 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLabels adds the provided list (zero or more) of labels to the conntrack filter
|
||||
// ConntrackFilterType here can be either:
|
||||
// 1. ConntrackMatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` contains ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that contain
|
||||
// one or more labels.
|
||||
// 2. ConntrackUnmatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` does NOT contain ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that don't contain
|
||||
// one or more labels.
|
||||
func (f *ConntrackFilter) AddLabels(tp ConntrackFilterType, labels [][]byte) error {
|
||||
if len(labels) == 0 {
|
||||
return errors.New("Invalid length for provided labels")
|
||||
}
|
||||
if f.labelFilter == nil {
|
||||
f.labelFilter = make(map[ConntrackFilterType][][]byte)
|
||||
}
|
||||
if _, ok := f.labelFilter[tp]; ok {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.labelFilter[tp] = labels
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddZone adds a zone to the conntrack filter
|
||||
func (f *ConntrackFilter) AddZone(zone uint16) error {
|
||||
if f.zoneFilter != nil {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.zoneFilter = &zone
|
||||
return nil
|
||||
}
|
||||
|
||||
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
|
||||
// false otherwise
|
||||
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
|
||||
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 && len(f.labelFilter) == 0 && f.zoneFilter == nil {
|
||||
// empty filter always not match
|
||||
return false
|
||||
}
|
||||
@ -488,6 +825,11 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Conntrack zone filter
|
||||
if f.zoneFilter != nil && *f.zoneFilter != flow.Zone {
|
||||
return false
|
||||
}
|
||||
|
||||
match := true
|
||||
|
||||
// IP conntrack filter
|
||||
@ -531,6 +873,29 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Label filter
|
||||
if len(f.labelFilter) > 0 {
|
||||
if len(flow.Labels) > 0 {
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackMatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && (bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be not contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackUnmatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && !(bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// flow doesn't contain labels, so it doesn't contain or notContain any provided matches
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
|
19
vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
generated
vendored
19
vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
generated
vendored
@ -11,6 +11,9 @@ type InetFamily uint8
|
||||
// ConntrackFlow placeholder
|
||||
type ConntrackFlow struct{}
|
||||
|
||||
// CustomConntrackFilter placeholder
|
||||
type CustomConntrackFilter struct{}
|
||||
|
||||
// ConntrackFilter placeholder
|
||||
type ConntrackFilter struct{}
|
||||
|
||||
@ -29,10 +32,18 @@ func ConntrackTableFlush(table ConntrackTableType) error {
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [ConntrackDeleteFilter] instead.
|
||||
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
||||
// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed
|
||||
// conntrack -L [table] [options] List conntrack or expectation table
|
||||
func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) {
|
||||
@ -48,6 +59,14 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [Handle.ConntrackDeleteFilters] instead.
|
||||
func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
431
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
431
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
@ -84,6 +84,270 @@ type DevlinkDeviceInfo struct {
|
||||
FwUndi string
|
||||
}
|
||||
|
||||
// DevlinkResource represents a device resource
|
||||
type DevlinkResource struct {
|
||||
Name string
|
||||
ID uint64
|
||||
Size uint64
|
||||
SizeNew uint64
|
||||
SizeMin uint64
|
||||
SizeMax uint64
|
||||
SizeGranularity uint64
|
||||
PendingChange bool
|
||||
Unit uint8
|
||||
SizeValid bool
|
||||
OCCValid bool
|
||||
OCCSize uint64
|
||||
Parent *DevlinkResource
|
||||
Children []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResource, returns error if occured
|
||||
func (dlr *DevlinkResource) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// mandatory attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_ID]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource id")
|
||||
}
|
||||
dlr.ID = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource name")
|
||||
}
|
||||
dlr.Name = nl.BytesToString(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size")
|
||||
}
|
||||
dlr.Size = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_GRAN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size granularity")
|
||||
}
|
||||
dlr.SizeGranularity = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_UNIT]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource unit")
|
||||
}
|
||||
dlr.Unit = uint8(attr.Value[0])
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MIN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size min")
|
||||
}
|
||||
dlr.SizeMin = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MAX]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size max")
|
||||
}
|
||||
dlr.SizeMax = native.Uint64(attr.Value)
|
||||
|
||||
// optional attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_OCC]
|
||||
if ok {
|
||||
dlr.OCCSize = native.Uint64(attr.Value)
|
||||
dlr.OCCValid = true
|
||||
}
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_VALID]
|
||||
if ok {
|
||||
dlr.SizeValid = uint8(attr.Value[0]) != 0
|
||||
}
|
||||
|
||||
dlr.SizeNew = dlr.Size
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_NEW]
|
||||
if ok {
|
||||
dlr.SizeNew = native.Uint64(attr.Value)
|
||||
}
|
||||
|
||||
dlr.PendingChange = dlr.Size != dlr.SizeNew
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if ok {
|
||||
// handle nested resoruces recursively
|
||||
subResources, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, subresource := range subResources {
|
||||
resource := DevlinkResource{Parent: dlr}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(subresource.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse child resource, parent:%s. %w", dlr.Name, err)
|
||||
}
|
||||
dlr.Children = append(dlr.Children, resource)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DevlinkResources represents all devlink resources of a devlink device
|
||||
type DevlinkResources struct {
|
||||
Bus string
|
||||
Device string
|
||||
Resources []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResources, returns error if occured
|
||||
func (dlrs *DevlinkResources) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// Bus
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_BUS_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing bus name")
|
||||
}
|
||||
dlrs.Bus = nl.BytesToString(attr.Value)
|
||||
|
||||
// Device
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_DEV_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing device name")
|
||||
}
|
||||
dlrs.Device = nl.BytesToString(attr.Value)
|
||||
|
||||
// Resource List
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource list")
|
||||
}
|
||||
|
||||
resourceAttrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resourceAttr := range resourceAttrs {
|
||||
resource := DevlinkResource{}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(resourceAttr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse root resoruces, %w", err)
|
||||
}
|
||||
dlrs.Resources = append(dlrs.Resources, resource)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DevlinkParam represents parameter of the device
|
||||
type DevlinkParam struct {
|
||||
Name string
|
||||
IsGeneric bool
|
||||
Type uint8 // possible values are in nl.DEVLINK_PARAM_TYPE_* constants
|
||||
Values []DevlinkParamValue
|
||||
}
|
||||
|
||||
// DevlinkParamValue contains values of the parameter
|
||||
// Data field contains specific type which can be casted by unsing info from the DevlinkParam.Type field
|
||||
type DevlinkParamValue struct {
|
||||
rawData []byte
|
||||
Data interface{}
|
||||
CMODE uint8 // possible values are in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkParam, returns error if occured
|
||||
func (dlp *DevlinkParam) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
|
||||
var valuesList [][]syscall.NetlinkRouteAttr
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM:
|
||||
nattrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, nattr := range nattrs {
|
||||
switch nattr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM_NAME:
|
||||
dlp.Name = nl.BytesToString(nattr.Value)
|
||||
case nl.DEVLINK_ATTR_PARAM_GENERIC:
|
||||
dlp.IsGeneric = true
|
||||
case nl.DEVLINK_ATTR_PARAM_TYPE:
|
||||
if len(nattr.Value) == 1 {
|
||||
dlp.Type = nattr.Value[0]
|
||||
}
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUES_LIST:
|
||||
nnattrs, err := nl.ParseRouteAttr(nattr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valuesList = append(valuesList, nnattrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, valAttr := range valuesList {
|
||||
v := DevlinkParamValue{}
|
||||
if err := v.parseAttributes(valAttr, dlp.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
dlp.Values = append(dlp.Values, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dlpv *DevlinkParamValue) parseAttributes(attrs []syscall.NetlinkRouteAttr, paramType uint8) error {
|
||||
for _, attr := range attrs {
|
||||
nattrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rawData []byte
|
||||
for _, nattr := range nattrs {
|
||||
switch nattr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUE_DATA:
|
||||
rawData = nattr.Value
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUE_CMODE:
|
||||
if len(nattr.Value) == 1 {
|
||||
dlpv.CMODE = nattr.Value[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
switch paramType {
|
||||
case nl.DEVLINK_PARAM_TYPE_U8:
|
||||
dlpv.Data = uint8(0)
|
||||
if rawData != nil && len(rawData) == 1 {
|
||||
dlpv.Data = uint8(rawData[0])
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_U16:
|
||||
dlpv.Data = uint16(0)
|
||||
if rawData != nil {
|
||||
dlpv.Data = native.Uint16(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_U32:
|
||||
dlpv.Data = uint32(0)
|
||||
if rawData != nil {
|
||||
dlpv.Data = native.Uint32(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_STRING:
|
||||
dlpv.Data = ""
|
||||
if rawData != nil {
|
||||
dlpv.Data = nl.BytesToString(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_BOOL:
|
||||
dlpv.Data = rawData != nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
|
||||
devices := make([]*DevlinkDevice, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
@ -443,6 +707,173 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
|
||||
return port, err
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
return pkgHandle.DevlinkGetDeviceResources(bus, device)
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_RESOURCE_DUMP, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resources DevlinkResources
|
||||
for _, m := range respmsg {
|
||||
attrs, err := nl.ParseRouteAttrAsMap(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources.parseAttributes(attrs)
|
||||
}
|
||||
|
||||
return &resources, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParams returns parameters for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device>`
|
||||
func (h *Handle) DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Flags |= unix.NLM_F_DUMP
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var params []*DevlinkParam
|
||||
for _, m := range respmsg {
|
||||
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &DevlinkParam{}
|
||||
if err := p.parseAttributes(attrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = append(params, p)
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParams returns parameters for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device>`
|
||||
func DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) {
|
||||
return pkgHandle.DevlinkGetDeviceParams(bus, device)
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParamByName returns specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device> name <param>`
|
||||
func (h *Handle) DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param)))
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(respmsg) == 0 {
|
||||
return nil, fmt.Errorf("unexpected response")
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(respmsg[0][nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &DevlinkParam{}
|
||||
if err := p.parseAttributes(attrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParamByName returns specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device> name <param>`
|
||||
func DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) {
|
||||
return pkgHandle.DevlinkGetDeviceParamByName(bus, device, param)
|
||||
}
|
||||
|
||||
// DevlinkSetDeviceParam set specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
|
||||
// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
// value argument should have one of the following types: uint8, uint16, uint32, string, bool
|
||||
func (h *Handle) DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error {
|
||||
// retrive the param type
|
||||
p, err := h.DevlinkGetDeviceParamByName(bus, device, param)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get device param: %v", err)
|
||||
}
|
||||
paramType := p.Type
|
||||
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_SET, bus, device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_TYPE, nl.Uint8Attr(paramType)))
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param)))
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_CMODE, nl.Uint8Attr(cmode)))
|
||||
|
||||
var valueAsBytes []byte
|
||||
switch paramType {
|
||||
case nl.DEVLINK_PARAM_TYPE_U8:
|
||||
v, ok := value.(uint8)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint8, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint8Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_U16:
|
||||
v, ok := value.(uint16)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint16, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint16Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_U32:
|
||||
v, ok := value.(uint32)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint32, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint32Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_STRING:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: string, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.ZeroTerminated(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_BOOL:
|
||||
v, ok := value.(bool)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: bool, actual: %T", value)
|
||||
}
|
||||
if v {
|
||||
valueAsBytes = []byte{}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported parameter type: %d", paramType)
|
||||
}
|
||||
if valueAsBytes != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_DATA, valueAsBytes))
|
||||
}
|
||||
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// DevlinkSetDeviceParam set specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
|
||||
// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
// value argument should have one of the following types: uint8, uint16, uint32, string, bool
|
||||
func DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error {
|
||||
return pkgHandle.DevlinkSetDeviceParam(bus, device, param, cmode, value)
|
||||
}
|
||||
|
||||
// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
|
||||
// otherwise returns an error code.
|
||||
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
|
||||
|
80
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
80
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
@ -19,6 +19,7 @@ type FilterAttrs struct {
|
||||
Parent uint32
|
||||
Priority uint16 // lower is higher priority
|
||||
Protocol uint16 // unix.ETH_P_*
|
||||
Chain *uint32
|
||||
}
|
||||
|
||||
func (q FilterAttrs) String() string {
|
||||
@ -27,6 +28,11 @@ func (q FilterAttrs) String() string {
|
||||
|
||||
type TcAct int32
|
||||
|
||||
const (
|
||||
TC_ACT_EXT_SHIFT = 28
|
||||
TC_ACT_EXT_VAL_MASK = (1 << TC_ACT_EXT_SHIFT) - 1
|
||||
)
|
||||
|
||||
const (
|
||||
TC_ACT_UNSPEC TcAct = -1
|
||||
TC_ACT_OK TcAct = 0
|
||||
@ -40,6 +46,22 @@ const (
|
||||
TC_ACT_JUMP TcAct = 0x10000000
|
||||
)
|
||||
|
||||
func getTcActExt(local int32) int32 {
|
||||
return local << TC_ACT_EXT_SHIFT
|
||||
}
|
||||
|
||||
func getTcActGotoChain() TcAct {
|
||||
return TcAct(getTcActExt(2))
|
||||
}
|
||||
|
||||
func getTcActExtOpcode(combined int32) int32 {
|
||||
return combined & (^TC_ACT_EXT_VAL_MASK)
|
||||
}
|
||||
|
||||
func TcActExtCmp(combined int32, opcode int32) bool {
|
||||
return getTcActExtOpcode(combined) == opcode
|
||||
}
|
||||
|
||||
func (a TcAct) String() string {
|
||||
switch a {
|
||||
case TC_ACT_UNSPEC:
|
||||
@ -63,6 +85,9 @@ func (a TcAct) String() string {
|
||||
case TC_ACT_JUMP:
|
||||
return "jump"
|
||||
}
|
||||
if TcActExtCmp(int32(a), int32(getTcActGotoChain())) {
|
||||
return "goto"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", int32(a))
|
||||
}
|
||||
|
||||
@ -93,17 +118,32 @@ func (a TcPolAct) String() string {
|
||||
}
|
||||
|
||||
type ActionAttrs struct {
|
||||
Index int
|
||||
Capab int
|
||||
Action TcAct
|
||||
Refcnt int
|
||||
Bindcnt int
|
||||
Index int
|
||||
Capab int
|
||||
Action TcAct
|
||||
Refcnt int
|
||||
Bindcnt int
|
||||
Statistics *ActionStatistic
|
||||
Timestamp *ActionTimestamp
|
||||
}
|
||||
|
||||
func (q ActionAttrs) String() string {
|
||||
return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt)
|
||||
}
|
||||
|
||||
type ActionTimestamp struct {
|
||||
Installed uint64
|
||||
LastUsed uint64
|
||||
Expires uint64
|
||||
FirstUsed uint64
|
||||
}
|
||||
|
||||
func (t ActionTimestamp) String() string {
|
||||
return fmt.Sprintf("Installed %d LastUsed %d Expires %d FirstUsed %d", t.Installed, t.LastUsed, t.Expires, t.FirstUsed)
|
||||
}
|
||||
|
||||
type ActionStatistic ClassStatistics
|
||||
|
||||
// Action represents an action in any supported filter.
|
||||
type Action interface {
|
||||
Attrs() *ActionAttrs
|
||||
@ -112,6 +152,7 @@ type Action interface {
|
||||
|
||||
type GenericAction struct {
|
||||
ActionAttrs
|
||||
Chain int32
|
||||
}
|
||||
|
||||
func (action *GenericAction) Type() string {
|
||||
@ -275,6 +316,7 @@ type SkbEditAction struct {
|
||||
PType *uint16
|
||||
Priority *uint32
|
||||
Mark *uint32
|
||||
Mask *uint32
|
||||
}
|
||||
|
||||
func (action *SkbEditAction) Type() string {
|
||||
@ -348,6 +390,7 @@ type FwFilter struct {
|
||||
InDev string
|
||||
Mask uint32
|
||||
Police *PoliceAction
|
||||
Actions []Action
|
||||
}
|
||||
|
||||
func (filter *FwFilter) Attrs() *FilterAttrs {
|
||||
@ -390,3 +433,30 @@ func (filter *GenericFilter) Attrs() *FilterAttrs {
|
||||
func (filter *GenericFilter) Type() string {
|
||||
return filter.FilterType
|
||||
}
|
||||
|
||||
type PeditAction struct {
|
||||
ActionAttrs
|
||||
Proto uint8
|
||||
SrcMacAddr net.HardwareAddr
|
||||
DstMacAddr net.HardwareAddr
|
||||
SrcIP net.IP
|
||||
DstIP net.IP
|
||||
SrcPort uint16
|
||||
DstPort uint16
|
||||
}
|
||||
|
||||
func (p *PeditAction) Attrs() *ActionAttrs {
|
||||
return &p.ActionAttrs
|
||||
}
|
||||
|
||||
func (p *PeditAction) Type() string {
|
||||
return "pedit"
|
||||
}
|
||||
|
||||
func NewPeditAction() *PeditAction {
|
||||
return &PeditAction{
|
||||
ActionAttrs: ActionAttrs{
|
||||
Action: TC_ACT_PIPE,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
187
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
187
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
@ -41,6 +41,7 @@ type U32 struct {
|
||||
RedirIndex int
|
||||
Sel *TcU32Sel
|
||||
Actions []Action
|
||||
Police *PoliceAction
|
||||
}
|
||||
|
||||
func (filter *U32) Attrs() *FilterAttrs {
|
||||
@ -64,6 +65,11 @@ type Flower struct {
|
||||
EncSrcIPMask net.IPMask
|
||||
EncDestPort uint16
|
||||
EncKeyId uint32
|
||||
SkipHw bool
|
||||
SkipSw bool
|
||||
IPProto *nl.IPProto
|
||||
DestPort uint16
|
||||
SrcPort uint16
|
||||
|
||||
Actions []Action
|
||||
}
|
||||
@ -129,6 +135,39 @@ func (filter *Flower) encode(parent *nl.RtAttr) error {
|
||||
if filter.EncKeyId != 0 {
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
|
||||
}
|
||||
if filter.IPProto != nil {
|
||||
ipproto := *filter.IPProto
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
|
||||
if filter.SrcPort != 0 {
|
||||
switch ipproto {
|
||||
case nl.IPPROTO_TCP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort))
|
||||
case nl.IPPROTO_UDP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort))
|
||||
case nl.IPPROTO_SCTP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort))
|
||||
}
|
||||
}
|
||||
if filter.DestPort != 0 {
|
||||
switch ipproto {
|
||||
case nl.IPPROTO_TCP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort))
|
||||
case nl.IPPROTO_UDP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort))
|
||||
case nl.IPPROTO_SCTP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var flags uint32 = 0
|
||||
if filter.SkipHw {
|
||||
flags |= nl.TCA_CLS_FLAGS_SKIP_HW
|
||||
}
|
||||
if filter.SkipSw {
|
||||
flags |= nl.TCA_CLS_FLAGS_SKIP_SW
|
||||
}
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags))
|
||||
|
||||
actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
|
||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||
@ -162,6 +201,14 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||
filter.EncDestPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
|
||||
filter.EncKeyId = ntohl(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_IP_PROTO:
|
||||
val := new(nl.IPProto)
|
||||
*val = nl.IPProto(datum.Value[0])
|
||||
filter.IPProto = val
|
||||
case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC:
|
||||
filter.SrcPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST:
|
||||
filter.DestPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_ACT:
|
||||
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||
if err != nil {
|
||||
@ -171,6 +218,16 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case nl.TCA_FLOWER_FLAGS:
|
||||
attr := nl.DeserializeUint32Bitfield(datum.Value)
|
||||
skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW
|
||||
skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW
|
||||
if skipSw != 0 {
|
||||
filter.SkipSw = true
|
||||
}
|
||||
if skipHw != 0 {
|
||||
filter.SkipHw = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -185,19 +242,7 @@ func FilterDel(filter Filter) error {
|
||||
// FilterDel will delete a filter from the system.
|
||||
// Equivalent to: `tc filter del $filter`
|
||||
func (h *Handle) FilterDel(filter Filter) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK)
|
||||
base := filter.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
Ifindex: int32(base.LinkIndex),
|
||||
Handle: base.Handle,
|
||||
Parent: base.Parent,
|
||||
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
return h.filterModify(filter, unix.RTM_DELTFILTER, 0)
|
||||
}
|
||||
|
||||
// FilterAdd will add a filter to the system.
|
||||
@ -209,7 +254,7 @@ func FilterAdd(filter Filter) error {
|
||||
// FilterAdd will add a filter to the system.
|
||||
// Equivalent to: `tc filter add $filter`
|
||||
func (h *Handle) FilterAdd(filter Filter) error {
|
||||
return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
||||
return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
||||
}
|
||||
|
||||
// FilterReplace will replace a filter.
|
||||
@ -221,11 +266,11 @@ func FilterReplace(filter Filter) error {
|
||||
// FilterReplace will replace a filter.
|
||||
// Equivalent to: `tc filter replace $filter`
|
||||
func (h *Handle) FilterReplace(filter Filter) error {
|
||||
return h.filterModify(filter, unix.NLM_F_CREATE)
|
||||
return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE)
|
||||
}
|
||||
|
||||
func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
||||
func (h *Handle) filterModify(filter Filter, proto, flags int) error {
|
||||
req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK)
|
||||
base := filter.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
@ -235,6 +280,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
|
||||
}
|
||||
req.AddData(msg)
|
||||
if filter.Attrs().Chain != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain)))
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
@ -284,6 +332,12 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
if filter.Link != 0 {
|
||||
options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
|
||||
}
|
||||
if filter.Police != nil {
|
||||
police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
|
||||
if err := encodePolice(police, filter.Police); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
|
||||
// backwards compatibility
|
||||
if filter.RedirIndex != 0 {
|
||||
@ -312,6 +366,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
native.PutUint32(b, filter.ClassId)
|
||||
options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
||||
}
|
||||
actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil)
|
||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||
return err
|
||||
}
|
||||
case *BpfFilter:
|
||||
var bpfFlags uint32
|
||||
if filter.ClassId != 0 {
|
||||
@ -340,7 +398,6 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(options)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
@ -446,6 +503,10 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
||||
default:
|
||||
detailed = true
|
||||
}
|
||||
case nl.TCA_CHAIN:
|
||||
val := new(uint32)
|
||||
*val = native.Uint32(attr.Value)
|
||||
base.Chain = val
|
||||
}
|
||||
}
|
||||
// only return the detailed version of the filter
|
||||
@ -474,6 +535,14 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
|
||||
attrs.Bindcnt = int(tcgen.Bindcnt)
|
||||
}
|
||||
|
||||
func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp {
|
||||
return &ActionTimestamp{
|
||||
Installed: tcf.Install,
|
||||
LastUsed: tcf.LastUse,
|
||||
Expires: tcf.Expires,
|
||||
FirstUsed: tcf.FirstUse}
|
||||
}
|
||||
|
||||
func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
|
||||
var rtab [256]uint32
|
||||
var ptab [256]uint32
|
||||
@ -597,6 +666,9 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||
if action.Mark != nil {
|
||||
aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
|
||||
}
|
||||
if action.Mask != nil {
|
||||
aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask))
|
||||
}
|
||||
case *ConnmarkAction:
|
||||
table := attr.AddRtAttr(tabIndex, nil)
|
||||
tabIndex++
|
||||
@ -635,6 +707,29 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||
gen := nl.TcGen{}
|
||||
toTcGen(action.Attrs(), &gen)
|
||||
aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
||||
case *PeditAction:
|
||||
table := attr.AddRtAttr(tabIndex, nil)
|
||||
tabIndex++
|
||||
pedit := nl.TcPedit{}
|
||||
if action.SrcMacAddr != nil {
|
||||
pedit.SetEthSrc(action.SrcMacAddr)
|
||||
}
|
||||
if action.DstMacAddr != nil {
|
||||
pedit.SetEthDst(action.DstMacAddr)
|
||||
}
|
||||
if action.SrcIP != nil {
|
||||
pedit.SetSrcIP(action.SrcIP)
|
||||
}
|
||||
if action.DstIP != nil {
|
||||
pedit.SetDstIP(action.DstIP)
|
||||
}
|
||||
if action.SrcPort != 0 {
|
||||
pedit.SetSrcPort(action.SrcPort, action.Proto)
|
||||
}
|
||||
if action.DstPort != 0 {
|
||||
pedit.SetDstPort(action.DstPort, action.Proto)
|
||||
}
|
||||
pedit.Encode(table)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -668,6 +763,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
for _, table := range tables {
|
||||
var action Action
|
||||
var actionType string
|
||||
var actionnStatistic *ActionStatistic
|
||||
var actionTimestamp *ActionTimestamp
|
||||
aattrs, err := nl.ParseRouteAttr(table.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -695,6 +792,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action = &SkbEditAction{}
|
||||
case "police":
|
||||
action = &PoliceAction{}
|
||||
case "pedit":
|
||||
action = &PeditAction{}
|
||||
default:
|
||||
break nextattr
|
||||
}
|
||||
@ -713,7 +812,11 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
toAttrs(&mirred.TcGen, action.Attrs())
|
||||
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
||||
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
||||
case nl.TCA_MIRRED_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
|
||||
case "tunnel_key":
|
||||
switch adatum.Attr.Type {
|
||||
case nl.TCA_TUNNEL_KEY_PARMS:
|
||||
@ -729,6 +832,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*TunnelKeyAction).DstAddr = adatum.Value[:]
|
||||
case nl.TCA_TUNNEL_KEY_ENC_DST_PORT:
|
||||
action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value)
|
||||
case nl.TCA_TUNNEL_KEY_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "skbedit":
|
||||
switch adatum.Attr.Type {
|
||||
@ -739,6 +845,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
case nl.TCA_SKBEDIT_MARK:
|
||||
mark := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Mark = &mark
|
||||
case nl.TCA_SKBEDIT_MASK:
|
||||
mask := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Mask = &mask
|
||||
case nl.TCA_SKBEDIT_PRIORITY:
|
||||
priority := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Priority = &priority
|
||||
@ -748,6 +857,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
case nl.TCA_SKBEDIT_QUEUE_MAPPING:
|
||||
mapping := native.Uint16(adatum.Value[0:2])
|
||||
action.(*SkbEditAction).QueueMapping = &mapping
|
||||
case nl.TCA_SKBEDIT_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "bpf":
|
||||
switch adatum.Attr.Type {
|
||||
@ -758,6 +870,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
|
||||
case nl.TCA_ACT_BPF_NAME:
|
||||
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
|
||||
case nl.TCA_ACT_BPF_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "connmark":
|
||||
switch adatum.Attr.Type {
|
||||
@ -766,6 +881,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
|
||||
toAttrs(&connmark.TcGen, action.Attrs())
|
||||
action.(*ConnmarkAction).Zone = connmark.Zone
|
||||
case nl.TCA_CONNMARK_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "csum":
|
||||
switch adatum.Attr.Type {
|
||||
@ -774,19 +892,36 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*CsumAction).ActionAttrs = ActionAttrs{}
|
||||
toAttrs(&csum.TcGen, action.Attrs())
|
||||
action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
|
||||
case nl.TCA_CSUM_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "gact":
|
||||
switch adatum.Attr.Type {
|
||||
case nl.TCA_GACT_PARMS:
|
||||
gen := *nl.DeserializeTcGen(adatum.Value)
|
||||
toAttrs(&gen, action.Attrs())
|
||||
if action.Attrs().Action.String() == "goto" {
|
||||
action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action
|
||||
}
|
||||
case nl.TCA_GACT_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "police":
|
||||
parsePolice(adatum, action.(*PoliceAction))
|
||||
}
|
||||
}
|
||||
case nl.TCA_ACT_STATS:
|
||||
s, err := parseTcStats2(aattr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actionnStatistic = (*ActionStatistic)(s)
|
||||
}
|
||||
}
|
||||
action.Attrs().Statistics = actionnStatistic
|
||||
action.Attrs().Timestamp = actionTimestamp
|
||||
actions = append(actions, action)
|
||||
}
|
||||
return actions, nil
|
||||
@ -824,6 +959,13 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
||||
u32.RedirIndex = int(action.Ifindex)
|
||||
}
|
||||
}
|
||||
case nl.TCA_U32_POLICE:
|
||||
var police PoliceAction
|
||||
adata, _ := nl.ParseRouteAttr(datum.Value)
|
||||
for _, aattr := range adata {
|
||||
parsePolice(aattr, &police)
|
||||
}
|
||||
u32.Police = &police
|
||||
case nl.TCA_U32_CLASSID:
|
||||
u32.ClassId = native.Uint32(datum.Value)
|
||||
case nl.TCA_U32_DIVISOR:
|
||||
@ -855,6 +997,15 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||
parsePolice(aattr, &police)
|
||||
}
|
||||
fw.Police = &police
|
||||
case nl.TCA_FW_ACT:
|
||||
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||
if err != nil {
|
||||
return detailed, err
|
||||
}
|
||||
fw.Actions, err = parseActions(tables)
|
||||
if err != nil {
|
||||
return detailed, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return detailed, nil
|
||||
|
24
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
24
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
@ -79,6 +79,10 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -163,6 +167,22 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -243,6 +263,10 @@ func (h *Handle) RouteAppend(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) RouteChange(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) RouteDel(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/inet_diag.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/inet_diag.go
generated
vendored
@ -21,6 +21,10 @@ const (
|
||||
INET_DIAG_BBRINFO
|
||||
INET_DIAG_CLASS_ID
|
||||
INET_DIAG_MD5SIG
|
||||
INET_DIAG_ULP_INFO
|
||||
INET_DIAG_SK_BPF_STORAGES
|
||||
INET_DIAG_CGROUP_ID
|
||||
INET_DIAG_SOCKOPT
|
||||
INET_DIAG_MAX
|
||||
)
|
||||
|
||||
@ -29,3 +33,8 @@ type InetDiagTCPInfoResp struct {
|
||||
TCPInfo *TCPInfo
|
||||
TCPBBRInfo *TCPBBRInfo
|
||||
}
|
||||
|
||||
type InetDiagUDPInfoResp struct {
|
||||
InetDiagMsg *Socket
|
||||
Memory *MemInfo
|
||||
}
|
||||
|
115
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
115
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
@ -67,11 +67,13 @@ type IpsetCreateOptions struct {
|
||||
Comments bool
|
||||
Skbinfo bool
|
||||
|
||||
Revision uint8
|
||||
IPFrom net.IP
|
||||
IPTo net.IP
|
||||
PortFrom uint16
|
||||
PortTo uint16
|
||||
Family uint8
|
||||
Revision uint8
|
||||
IPFrom net.IP
|
||||
IPTo net.IP
|
||||
PortFrom uint16
|
||||
PortTo uint16
|
||||
MaxElements uint32
|
||||
}
|
||||
|
||||
// IpsetProtocol returns the ipset protocol version from the kernel
|
||||
@ -94,6 +96,11 @@ func IpsetFlush(setname string) error {
|
||||
return pkgHandle.IpsetFlush(setname)
|
||||
}
|
||||
|
||||
// IpsetSwap swaps two ipsets.
|
||||
func IpsetSwap(setname, othersetname string) error {
|
||||
return pkgHandle.IpsetSwap(setname, othersetname)
|
||||
}
|
||||
|
||||
// IpsetList dumps an specific ipset.
|
||||
func IpsetList(setname string) (*IPSetResult, error) {
|
||||
return pkgHandle.IpsetList(setname)
|
||||
@ -114,6 +121,11 @@ func IpsetDel(setname string, entry *IPSetEntry) error {
|
||||
return pkgHandle.IpsetDel(setname, entry)
|
||||
}
|
||||
|
||||
// IpsetTest tests whether an entry is in a set or not.
|
||||
func IpsetTest(setname string, entry *IPSetEntry) (bool, error) {
|
||||
return pkgHandle.IpsetTest(setname, entry)
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_PROTOCOL)
|
||||
msgs, err := req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
@ -153,11 +165,18 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2]))
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:]))
|
||||
default:
|
||||
family = unix.AF_INET
|
||||
family = options.Family
|
||||
if family == 0 {
|
||||
family = unix.AF_INET
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family)))
|
||||
|
||||
if options.MaxElements != 0 {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MAXELEM | nl.NLA_F_NET_BYTEORDER, Value: options.MaxElements})
|
||||
}
|
||||
|
||||
if timeout := options.Timeout; timeout != nil {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
||||
}
|
||||
@ -197,6 +216,14 @@ func (h *Handle) IpsetFlush(setname string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetSwap(setname, othersetname string) error {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_SWAP)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(othersetname)))
|
||||
_, err := ipsetExecute(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetList(name string) (*IPSetResult, error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_LIST)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(name)))
|
||||
@ -236,18 +263,23 @@ func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error {
|
||||
return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
|
||||
}
|
||||
|
||||
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
||||
req := h.newIpsetRequest(nlCmd)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if entry.Comment != "" {
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
|
||||
func encodeIP(ip net.IP) (*nl.RtAttr, error) {
|
||||
typ := int(nl.NLA_F_NET_BYTEORDER)
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
typ |= nl.IPSET_ATTR_IPADDR_IPV4
|
||||
ip = ip4
|
||||
} else {
|
||||
typ |= nl.IPSET_ATTR_IPADDR_IPV6
|
||||
}
|
||||
|
||||
return nl.NewRtAttr(typ, ip), nil
|
||||
}
|
||||
|
||||
func buildEntryData(entry *IPSetEntry) (*nl.RtAttr, error) {
|
||||
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
if entry.Comment != "" {
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
|
||||
}
|
||||
|
||||
if entry.Timeout != nil {
|
||||
@ -255,7 +287,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
}
|
||||
|
||||
if entry.IP != nil {
|
||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
|
||||
nestedData, err := encodeIP(entry.IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||
}
|
||||
|
||||
@ -268,7 +303,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
}
|
||||
|
||||
if entry.IP2 != nil {
|
||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2)
|
||||
nestedData, err := encodeIP(entry.IP2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||
}
|
||||
|
||||
@ -295,14 +333,53 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
if entry.Mark != nil {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER, Value: *entry.Mark})
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
||||
req := h.newIpsetRequest(nlCmd)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
}
|
||||
|
||||
data, err := buildEntryData(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
|
||||
req.AddData(data)
|
||||
|
||||
_, err := ipsetExecute(req)
|
||||
_, err = ipsetExecute(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetTest(setname string, entry *IPSetEntry) (bool, error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_TEST)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
}
|
||||
|
||||
data, err := buildEntryData(entry)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
req.AddData(data)
|
||||
|
||||
_, err = ipsetExecute(req)
|
||||
if err != nil {
|
||||
if err == nl.IPSetError(nl.IPSET_ERR_EXIST) {
|
||||
// not exist
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
|
||||
req := h.newNetlinkRequest(cmd|(unix.NFNL_SUBSYS_IPSET<<8), nl.GetIpsetFlags(cmd))
|
||||
|
||||
@ -466,7 +543,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
||||
case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
|
||||
for attr := range nl.ParseAttributes(attr.Value) {
|
||||
switch attr.Type {
|
||||
case nl.IPSET_ATTR_IP:
|
||||
case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6:
|
||||
entry.IP = net.IP(attr.Value)
|
||||
default:
|
||||
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||
@ -475,7 +552,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
||||
case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED:
|
||||
for attr := range nl.ParseAttributes(attr.Value) {
|
||||
switch attr.Type {
|
||||
case nl.IPSET_ATTR_IP:
|
||||
case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6:
|
||||
entry.IP2 = net.IP(attr.Value)
|
||||
default:
|
||||
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||
|
146
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
146
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
@ -22,34 +22,41 @@ type (
|
||||
|
||||
// LinkAttrs represents data shared by most link types
|
||||
type LinkAttrs struct {
|
||||
Index int
|
||||
MTU int
|
||||
TxQLen int // Transmit Queue Length
|
||||
Name string
|
||||
HardwareAddr net.HardwareAddr
|
||||
Flags net.Flags
|
||||
RawFlags uint32
|
||||
ParentIndex int // index of the parent link device
|
||||
MasterIndex int // must be the index of a bridge
|
||||
Namespace interface{} // nil | NsPid | NsFd
|
||||
Alias string
|
||||
Statistics *LinkStatistics
|
||||
Promisc int
|
||||
Allmulti int
|
||||
Multi int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
Protinfo *Protinfo
|
||||
OperState LinkOperState
|
||||
PhysSwitchID int
|
||||
NetNsID int
|
||||
NumTxQueues int
|
||||
NumRxQueues int
|
||||
GSOMaxSize uint32
|
||||
GSOMaxSegs uint32
|
||||
Vfs []VfInfo // virtual functions available on link
|
||||
Group uint32
|
||||
Slave LinkSlave
|
||||
Index int
|
||||
MTU int
|
||||
TxQLen int // Transmit Queue Length
|
||||
Name string
|
||||
HardwareAddr net.HardwareAddr
|
||||
Flags net.Flags
|
||||
RawFlags uint32
|
||||
ParentIndex int // index of the parent link device
|
||||
MasterIndex int // must be the index of a bridge
|
||||
Namespace interface{} // nil | NsPid | NsFd
|
||||
Alias string
|
||||
AltNames []string
|
||||
Statistics *LinkStatistics
|
||||
Promisc int
|
||||
Allmulti int
|
||||
Multi int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
Protinfo *Protinfo
|
||||
OperState LinkOperState
|
||||
PhysSwitchID int
|
||||
NetNsID int
|
||||
NumTxQueues int
|
||||
NumRxQueues int
|
||||
TSOMaxSegs uint32
|
||||
TSOMaxSize uint32
|
||||
GSOMaxSegs uint32
|
||||
GSOMaxSize uint32
|
||||
GROMaxSize uint32
|
||||
GSOIPv4MaxSize uint32
|
||||
GROIPv4MaxSize uint32
|
||||
Vfs []VfInfo // virtual functions available on link
|
||||
Group uint32
|
||||
PermHWAddr net.HardwareAddr
|
||||
Slave LinkSlave
|
||||
}
|
||||
|
||||
// LinkSlave represents a slave device.
|
||||
@ -63,6 +70,7 @@ type VfInfo struct {
|
||||
Mac net.HardwareAddr
|
||||
Vlan int
|
||||
Qos int
|
||||
VlanProto int
|
||||
TxRate int // IFLA_VF_TX_RATE Max TxRate
|
||||
Spoofchk bool
|
||||
LinkState uint32
|
||||
@ -265,6 +273,8 @@ type Bridge struct {
|
||||
AgeingTime *uint32
|
||||
HelloTime *uint32
|
||||
VlanFiltering *bool
|
||||
VlanDefaultPVID *uint16
|
||||
GroupFwdMask *uint16
|
||||
}
|
||||
|
||||
func (bridge *Bridge) Attrs() *LinkAttrs {
|
||||
@ -308,6 +318,9 @@ type Macvlan struct {
|
||||
|
||||
// MACAddrs is only populated for Macvlan SOURCE links
|
||||
MACAddrs []net.HardwareAddr
|
||||
|
||||
BCQueueLen uint32
|
||||
UsedBCQueueLen uint32
|
||||
}
|
||||
|
||||
func (macvlan *Macvlan) Attrs() *LinkAttrs {
|
||||
@ -350,6 +363,46 @@ func (tuntap *Tuntap) Type() string {
|
||||
return "tuntap"
|
||||
}
|
||||
|
||||
type NetkitMode uint32
|
||||
|
||||
const (
|
||||
NETKIT_MODE_L2 NetkitMode = iota
|
||||
NETKIT_MODE_L3
|
||||
)
|
||||
|
||||
type NetkitPolicy int
|
||||
|
||||
const (
|
||||
NETKIT_POLICY_FORWARD NetkitPolicy = 0
|
||||
NETKIT_POLICY_BLACKHOLE NetkitPolicy = 2
|
||||
)
|
||||
|
||||
func (n *Netkit) IsPrimary() bool {
|
||||
return n.isPrimary
|
||||
}
|
||||
|
||||
// SetPeerAttrs will not take effect if trying to modify an existing netkit device
|
||||
func (n *Netkit) SetPeerAttrs(Attrs *LinkAttrs) {
|
||||
n.peerLinkAttrs = *Attrs
|
||||
}
|
||||
|
||||
type Netkit struct {
|
||||
LinkAttrs
|
||||
Mode NetkitMode
|
||||
Policy NetkitPolicy
|
||||
PeerPolicy NetkitPolicy
|
||||
isPrimary bool
|
||||
peerLinkAttrs LinkAttrs
|
||||
}
|
||||
|
||||
func (n *Netkit) Attrs() *LinkAttrs {
|
||||
return &n.LinkAttrs
|
||||
}
|
||||
|
||||
func (n *Netkit) Type() string {
|
||||
return "netkit"
|
||||
}
|
||||
|
||||
// Veth devices must specify PeerName on create
|
||||
type Veth struct {
|
||||
LinkAttrs
|
||||
@ -703,6 +756,7 @@ const (
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4
|
||||
BOND_XMIT_HASH_POLICY_VLAN_SRCMAC
|
||||
BOND_XMIT_HASH_POLICY_UNKNOWN
|
||||
)
|
||||
|
||||
@ -712,6 +766,7 @@ var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
|
||||
BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac",
|
||||
}
|
||||
var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
|
||||
"layer2": BOND_XMIT_HASH_POLICY_LAYER2,
|
||||
@ -719,6 +774,7 @@ var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
|
||||
"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
|
||||
"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
|
||||
"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
|
||||
"vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC,
|
||||
}
|
||||
|
||||
// BondLacpRate type
|
||||
@ -974,16 +1030,18 @@ func (v *VrfSlave) SlaveType() string {
|
||||
// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
|
||||
type Geneve struct {
|
||||
LinkAttrs
|
||||
ID uint32 // vni
|
||||
Remote net.IP
|
||||
Ttl uint8
|
||||
Tos uint8
|
||||
Dport uint16
|
||||
UdpCsum uint8
|
||||
UdpZeroCsum6Tx uint8
|
||||
UdpZeroCsum6Rx uint8
|
||||
Link uint32
|
||||
FlowBased bool
|
||||
ID uint32 // vni
|
||||
Remote net.IP
|
||||
Ttl uint8
|
||||
Tos uint8
|
||||
Dport uint16
|
||||
UdpCsum uint8
|
||||
UdpZeroCsum6Tx uint8
|
||||
UdpZeroCsum6Rx uint8
|
||||
Link uint32
|
||||
FlowBased bool
|
||||
InnerProtoInherit bool
|
||||
Df GeneveDf
|
||||
}
|
||||
|
||||
func (geneve *Geneve) Attrs() *LinkAttrs {
|
||||
@ -994,6 +1052,15 @@ func (geneve *Geneve) Type() string {
|
||||
return "geneve"
|
||||
}
|
||||
|
||||
type GeneveDf uint8
|
||||
|
||||
const (
|
||||
GENEVE_DF_UNSET GeneveDf = iota
|
||||
GENEVE_DF_SET
|
||||
GENEVE_DF_INHERIT
|
||||
GENEVE_DF_MAX
|
||||
)
|
||||
|
||||
// Gretap devices must specify LocalIP and RemoteIP on create
|
||||
type Gretap struct {
|
||||
LinkAttrs
|
||||
@ -1064,6 +1131,7 @@ type Ip6tnl struct {
|
||||
EncapFlags uint16
|
||||
EncapSport uint16
|
||||
EncapDport uint16
|
||||
FlowBased bool
|
||||
}
|
||||
|
||||
func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs {
|
||||
@ -1165,6 +1233,7 @@ type Gretun struct {
|
||||
EncapFlags uint16
|
||||
EncapSport uint16
|
||||
EncapDport uint16
|
||||
FlowBased bool
|
||||
}
|
||||
|
||||
func (gretun *Gretun) Attrs() *LinkAttrs {
|
||||
@ -1208,6 +1277,7 @@ func (gtp *GTP) Type() string {
|
||||
}
|
||||
|
||||
// Virtual XFRM Interfaces
|
||||
//
|
||||
// Named "xfrmi" to prevent confusion with XFRM objects
|
||||
type Xfrmi struct {
|
||||
LinkAttrs
|
||||
|
584
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
584
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
@ -345,6 +345,16 @@ func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error {
|
||||
return h.linkModify(bridge, unix.NLM_F_ACK)
|
||||
}
|
||||
|
||||
func BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
|
||||
return pkgHandle.BridgeSetVlanDefaultPVID(link, pvid)
|
||||
}
|
||||
|
||||
func (h *Handle) BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
|
||||
bridge := link.(*Bridge)
|
||||
bridge.VlanDefaultPVID = &pvid
|
||||
return h.linkModify(bridge, unix.NLM_F_ACK)
|
||||
}
|
||||
|
||||
func SetPromiscOn(link Link) error {
|
||||
return pkgHandle.SetPromiscOn(link)
|
||||
}
|
||||
@ -487,6 +497,58 @@ func (h *Handle) LinkSetAlias(link Link, name string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkAddAltName adds a new alternative name for the link device.
|
||||
// Equivalent to: `ip link property add $link altname $name`
|
||||
func LinkAddAltName(link Link, name string) error {
|
||||
return pkgHandle.LinkAddAltName(link, name)
|
||||
}
|
||||
|
||||
// LinkAddAltName adds a new alternative name for the link device.
|
||||
// Equivalent to: `ip link property add $link altname $name`
|
||||
func (h *Handle) LinkAddAltName(link Link, name string) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWLINKPROP, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
|
||||
data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name))
|
||||
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkDelAltName delete an alternative name for the link device.
|
||||
// Equivalent to: `ip link property del $link altname $name`
|
||||
func LinkDelAltName(link Link, name string) error {
|
||||
return pkgHandle.LinkDelAltName(link, name)
|
||||
}
|
||||
|
||||
// LinkDelAltName delete an alternative name for the link device.
|
||||
// Equivalent to: `ip link property del $link altname $name`
|
||||
func (h *Handle) LinkDelAltName(link Link, name string) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_DELLINKPROP, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
|
||||
data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name))
|
||||
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetHardwareAddr sets the hardware address of the link device.
|
||||
// Equivalent to: `ip link set $link address $hwaddr`
|
||||
func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
|
||||
@ -602,6 +664,43 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
|
||||
func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto)
|
||||
}
|
||||
|
||||
// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
|
||||
func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
|
||||
vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
|
||||
vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil)
|
||||
|
||||
vfmsg := nl.VfVlanInfo{
|
||||
VfVlan: nl.VfVlan{
|
||||
Vf: uint32(vf),
|
||||
Vlan: uint32(vlan),
|
||||
Qos: uint32(qos),
|
||||
},
|
||||
VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8,
|
||||
}
|
||||
|
||||
vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, vfmsg.Serialize())
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetVfTxRate sets the tx rate of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf rate $rate`
|
||||
func LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||
@ -946,6 +1045,141 @@ func LinkSetXdpFdWithFlags(link Link, fd, flags int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_segs $maxSegs`
|
||||
func LinkSetGSOMaxSegs(link Link, maxSegs int) error {
|
||||
return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs)
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_segs $maxSegs`
|
||||
func (h *Handle) LinkSetGSOMaxSegs(link Link, maxSize int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_size $maxSize`
|
||||
func LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGSOMaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_max_size $maxSize`
|
||||
func LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGROMaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
|
||||
func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
|
||||
func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func boolAttr(val bool) []byte {
|
||||
var v uint8
|
||||
if val {
|
||||
@ -1401,6 +1635,21 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
req.AddData(gsoAttr)
|
||||
}
|
||||
|
||||
if base.GROMaxSize > 0 {
|
||||
groAttr := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, nl.Uint32Attr(base.GROMaxSize))
|
||||
req.AddData(groAttr)
|
||||
}
|
||||
|
||||
if base.GSOIPv4MaxSize > 0 {
|
||||
gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GSOIPv4MaxSize))
|
||||
req.AddData(gsoAttr)
|
||||
}
|
||||
|
||||
if base.GROIPv4MaxSize > 0 {
|
||||
groAttr := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GROIPv4MaxSize))
|
||||
req.AddData(groAttr)
|
||||
}
|
||||
|
||||
if base.Group > 0 {
|
||||
groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
|
||||
req.AddData(groupAttr)
|
||||
@ -1437,6 +1686,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
|
||||
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
|
||||
}
|
||||
case *Netkit:
|
||||
if err := addNetkitAttrs(link, linkInfo, flags); err != nil {
|
||||
return err
|
||||
}
|
||||
case *Veth:
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
|
||||
@ -1480,15 +1733,9 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
|
||||
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
|
||||
case *Macvlan:
|
||||
if link.Mode != MACVLAN_MODE_DEFAULT {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
|
||||
}
|
||||
addMacvlanAttrs(link, linkInfo)
|
||||
case *Macvtap:
|
||||
if link.Mode != MACVLAN_MODE_DEFAULT {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
|
||||
}
|
||||
addMacvtapAttrs(link, linkInfo)
|
||||
case *Geneve:
|
||||
addGeneveAttrs(link, linkInfo)
|
||||
case *Gretap:
|
||||
@ -1569,6 +1816,13 @@ func (h *Handle) linkByNameDump(name string) (Link, error) {
|
||||
if link.Attrs().Name == name {
|
||||
return link, nil
|
||||
}
|
||||
|
||||
// support finding interfaces also via altnames
|
||||
for _, altName := range link.Attrs().AltNames {
|
||||
if altName == name {
|
||||
return link, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
|
||||
}
|
||||
@ -1607,6 +1861,9 @@ func (h *Handle) LinkByName(name string) (Link, error) {
|
||||
req.AddData(attr)
|
||||
|
||||
nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name))
|
||||
if len(name) > 15 {
|
||||
nameData = nl.NewRtAttr(unix.IFLA_ALT_IFNAME, nl.ZeroTerminated(name))
|
||||
}
|
||||
req.AddData(nameData)
|
||||
|
||||
link, err := execGetLink(req)
|
||||
@ -1712,9 +1969,6 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
base.Flags = linkFlags(msg.Flags)
|
||||
base.EncapType = msg.EncapType()
|
||||
base.NetNsID = -1
|
||||
if msg.Flags&unix.IFF_PROMISC != 0 {
|
||||
base.Promisc = 1
|
||||
}
|
||||
if msg.Flags&unix.IFF_ALLMULTI != 0 {
|
||||
base.Allmulti = 1
|
||||
}
|
||||
@ -1750,6 +2004,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
link = &Bridge{}
|
||||
case "vlan":
|
||||
link = &Vlan{}
|
||||
case "netkit":
|
||||
link = &Netkit{}
|
||||
case "veth":
|
||||
link = &Veth{}
|
||||
case "wireguard":
|
||||
@ -1807,6 +2063,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
return nil, err
|
||||
}
|
||||
switch linkType {
|
||||
case "netkit":
|
||||
parseNetkitData(link, data)
|
||||
case "vlan":
|
||||
parseVlanData(link, data)
|
||||
case "vxlan":
|
||||
@ -1897,6 +2155,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
base.Name = string(attr.Value[:len(attr.Value)-1])
|
||||
case unix.IFLA_MTU:
|
||||
base.MTU = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_PROMISCUITY:
|
||||
base.Promisc = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_LINK:
|
||||
base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_MASTER:
|
||||
@ -1931,16 +2191,38 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
protinfo := parseProtinfo(attrs)
|
||||
base.Protinfo = &protinfo
|
||||
}
|
||||
case unix.IFLA_PROP_LIST | unix.NLA_F_NESTED:
|
||||
attrs, err := nl.ParseRouteAttr(attr.Value[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.AltNames = []string{}
|
||||
for _, attr := range attrs {
|
||||
if attr.Attr.Type == unix.IFLA_ALT_IFNAME {
|
||||
base.AltNames = append(base.AltNames, nl.BytesToString(attr.Value))
|
||||
}
|
||||
}
|
||||
case unix.IFLA_OPERSTATE:
|
||||
base.OperState = LinkOperState(uint8(attr.Value[0]))
|
||||
case unix.IFLA_PHYS_SWITCH_ID:
|
||||
base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_LINK_NETNSID:
|
||||
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_GSO_MAX_SIZE:
|
||||
base.GSOMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_TSO_MAX_SEGS:
|
||||
base.TSOMaxSegs = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_TSO_MAX_SIZE:
|
||||
base.TSOMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_MAX_SEGS:
|
||||
base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_MAX_SIZE:
|
||||
base.GSOMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GRO_MAX_SIZE:
|
||||
base.GROMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_IPV4_MAX_SIZE:
|
||||
base.GSOIPv4MaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GRO_IPV4_MAX_SIZE:
|
||||
base.GROIPv4MaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_VFINFO_LIST:
|
||||
data, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
@ -1957,6 +2239,13 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_GROUP:
|
||||
base.Group = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_PERM_ADDRESS:
|
||||
for _, b := range attr.Value {
|
||||
if b != 0 {
|
||||
base.PermHWAddr = attr.Value[:]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2069,21 +2358,24 @@ type LinkUpdate struct {
|
||||
// LinkSubscribe takes a chan down which notifications will be sent
|
||||
// when links change. Close the 'done' chan to stop subscription.
|
||||
func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
|
||||
return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
|
||||
return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// LinkSubscribeAt works like LinkSubscribe plus it allows the caller
|
||||
// to choose the network namespace in which to subscribe (ns).
|
||||
func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
|
||||
return linkSubscribeAt(ns, netns.None(), ch, done, nil, false)
|
||||
return linkSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// LinkSubscribeOptions contains a set of options to use with
|
||||
// LinkSubscribeWithOptions.
|
||||
type LinkSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// LinkSubscribeWithOptions work like LinkSubscribe but enable to
|
||||
@ -2094,14 +2386,27 @@ func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, option
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -2182,6 +2487,16 @@ func (h *Handle) LinkSetGuard(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
|
||||
}
|
||||
|
||||
// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
|
||||
func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
|
||||
return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask)
|
||||
}
|
||||
|
||||
// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
|
||||
func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
|
||||
return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK)
|
||||
}
|
||||
|
||||
func LinkSetFastLeave(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetFastLeave(link, mode)
|
||||
}
|
||||
@ -2214,6 +2529,14 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
|
||||
}
|
||||
|
||||
func LinkSetIsolated(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetIsolated(link, mode)
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetIsolated(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_ISOLATED)
|
||||
}
|
||||
|
||||
func LinkSetBrProxyArp(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetBrProxyArp(link, mode)
|
||||
}
|
||||
@ -2230,7 +2553,15 @@ func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI)
|
||||
}
|
||||
|
||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
func LinkSetBrNeighSuppress(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetBrNeighSuppress(link, mode)
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS)
|
||||
}
|
||||
|
||||
func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
@ -2240,7 +2571,7 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
req.AddData(msg)
|
||||
|
||||
br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
|
||||
br.AddRtAttr(attr, boolToByte(mode))
|
||||
br.AddRtAttr(attr, val)
|
||||
req.AddData(br)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
if err != nil {
|
||||
@ -2248,6 +2579,9 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr)
|
||||
}
|
||||
|
||||
// LinkSetTxQLen sets the transaction queue length for the link.
|
||||
// Equivalent to: `ip link set $link txqlen $qlen`
|
||||
@ -2305,6 +2639,80 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
|
||||
if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
|
||||
return fmt.Errorf("netkit doesn't support setting Ethernet")
|
||||
}
|
||||
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
// Kernel will return error if trying to change the mode of an existing netkit device
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
|
||||
|
||||
if (flag & unix.NLM_F_EXCL) == 0 {
|
||||
// Modifying peer link attributes will not take effect
|
||||
return nil
|
||||
}
|
||||
|
||||
peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil)
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
if nk.peerLinkAttrs.Flags&net.FlagUp != 0 {
|
||||
msg.Change = unix.IFF_UP
|
||||
msg.Flags = unix.IFF_UP
|
||||
}
|
||||
if nk.peerLinkAttrs.Index != 0 {
|
||||
msg.Index = int32(nk.peerLinkAttrs.Index)
|
||||
}
|
||||
peer.AddChild(msg)
|
||||
if nk.peerLinkAttrs.Name != "" {
|
||||
peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name))
|
||||
}
|
||||
if nk.peerLinkAttrs.MTU > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU)))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOMaxSegs > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOMaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.GROIPv4MaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.Namespace != nil {
|
||||
switch ns := nk.peerLinkAttrs.Namespace.(type) {
|
||||
case NsPid:
|
||||
peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns)))
|
||||
case NsFd:
|
||||
peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
netkit := link.(*Netkit)
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.IFLA_NETKIT_PRIMARY:
|
||||
isPrimary := datum.Value[0:1][0]
|
||||
if isPrimary != 0 {
|
||||
netkit.isPrimary = true
|
||||
}
|
||||
case nl.IFLA_NETKIT_MODE:
|
||||
netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4]))
|
||||
case nl.IFLA_NETKIT_POLICY:
|
||||
netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
|
||||
case nl.IFLA_NETKIT_PEER_POLICY:
|
||||
netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
vlan := link.(*Vlan)
|
||||
for _, datum := range data {
|
||||
@ -2539,11 +2947,30 @@ func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
}
|
||||
}
|
||||
|
||||
func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) {
|
||||
addMacvlanAttrs(&macvtap.Macvlan, linkInfo)
|
||||
}
|
||||
|
||||
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
macv := link.(*Macvtap)
|
||||
parseMacvlanData(&macv.Macvlan, data)
|
||||
}
|
||||
|
||||
func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) {
|
||||
var data *nl.RtAttr
|
||||
|
||||
if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 {
|
||||
data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
}
|
||||
|
||||
if macvlan.Mode != MACVLAN_MODE_DEFAULT {
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode]))
|
||||
}
|
||||
if macvlan.BCQueueLen > 0 {
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen))
|
||||
}
|
||||
}
|
||||
|
||||
func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
macv := link.(*Macvlan)
|
||||
for _, datum := range data {
|
||||
@ -2571,6 +2998,10 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
for _, macDatum := range macs {
|
||||
macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6]))
|
||||
}
|
||||
case nl.IFLA_MACVLAN_BC_QUEUE_LEN:
|
||||
macv.BCQueueLen = native.Uint32(datum.Value[0:4])
|
||||
case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED:
|
||||
macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2599,10 +3030,13 @@ func linkFlags(rawFlags uint32) net.Flags {
|
||||
func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if geneve.InnerProtoInherit {
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_INNER_PROTO_INHERIT, []byte{})
|
||||
}
|
||||
|
||||
if geneve.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
linkInfo.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, boolAttr(geneve.FlowBased))
|
||||
return
|
||||
geneve.ID = 0
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, []byte{})
|
||||
}
|
||||
|
||||
if ip := geneve.Remote; ip != nil {
|
||||
@ -2628,6 +3062,8 @@ func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||
if geneve.Tos != 0 {
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
|
||||
}
|
||||
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df)))
|
||||
}
|
||||
|
||||
func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
@ -2644,6 +3080,10 @@ func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
geneve.Ttl = uint8(datum.Value[0])
|
||||
case nl.IFLA_GENEVE_TOS:
|
||||
geneve.Tos = uint8(datum.Value[0])
|
||||
case nl.IFLA_GENEVE_COLLECT_METADATA:
|
||||
geneve.FlowBased = true
|
||||
case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
|
||||
geneve.InnerProtoInherit = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2653,7 +3093,7 @@ func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
|
||||
|
||||
if gretap.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
@ -2736,6 +3176,12 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if gre.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
if ip := gre.Local; ip != nil {
|
||||
if ip.To4() != nil {
|
||||
ip = ip.To4()
|
||||
@ -2806,6 +3252,8 @@ func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
gre.EncapSport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_ENCAP_DPORT:
|
||||
gre.EncapDport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_COLLECT_METADATA:
|
||||
gre.FlowBased = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2846,14 +3294,14 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
|
||||
}
|
||||
|
||||
func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if iptun.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased))
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
ip := iptun.Local.To4()
|
||||
if ip != nil {
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
|
||||
@ -2880,10 +3328,6 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
|
||||
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
iptun := link.(*Iptun)
|
||||
for _, datum := range data {
|
||||
// NOTE: same with vxlan, ip tunnel may also has null datum.Value
|
||||
if len(datum.Value) == 0 {
|
||||
continue
|
||||
}
|
||||
switch datum.Attr.Type {
|
||||
case nl.IFLA_IPTUN_LOCAL:
|
||||
iptun.Local = net.IP(datum.Value[0:4])
|
||||
@ -2914,6 +3358,12 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if ip6tnl.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
if ip6tnl.Link != 0 {
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
|
||||
}
|
||||
@ -2968,6 +3418,8 @@ func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
ip6tnl.EncapSport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_IPTUN_ENCAP_DPORT:
|
||||
ip6tnl.EncapDport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_IPTUN_COLLECT_METADATA:
|
||||
ip6tnl.FlowBased = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3115,6 +3567,12 @@ func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
|
||||
if bridge.VlanFiltering != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering))
|
||||
}
|
||||
if bridge.VlanDefaultPVID != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID))
|
||||
}
|
||||
if bridge.GroupFwdMask != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask))
|
||||
}
|
||||
}
|
||||
|
||||
func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
|
||||
@ -3133,6 +3591,12 @@ func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
|
||||
case nl.IFLA_BR_VLAN_FILTERING:
|
||||
vlanFiltering := datum.Value[0] == 1
|
||||
br.VlanFiltering = &vlanFiltering
|
||||
case nl.IFLA_BR_VLAN_DEFAULT_PVID:
|
||||
vlanDefaultPVID := native.Uint16(datum.Value[0:2])
|
||||
br.VlanDefaultPVID = &vlanDefaultPVID
|
||||
case nl.IFLA_BR_GROUP_FWD_MASK:
|
||||
mask := native.Uint16(datum.Value[0:2])
|
||||
br.GroupFwdMask = &mask
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3174,12 +3638,17 @@ func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vfs = append(vfs, parseVfInfo(vfAttrs, i))
|
||||
|
||||
vf, err := parseVfInfo(vfAttrs, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vfs = append(vfs, vf)
|
||||
}
|
||||
return vfs, nil
|
||||
}
|
||||
|
||||
func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) {
|
||||
vf := VfInfo{ID: id}
|
||||
for _, element := range data {
|
||||
switch element.Attr.Type {
|
||||
@ -3190,6 +3659,12 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
vl := nl.DeserializeVfVlan(element.Value[:])
|
||||
vf.Vlan = int(vl.Vlan)
|
||||
vf.Qos = int(vl.Qos)
|
||||
case nl.IFLA_VF_VLAN_LIST:
|
||||
vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:])
|
||||
if err != nil {
|
||||
return vf, err
|
||||
}
|
||||
vf.VlanProto = int(vfVlanInfoList[0].VlanProto)
|
||||
case nl.IFLA_VF_TX_RATE:
|
||||
txr := nl.DeserializeVfTxRate(element.Value[:])
|
||||
vf.TxRate = int(txr.Rate)
|
||||
@ -3223,7 +3698,7 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
vf.Trust = result.Setting
|
||||
}
|
||||
}
|
||||
return vf
|
||||
return vf, nil
|
||||
}
|
||||
|
||||
func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
|
||||
@ -3246,8 +3721,7 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
}
|
||||
}
|
||||
|
||||
// LinkSetBondSlave add slave to bond link via ioctl interface.
|
||||
func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
|
||||
fd, err := getSocketUDP()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -3255,10 +3729,38 @@ func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
defer syscall.Close(fd)
|
||||
|
||||
ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
|
||||
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq)))
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno)
|
||||
return fmt.Errorf("errno=%v", errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
|
||||
//
|
||||
// Multiple calls keeps the status unchanged(shown in the unit test).
|
||||
func LinkSetBondSlaveActive(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlave add slave to bond link via ioctl interface.
|
||||
func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlave removes specified slave from bond link via ioctl interface.
|
||||
func LinkDelBondSlave(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
39
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
39
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
@ -339,13 +339,13 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
||||
// 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)
|
||||
return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, 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)
|
||||
return neighSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// NeighSubscribeOptions contains a set of options to use with
|
||||
@ -354,6 +354,11 @@ type NeighSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
|
||||
// max size is based on value of /proc/sys/net/core/rmem_max
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// NeighSubscribeWithOptions work like NeighSubscribe but enable to
|
||||
@ -364,16 +369,17 @@ func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, opti
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH)
|
||||
makeRequest := func(family int) error {
|
||||
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH,
|
||||
unix.NLM_F_DUMP)
|
||||
infmsg := nl.NewIfInfomsg(family)
|
||||
req.AddData(infmsg)
|
||||
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
|
||||
ndmsg := &Ndmsg{Family: uint8(family)}
|
||||
req.AddData(ndmsg)
|
||||
if err := s.Send(req); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -382,6 +388,17 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -427,12 +444,12 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
|
||||
continue
|
||||
}
|
||||
if m.Header.Type == unix.NLMSG_ERROR {
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
if error == 0 {
|
||||
nError := int32(native.Uint32(m.Data[0:4]))
|
||||
if nError == 0 {
|
||||
continue
|
||||
}
|
||||
if cberr != nil {
|
||||
cberr(syscall.Errno(-error))
|
||||
cberr(syscall.Errno(-nError))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
32
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
32
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
@ -52,6 +52,10 @@ func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -124,6 +128,22 @@ func LinkSetTxQLen(link Link, qlen int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkAdd(link Link) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -184,6 +204,10 @@ func RouteAppend(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func RouteChange(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func RouteDel(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -216,6 +240,10 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func XfrmStateAdd(policy *XfrmState) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -255,3 +283,7 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
||||
func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func SocketDestroy(local, remote net.Addr) (*Socket, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
39
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
39
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
@ -15,6 +15,38 @@ var L4ProtoMap = map[uint8]string{
|
||||
17: "udp",
|
||||
}
|
||||
|
||||
// From https://git.netfilter.org/libnetfilter_conntrack/tree/include/libnetfilter_conntrack/libnetfilter_conntrack_tcp.h
|
||||
// enum tcp_state {
|
||||
// TCP_CONNTRACK_NONE,
|
||||
// TCP_CONNTRACK_SYN_SENT,
|
||||
// TCP_CONNTRACK_SYN_RECV,
|
||||
// TCP_CONNTRACK_ESTABLISHED,
|
||||
// TCP_CONNTRACK_FIN_WAIT,
|
||||
// TCP_CONNTRACK_CLOSE_WAIT,
|
||||
// TCP_CONNTRACK_LAST_ACK,
|
||||
// TCP_CONNTRACK_TIME_WAIT,
|
||||
// TCP_CONNTRACK_CLOSE,
|
||||
// TCP_CONNTRACK_LISTEN, /* obsolete */
|
||||
// #define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN
|
||||
// TCP_CONNTRACK_MAX,
|
||||
// TCP_CONNTRACK_IGNORE
|
||||
// };
|
||||
const (
|
||||
TCP_CONNTRACK_NONE = 0
|
||||
TCP_CONNTRACK_SYN_SENT = 1
|
||||
TCP_CONNTRACK_SYN_RECV = 2
|
||||
TCP_CONNTRACK_ESTABLISHED = 3
|
||||
TCP_CONNTRACK_FIN_WAIT = 4
|
||||
TCP_CONNTRACK_CLOSE_WAIT = 5
|
||||
TCP_CONNTRACK_LAST_ACK = 6
|
||||
TCP_CONNTRACK_TIME_WAIT = 7
|
||||
TCP_CONNTRACK_CLOSE = 8
|
||||
TCP_CONNTRACK_LISTEN = 9
|
||||
TCP_CONNTRACK_SYN_SENT2 = 9
|
||||
TCP_CONNTRACK_MAX = 10
|
||||
TCP_CONNTRACK_IGNORE = 11
|
||||
)
|
||||
|
||||
// All the following constants are coming from:
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h
|
||||
|
||||
@ -31,6 +63,7 @@ var L4ProtoMap = map[uint8]string{
|
||||
// IPCTNL_MSG_MAX
|
||||
// };
|
||||
const (
|
||||
IPCTNL_MSG_CT_NEW = 0
|
||||
IPCTNL_MSG_CT_GET = 1
|
||||
IPCTNL_MSG_CT_DELETE = 2
|
||||
)
|
||||
@ -88,7 +121,10 @@ const (
|
||||
CTA_COUNTERS_REPLY = 10
|
||||
CTA_USE = 11
|
||||
CTA_ID = 12
|
||||
CTA_ZONE = 18
|
||||
CTA_TIMESTAMP = 20
|
||||
CTA_LABELS = 22
|
||||
CTA_LABELS_MASK = 23
|
||||
)
|
||||
|
||||
// enum ctattr_tuple {
|
||||
@ -149,7 +185,10 @@ const (
|
||||
// };
|
||||
// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
|
||||
const (
|
||||
CTA_PROTOINFO_UNSPEC = 0
|
||||
CTA_PROTOINFO_TCP = 1
|
||||
CTA_PROTOINFO_DCCP = 2
|
||||
CTA_PROTOINFO_SCTP = 3
|
||||
)
|
||||
|
||||
// enum ctattr_protoinfo_tcp {
|
||||
|
106
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
106
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
@ -9,39 +9,56 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_RESOURCE_DUMP = 36
|
||||
DEVLINK_CMD_PARAM_GET = 38
|
||||
DEVLINK_CMD_PARAM_SET = 39
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_ATTR_BUS_NAME = 1
|
||||
DEVLINK_ATTR_DEV_NAME = 2
|
||||
DEVLINK_ATTR_PORT_INDEX = 3
|
||||
DEVLINK_ATTR_PORT_TYPE = 4
|
||||
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
||||
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
||||
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
||||
DEVLINK_ATTR_ESWITCH_MODE = 25
|
||||
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
||||
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
DEVLINK_ATTR_BUS_NAME = 1
|
||||
DEVLINK_ATTR_DEV_NAME = 2
|
||||
DEVLINK_ATTR_PORT_INDEX = 3
|
||||
DEVLINK_ATTR_PORT_TYPE = 4
|
||||
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
||||
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
||||
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
||||
DEVLINK_ATTR_ESWITCH_MODE = 25
|
||||
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
||||
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
||||
DEVLINK_ATTR_RESOURCE_LIST = 63 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE = 64 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE_NAME = 65 /* string */
|
||||
DEVLINK_ATTR_RESOURCE_ID = 66 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE = 67 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_NEW = 68 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_VALID = 69 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MIN = 70 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MAX = 71 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 72 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_UNIT = 73 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_OCC = 74 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 75 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 76 /* u64 */
|
||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
)
|
||||
|
||||
const (
|
||||
@ -94,3 +111,32 @@ const (
|
||||
DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
|
||||
DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_RESOURCE_UNIT_ENTRY uint8 = 0
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_ATTR_PARAM = iota + 80 /* nested */
|
||||
DEVLINK_ATTR_PARAM_NAME /* string */
|
||||
DEVLINK_ATTR_PARAM_GENERIC /* flag */
|
||||
DEVLINK_ATTR_PARAM_TYPE /* u8 */
|
||||
DEVLINK_ATTR_PARAM_VALUES_LIST /* nested */
|
||||
DEVLINK_ATTR_PARAM_VALUE /* nested */
|
||||
DEVLINK_ATTR_PARAM_VALUE_DATA /* dynamic */
|
||||
DEVLINK_ATTR_PARAM_VALUE_CMODE /* u8 */
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_PARAM_TYPE_U8 = 1
|
||||
DEVLINK_PARAM_TYPE_U16 = 2
|
||||
DEVLINK_PARAM_TYPE_U32 = 3
|
||||
DEVLINK_PARAM_TYPE_STRING = 5
|
||||
DEVLINK_PARAM_TYPE_BOOL = 6
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_PARAM_CMODE_RUNTIME = iota
|
||||
DEVLINK_PARAM_CMODE_DRIVERINIT
|
||||
DEVLINK_PARAM_CMODE_PERMANENT
|
||||
)
|
||||
|
21
vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go
generated
vendored
Normal file
21
vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package nl
|
||||
|
||||
// id's of route attribute from https://elixir.bootlin.com/linux/v5.17.3/source/include/uapi/linux/lwtunnel.h#L38
|
||||
// the value's size are specified in https://elixir.bootlin.com/linux/v5.17.3/source/net/ipv4/ip_tunnel_core.c#L928
|
||||
|
||||
const (
|
||||
LWTUNNEL_IP6_UNSPEC = iota
|
||||
LWTUNNEL_IP6_ID
|
||||
LWTUNNEL_IP6_DST
|
||||
LWTUNNEL_IP6_SRC
|
||||
LWTUNNEL_IP6_HOPLIMIT
|
||||
LWTUNNEL_IP6_TC
|
||||
LWTUNNEL_IP6_FLAGS
|
||||
LWTUNNEL_IP6_PAD // not implemented
|
||||
LWTUNNEL_IP6_OPTS // not implemented
|
||||
__LWTUNNEL_IP6_MAX
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
5
vendor/github.com/vishvananda/netlink/nl/ipset_linux.go
generated
vendored
5
vendor/github.com/vishvananda/netlink/nl/ipset_linux.go
generated
vendored
@ -88,6 +88,11 @@ const (
|
||||
SET_ATTR_CREATE_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
IPSET_ATTR_IPADDR_IPV4 = 1
|
||||
IPSET_ATTR_IPADDR_IPV6 = 2
|
||||
)
|
||||
|
||||
/* ADT specific attributes */
|
||||
const (
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1
|
||||
|
106
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
106
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
@ -3,6 +3,7 @@ package nl
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -30,6 +31,16 @@ const (
|
||||
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_NETKIT_UNSPEC = iota
|
||||
IFLA_NETKIT_PEER_INFO
|
||||
IFLA_NETKIT_PRIMARY
|
||||
IFLA_NETKIT_POLICY
|
||||
IFLA_NETKIT_PEER_POLICY
|
||||
IFLA_NETKIT_MODE
|
||||
IFLA_NETKIT_MAX = IFLA_NETKIT_MODE
|
||||
)
|
||||
|
||||
const (
|
||||
VETH_INFO_UNSPEC = iota
|
||||
VETH_INFO_PEER
|
||||
@ -85,7 +96,37 @@ const (
|
||||
IFLA_BRPORT_PROXYARP
|
||||
IFLA_BRPORT_LEARNING_SYNC
|
||||
IFLA_BRPORT_PROXYARP_WIFI
|
||||
IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI
|
||||
IFLA_BRPORT_ROOT_ID
|
||||
IFLA_BRPORT_BRIDGE_ID
|
||||
IFLA_BRPORT_DESIGNATED_PORT
|
||||
IFLA_BRPORT_DESIGNATED_COST
|
||||
IFLA_BRPORT_ID
|
||||
IFLA_BRPORT_NO
|
||||
IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
|
||||
IFLA_BRPORT_CONFIG_PENDING
|
||||
IFLA_BRPORT_MESSAGE_AGE_TIMER
|
||||
IFLA_BRPORT_FORWARD_DELAY_TIMER
|
||||
IFLA_BRPORT_HOLD_TIMER
|
||||
IFLA_BRPORT_FLUSH
|
||||
IFLA_BRPORT_MULTICAST_ROUTER
|
||||
IFLA_BRPORT_PAD
|
||||
IFLA_BRPORT_MCAST_FLOOD
|
||||
IFLA_BRPORT_MCAST_TO_UCAST
|
||||
IFLA_BRPORT_VLAN_TUNNEL
|
||||
IFLA_BRPORT_BCAST_FLOOD
|
||||
IFLA_BRPORT_GROUP_FWD_MASK
|
||||
IFLA_BRPORT_NEIGH_SUPPRESS
|
||||
IFLA_BRPORT_ISOLATED
|
||||
IFLA_BRPORT_BACKUP_PORT
|
||||
IFLA_BRPORT_MRP_RING_OPEN
|
||||
IFLA_BRPORT_MRP_IN_OPEN
|
||||
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT
|
||||
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT
|
||||
IFLA_BRPORT_LOCKED
|
||||
IFLA_BRPORT_MAB
|
||||
IFLA_BRPORT_MCAST_N_GROUPS
|
||||
IFLA_BRPORT_MCAST_MAX_GROUPS
|
||||
IFLA_BRPORT_MAX = IFLA_BRPORT_MCAST_MAX_GROUPS
|
||||
)
|
||||
|
||||
const (
|
||||
@ -103,7 +144,9 @@ const (
|
||||
IFLA_MACVLAN_MACADDR
|
||||
IFLA_MACVLAN_MACADDR_DATA
|
||||
IFLA_MACVLAN_MACADDR_COUNT
|
||||
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
|
||||
IFLA_MACVLAN_BC_QUEUE_LEN
|
||||
IFLA_MACVLAN_BC_QUEUE_LEN_USED
|
||||
IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED
|
||||
)
|
||||
|
||||
const (
|
||||
@ -186,7 +229,10 @@ const (
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_TX
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_RX
|
||||
IFLA_GENEVE_LABEL
|
||||
IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL
|
||||
IFLA_GENEVE_TTL_INHERIT
|
||||
IFLA_GENEVE_DF
|
||||
IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||
)
|
||||
|
||||
const (
|
||||
@ -244,7 +290,15 @@ const (
|
||||
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
|
||||
IFLA_VF_VLAN_LIST /* nested list of vlans, option for QinQ */
|
||||
|
||||
IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_VLAN_INFO_UNSPEC = iota
|
||||
IFLA_VF_VLAN_INFO /* VLAN ID, QoS and VLAN protocol */
|
||||
__IFLA_VF_VLAN_INFO_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
@ -269,6 +323,7 @@ const (
|
||||
const (
|
||||
SizeofVfMac = 0x24
|
||||
SizeofVfVlan = 0x0c
|
||||
SizeofVfVlanInfo = 0x10
|
||||
SizeofVfTxRate = 0x08
|
||||
SizeofVfRate = 0x0c
|
||||
SizeofVfSpoofchk = 0x08
|
||||
@ -324,6 +379,49 @@ func (msg *VfVlan) Serialize() []byte {
|
||||
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
func DeserializeVfVlanList(b []byte) ([]*VfVlanInfo, error) {
|
||||
var vfVlanInfoList []*VfVlanInfo
|
||||
attrs, err := ParseRouteAttr(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, element := range attrs {
|
||||
if element.Attr.Type == IFLA_VF_VLAN_INFO {
|
||||
vfVlanInfoList = append(vfVlanInfoList, DeserializeVfVlanInfo(element.Value))
|
||||
}
|
||||
}
|
||||
|
||||
if len(vfVlanInfoList) == 0 {
|
||||
return nil, fmt.Errorf("VF vlan list is defined but no vf vlan info elements were found")
|
||||
}
|
||||
|
||||
return vfVlanInfoList, nil
|
||||
}
|
||||
|
||||
// struct ifla_vf_vlan_info {
|
||||
// __u32 vf;
|
||||
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
// __u32 qos;
|
||||
// __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
|
||||
// };
|
||||
|
||||
type VfVlanInfo struct {
|
||||
VfVlan
|
||||
VlanProto uint16
|
||||
}
|
||||
|
||||
func DeserializeVfVlanInfo(b []byte) *VfVlanInfo {
|
||||
return &VfVlanInfo{
|
||||
*(*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])),
|
||||
binary.BigEndian.Uint16(b[SizeofVfVlan:SizeofVfVlanInfo]),
|
||||
}
|
||||
}
|
||||
|
||||
func (msg *VfVlanInfo) Serialize() []byte {
|
||||
return (*(*[SizeofVfVlanInfo]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_tx_rate {
|
||||
// __u32 vf;
|
||||
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
|
||||
|
206
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
206
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -330,6 +331,19 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
||||
return msg
|
||||
}
|
||||
|
||||
type Uint32Bitfield struct {
|
||||
Value uint32
|
||||
Selector uint32
|
||||
}
|
||||
|
||||
func (a *Uint32Bitfield) Serialize() []byte {
|
||||
return (*(*[SizeofUint32Bitfield]byte)(unsafe.Pointer(a)))[:]
|
||||
}
|
||||
|
||||
func DeserializeUint32Bitfield(data []byte) *Uint32Bitfield {
|
||||
return (*Uint32Bitfield)(unsafe.Pointer(&data[0:SizeofUint32Bitfield][0]))
|
||||
}
|
||||
|
||||
type Uint32Attribute struct {
|
||||
Type uint16
|
||||
Value uint32
|
||||
@ -475,10 +489,30 @@ func (req *NetlinkRequest) AddRawData(data []byte) {
|
||||
req.RawData = append(req.RawData, data...)
|
||||
}
|
||||
|
||||
// Execute the request against a the given sockType.
|
||||
// Execute the request against the given sockType.
|
||||
// Returns a list of netlink messages in serialized format, optionally filtered
|
||||
// by resType.
|
||||
func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
|
||||
var res [][]byte
|
||||
err := req.ExecuteIter(sockType, resType, func(msg []byte) bool {
|
||||
res = append(res, msg)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ExecuteIter executes the request against the given sockType.
|
||||
// Calls the provided callback func once for each netlink message.
|
||||
// If the callback returns false, it is not called again, but
|
||||
// the remaining messages are consumed/discarded.
|
||||
//
|
||||
// Thread safety: ExecuteIter holds a lock on the socket until
|
||||
// it finishes iteration so the callback must not call back into
|
||||
// the netlink API.
|
||||
func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg []byte) bool) error {
|
||||
var (
|
||||
s *NetlinkSocket
|
||||
err error
|
||||
@ -495,18 +529,18 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
||||
if s == nil {
|
||||
s, err = getNetlinkSocket(sockType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if EnableErrorMessageReporting {
|
||||
if err := s.SetExtAck(true); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,36 +551,44 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
||||
}
|
||||
|
||||
if err := s.Send(req); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
pid, err := s.GetPid()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
var res [][]byte
|
||||
|
||||
done:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if from.Pid != PidKernel {
|
||||
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
|
||||
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
|
||||
}
|
||||
for _, m := range msgs {
|
||||
if m.Header.Seq != req.Seq {
|
||||
if sharedSocket {
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
|
||||
return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
|
||||
}
|
||||
if m.Header.Pid != pid {
|
||||
continue
|
||||
}
|
||||
|
||||
if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 {
|
||||
return syscall.Errno(unix.EINTR)
|
||||
}
|
||||
|
||||
if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR {
|
||||
// NLMSG_DONE might have no payload, if so assume no error.
|
||||
if m.Header.Type == unix.NLMSG_DONE && len(m.Data) == 0 {
|
||||
break done
|
||||
}
|
||||
|
||||
native := NativeEndian()
|
||||
errno := int32(native.Uint32(m.Data[0:4]))
|
||||
if errno == 0 {
|
||||
@ -556,7 +598,7 @@ done:
|
||||
err = syscall.Errno(-errno)
|
||||
|
||||
unreadData := m.Data[4:]
|
||||
if m.Header.Flags|unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
|
||||
if m.Header.Flags&unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
|
||||
// Skip the echoed request message.
|
||||
echoReqH := (*syscall.NlMsghdr)(unsafe.Pointer(&unreadData[0]))
|
||||
unreadData = unreadData[nlmAlignOf(int(echoReqH.Len)):]
|
||||
@ -568,8 +610,7 @@ done:
|
||||
|
||||
switch attr.Type {
|
||||
case NLMSGERR_ATTR_MSG:
|
||||
err = fmt.Errorf("%w: %s", err, string(attrData))
|
||||
|
||||
err = fmt.Errorf("%w: %s", err, unix.ByteSliceToString(attrData))
|
||||
default:
|
||||
// TODO: handle other NLMSGERR_ATTR types
|
||||
}
|
||||
@ -578,18 +619,26 @@ done:
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if resType != 0 && m.Header.Type != resType {
|
||||
continue
|
||||
}
|
||||
res = append(res, m.Data)
|
||||
if cont := f(m.Data); !cont {
|
||||
// Drain the rest of the messages from the kernel but don't
|
||||
// pass them to the iterator func.
|
||||
f = dummyMsgIterFunc
|
||||
}
|
||||
if m.Header.Flags&unix.NLM_F_MULTI == 0 {
|
||||
break done
|
||||
}
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func dummyMsgIterFunc(msg []byte) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Create a new netlink request from proto and flags
|
||||
@ -607,8 +656,9 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
|
||||
}
|
||||
|
||||
type NetlinkSocket struct {
|
||||
fd int32
|
||||
lsa unix.SockaddrNetlink
|
||||
fd int32
|
||||
file *os.File
|
||||
lsa unix.SockaddrNetlink
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
@ -617,8 +667,13 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = unix.SetNonblock(fd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &NetlinkSocket{
|
||||
fd: int32(fd),
|
||||
fd: int32(fd),
|
||||
file: os.NewFile(uintptr(fd), "netlink"),
|
||||
}
|
||||
s.lsa.Family = unix.AF_NETLINK
|
||||
if err := unix.Bind(fd, &s.lsa); err != nil {
|
||||
@ -649,12 +704,14 @@ func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSock
|
||||
// In case of success, the caller is expected to execute the returned function
|
||||
// at the end of the code that needs to be executed in the network namespace.
|
||||
// Example:
|
||||
// func jobAt(...) error {
|
||||
// d, err := executeInNetns(...)
|
||||
// if err != nil { return err}
|
||||
// defer d()
|
||||
// < code which needs to be executed in specific netns>
|
||||
// }
|
||||
//
|
||||
// func jobAt(...) error {
|
||||
// d, err := executeInNetns(...)
|
||||
// if err != nil { return err}
|
||||
// defer d()
|
||||
// < code which needs to be executed in specific netns>
|
||||
// }
|
||||
//
|
||||
// TODO: his function probably belongs to netns pkg.
|
||||
func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
|
||||
var (
|
||||
@ -703,8 +760,13 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = unix.SetNonblock(fd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &NetlinkSocket{
|
||||
fd: int32(fd),
|
||||
fd: int32(fd),
|
||||
file: os.NewFile(uintptr(fd), "netlink"),
|
||||
}
|
||||
s.lsa.Family = unix.AF_NETLINK
|
||||
|
||||
@ -733,33 +795,36 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) Close() {
|
||||
fd := int(atomic.SwapInt32(&s.fd, -1))
|
||||
unix.Close(fd)
|
||||
s.file.Close()
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) GetFd() int {
|
||||
return int(atomic.LoadInt32(&s.fd))
|
||||
return int(s.fd)
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
|
||||
fd := int(atomic.LoadInt32(&s.fd))
|
||||
if fd < 0 {
|
||||
return fmt.Errorf("Send called on a closed socket")
|
||||
}
|
||||
if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return unix.Sendto(int(s.fd), request.Serialize(), 0, &s.lsa)
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) {
|
||||
fd := int(atomic.LoadInt32(&s.fd))
|
||||
if fd < 0 {
|
||||
return nil, nil, fmt.Errorf("Receive called on a closed socket")
|
||||
rawConn, err := s.file.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var (
|
||||
fromAddr *unix.SockaddrNetlink
|
||||
rb [RECEIVE_BUFFER_SIZE]byte
|
||||
nr int
|
||||
from unix.Sockaddr
|
||||
innerErr error
|
||||
)
|
||||
err = rawConn.Read(func(fd uintptr) (done bool) {
|
||||
nr, from, innerErr = unix.Recvfrom(int(fd), rb[:], 0)
|
||||
return innerErr != unix.EWOULDBLOCK
|
||||
})
|
||||
if innerErr != nil {
|
||||
err = innerErr
|
||||
}
|
||||
var fromAddr *unix.SockaddrNetlink
|
||||
var rb [RECEIVE_BUFFER_SIZE]byte
|
||||
nr, from, err := unix.Recvfrom(fd, rb[:], 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -770,8 +835,9 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli
|
||||
if nr < unix.NLMSG_HDRLEN {
|
||||
return nil, nil, fmt.Errorf("Got short response from netlink")
|
||||
}
|
||||
rb2 := make([]byte, nr)
|
||||
copy(rb2, rb[:nr])
|
||||
msgLen := nlmAlignOf(nr)
|
||||
rb2 := make([]byte, msgLen)
|
||||
copy(rb2, rb[:msgLen])
|
||||
nl, err := syscall.ParseNetlinkMessage(rb2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -793,6 +859,15 @@ func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
|
||||
return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
|
||||
}
|
||||
|
||||
// SetReceiveBufferSize allows to set a receive buffer size on the socket
|
||||
func (s *NetlinkSocket) SetReceiveBufferSize(size int, force bool) error {
|
||||
opt := unix.SO_RCVBUF
|
||||
if force {
|
||||
opt = unix.SO_RCVBUFFORCE
|
||||
}
|
||||
return unix.SetsockoptInt(int(s.fd), unix.SOL_SOCKET, opt, size)
|
||||
}
|
||||
|
||||
// SetExtAck requests error messages to be reported on the socket
|
||||
func (s *NetlinkSocket) SetExtAck(enable bool) error {
|
||||
var enableN int
|
||||
@ -804,8 +879,7 @@ func (s *NetlinkSocket) SetExtAck(enable bool) error {
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) GetPid() (uint32, error) {
|
||||
fd := int(atomic.LoadInt32(&s.fd))
|
||||
lsa, err := unix.Getsockname(fd)
|
||||
lsa, err := unix.Getsockname(int(s.fd))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -849,6 +923,12 @@ func Uint16Attr(v uint16) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint16Attr(v uint16) []byte {
|
||||
bytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func Uint32Attr(v uint32) []byte {
|
||||
native := NativeEndian()
|
||||
bytes := make([]byte, 4)
|
||||
@ -856,6 +936,12 @@ func Uint32Attr(v uint32) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint32Attr(v uint32) []byte {
|
||||
bytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func Uint64Attr(v uint64) []byte {
|
||||
native := NativeEndian()
|
||||
bytes := make([]byte, 8)
|
||||
@ -863,6 +949,12 @@ func Uint64Attr(v uint64) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint64Attr(v uint64) []byte {
|
||||
bytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
for len(b) >= unix.SizeofRtAttr {
|
||||
@ -877,6 +969,22 @@ func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
||||
return attrs, nil
|
||||
}
|
||||
|
||||
// ParseRouteAttrAsMap parses provided buffer that contains raw RtAttrs and returns a map of parsed
|
||||
// atttributes indexed by attribute type or error if occured.
|
||||
func ParseRouteAttrAsMap(b []byte) (map[uint16]syscall.NetlinkRouteAttr, error) {
|
||||
attrMap := make(map[uint16]syscall.NetlinkRouteAttr)
|
||||
|
||||
attrs, err := ParseRouteAttr(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, attr := range attrs {
|
||||
attrMap[attr.Attr.Type] = attr
|
||||
}
|
||||
return attrMap, nil
|
||||
}
|
||||
|
||||
func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
|
||||
a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
|
||||
if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {
|
||||
|
4
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
@ -48,7 +48,9 @@ type RtNexthop struct {
|
||||
}
|
||||
|
||||
func DeserializeRtNexthop(b []byte) *RtNexthop {
|
||||
return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))
|
||||
return &RtNexthop{
|
||||
RtNexthop: *((*unix.RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))),
|
||||
}
|
||||
}
|
||||
|
||||
func (msg *RtNexthop) Len() int {
|
||||
|
4
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
@ -12,6 +12,7 @@ const (
|
||||
SEG6_LOCAL_NH6
|
||||
SEG6_LOCAL_IIF
|
||||
SEG6_LOCAL_OIF
|
||||
SEG6_LOCAL_BPF
|
||||
__SEG6_LOCAL_MAX
|
||||
)
|
||||
const (
|
||||
@ -34,6 +35,7 @@ const (
|
||||
SEG6_LOCAL_ACTION_END_S // 12
|
||||
SEG6_LOCAL_ACTION_END_AS // 13
|
||||
SEG6_LOCAL_ACTION_END_AM // 14
|
||||
SEG6_LOCAL_ACTION_END_BPF // 15
|
||||
__SEG6_LOCAL_ACTION_MAX
|
||||
)
|
||||
const (
|
||||
@ -71,6 +73,8 @@ func SEG6LocalActionString(action int) string {
|
||||
return "End.AS"
|
||||
case SEG6_LOCAL_ACTION_END_AM:
|
||||
return "End.AM"
|
||||
case SEG6_LOCAL_ACTION_END_BPF:
|
||||
return "End.BPF"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
1
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
1
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
@ -46,6 +46,7 @@ const (
|
||||
// socket diags related
|
||||
const (
|
||||
SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */
|
||||
SOCK_DESTROY = 21
|
||||
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
|
||||
)
|
||||
|
||||
|
544
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
544
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
@ -1,8 +1,13 @@
|
||||
package nl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// LinkLayer
|
||||
@ -42,7 +47,14 @@ const (
|
||||
TCA_FCNT
|
||||
TCA_STATS2
|
||||
TCA_STAB
|
||||
TCA_MAX = TCA_STAB
|
||||
TCA_PAD
|
||||
TCA_DUMP_INVISIBLE
|
||||
TCA_CHAIN
|
||||
TCA_HW_OFFLOAD
|
||||
TCA_INGRESS_BLOCK
|
||||
TCA_EGRESS_BLOCK
|
||||
TCA_DUMP_FLAGS
|
||||
TCA_MAX = TCA_DUMP_FLAGS
|
||||
)
|
||||
|
||||
const (
|
||||
@ -56,6 +68,12 @@ const (
|
||||
TCA_ACT_OPTIONS
|
||||
TCA_ACT_INDEX
|
||||
TCA_ACT_STATS
|
||||
TCA_ACT_PAD
|
||||
TCA_ACT_COOKIE
|
||||
TCA_ACT_FLAGS
|
||||
TCA_ACT_HW_STATS
|
||||
TCA_ACT_USED_HW_STATS
|
||||
TCA_ACT_IN_HW_COUNT
|
||||
TCA_ACT_MAX
|
||||
)
|
||||
|
||||
@ -71,7 +89,11 @@ const (
|
||||
TCA_STATS_RATE_EST
|
||||
TCA_STATS_QUEUE
|
||||
TCA_STATS_APP
|
||||
TCA_STATS_MAX = TCA_STATS_APP
|
||||
TCA_STATS_RATE_EST64
|
||||
TCA_STATS_PAD
|
||||
TCA_STATS_BASIC_HW
|
||||
TCA_STATS_PKT64
|
||||
TCA_STATS_MAX = TCA_STATS_PKT64
|
||||
)
|
||||
|
||||
const (
|
||||
@ -83,12 +105,13 @@ const (
|
||||
SizeofTcNetemCorr = 0x0c
|
||||
SizeofTcNetemReorder = 0x08
|
||||
SizeofTcNetemCorrupt = 0x08
|
||||
SizeOfTcNetemRate = 0x10
|
||||
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
|
||||
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
|
||||
SizeofTcHtbGlob = 0x14
|
||||
SizeofTcU32Key = 0x10
|
||||
SizeofTcU32Sel = 0x10 // without keys
|
||||
SizeofTcGen = 0x14
|
||||
SizeofTcGen = 0x16
|
||||
SizeofTcConnmark = SizeofTcGen + 0x04
|
||||
SizeofTcCsum = SizeofTcGen + 0x04
|
||||
SizeofTcMirred = SizeofTcGen + 0x08
|
||||
@ -98,6 +121,7 @@ const (
|
||||
SizeofTcSfqQopt = 0x0b
|
||||
SizeofTcSfqRedStats = 0x18
|
||||
SizeofTcSfqQoptV1 = SizeofTcSfqQopt + SizeofTcSfqRedStats + 0x1c
|
||||
SizeofUint32Bitfield = 0x8
|
||||
)
|
||||
|
||||
// struct tcmsg {
|
||||
@ -131,6 +155,18 @@ func (x *TcMsg) Serialize() []byte {
|
||||
return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
type Tcf struct {
|
||||
Install uint64
|
||||
LastUse uint64
|
||||
Expires uint64
|
||||
FirstUse uint64
|
||||
}
|
||||
|
||||
func DeserializeTcf(b []byte) *Tcf {
|
||||
const size = int(unsafe.Sizeof(Tcf{}))
|
||||
return (*Tcf)(unsafe.Pointer(&b[0:size][0]))
|
||||
}
|
||||
|
||||
// struct tcamsg {
|
||||
// unsigned char tca_family;
|
||||
// unsigned char tca__pad1;
|
||||
@ -337,6 +373,26 @@ func (x *TcNetemCorrupt) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// TcNetemRate is a struct that represents the rate of a netem qdisc
|
||||
type TcNetemRate struct {
|
||||
Rate uint32
|
||||
PacketOverhead int32
|
||||
CellSize uint32
|
||||
CellOverhead int32
|
||||
}
|
||||
|
||||
func (msg *TcNetemRate) Len() int {
|
||||
return SizeofTcRateSpec
|
||||
}
|
||||
|
||||
func DeserializeTcNetemRate(b []byte) *TcNetemRate {
|
||||
return (*TcNetemRate)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0]))
|
||||
}
|
||||
|
||||
func (msg *TcNetemRate) Serialize() []byte {
|
||||
return (*(*[SizeOfTcNetemRate]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct tc_tbf_qopt {
|
||||
// struct tc_ratespec rate;
|
||||
// struct tc_ratespec peakrate;
|
||||
@ -804,7 +860,8 @@ const (
|
||||
TCA_SKBEDIT_MARK
|
||||
TCA_SKBEDIT_PAD
|
||||
TCA_SKBEDIT_PTYPE
|
||||
TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
|
||||
TCA_SKBEDIT_MASK
|
||||
TCA_SKBEDIT_MAX
|
||||
)
|
||||
|
||||
type TcSkbEdit struct {
|
||||
@ -891,6 +948,10 @@ const (
|
||||
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
|
||||
TCA_FQ_CE_THRESHOLD // DCTCP-like CE-marking threshold
|
||||
TCA_FQ_TIMER_SLACK // timer slack
|
||||
TCA_FQ_HORIZON // time horizon in us
|
||||
TCA_FQ_HORIZON_DROP // drop packets beyond horizon, or cap their EDT
|
||||
)
|
||||
|
||||
const (
|
||||
@ -1018,6 +1079,9 @@ const (
|
||||
__TCA_FLOWER_MAX
|
||||
)
|
||||
|
||||
const TCA_CLS_FLAGS_SKIP_HW = 1 << 0 /* don't offload filter to HW */
|
||||
const TCA_CLS_FLAGS_SKIP_SW = 1 << 1 /* don't use filter in SW */
|
||||
|
||||
// struct tc_sfq_qopt {
|
||||
// unsigned quantum; /* Bytes per round allocated to flow */
|
||||
// int perturb_period; /* Period of hash perturbation */
|
||||
@ -1046,14 +1110,14 @@ func (x *TcSfqQopt) Serialize() []byte {
|
||||
return (*(*[SizeofTcSfqQopt]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_sfqred_stats {
|
||||
// __u32 prob_drop; /* Early drops, below max threshold */
|
||||
// __u32 forced_drop; /* Early drops, after max threshold */
|
||||
// __u32 prob_mark; /* Marked packets, below max threshold */
|
||||
// __u32 forced_mark; /* Marked packets, after max threshold */
|
||||
// __u32 prob_mark_head; /* Marked packets, below max threshold */
|
||||
// __u32 forced_mark_head;/* Marked packets, after max threshold */
|
||||
// };
|
||||
// struct tc_sfqred_stats {
|
||||
// __u32 prob_drop; /* Early drops, below max threshold */
|
||||
// __u32 forced_drop; /* Early drops, after max threshold */
|
||||
// __u32 prob_mark; /* Marked packets, below max threshold */
|
||||
// __u32 forced_mark; /* Marked packets, after max threshold */
|
||||
// __u32 prob_mark_head; /* Marked packets, below max threshold */
|
||||
// __u32 forced_mark_head;/* Marked packets, after max threshold */
|
||||
// };
|
||||
type TcSfqRedStats struct {
|
||||
ProbDrop uint32
|
||||
ForcedDrop uint32
|
||||
@ -1075,22 +1139,26 @@ func (x *TcSfqRedStats) Serialize() []byte {
|
||||
return (*(*[SizeofTcSfqRedStats]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_sfq_qopt_v1 {
|
||||
// struct tc_sfq_qopt v0;
|
||||
// unsigned int depth; /* max number of packets per flow */
|
||||
// unsigned int headdrop;
|
||||
// struct tc_sfq_qopt_v1 {
|
||||
// struct tc_sfq_qopt v0;
|
||||
// unsigned int depth; /* max number of packets per flow */
|
||||
// unsigned int headdrop;
|
||||
//
|
||||
// /* SFQRED parameters */
|
||||
// __u32 limit; /* HARD maximal flow queue length (bytes) */
|
||||
// __u32 qth_min; /* Min average length threshold (bytes) */
|
||||
// __u32 qth_max; /* Max average length threshold (bytes) */
|
||||
// unsigned char Wlog; /* log(W) */
|
||||
// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
|
||||
// unsigned char Scell_log; /* cell size for idle damping */
|
||||
// unsigned char flags;
|
||||
// __u32 max_P; /* probability, high resolution */
|
||||
//
|
||||
// __u32 limit; /* HARD maximal flow queue length (bytes) */
|
||||
// __u32 qth_min; /* Min average length threshold (bytes) */
|
||||
// __u32 qth_max; /* Max average length threshold (bytes) */
|
||||
// unsigned char Wlog; /* log(W) */
|
||||
// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
|
||||
// unsigned char Scell_log; /* cell size for idle damping */
|
||||
// unsigned char flags;
|
||||
// __u32 max_P; /* probability, high resolution */
|
||||
//
|
||||
// /* SFQRED stats */
|
||||
// struct tc_sfqred_stats stats;
|
||||
// };
|
||||
//
|
||||
// struct tc_sfqred_stats stats;
|
||||
// };
|
||||
type TcSfqQoptV1 struct {
|
||||
TcSfqQopt
|
||||
Depth uint32
|
||||
@ -1117,3 +1185,427 @@ func DeserializeTcSfqQoptV1(b []byte) *TcSfqQoptV1 {
|
||||
func (x *TcSfqQoptV1) Serialize() []byte {
|
||||
return (*(*[SizeofTcSfqQoptV1]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// IPProto represents Flower ip_proto attribute
|
||||
type IPProto uint8
|
||||
|
||||
const (
|
||||
IPPROTO_TCP IPProto = unix.IPPROTO_TCP
|
||||
IPPROTO_UDP IPProto = unix.IPPROTO_UDP
|
||||
IPPROTO_SCTP IPProto = unix.IPPROTO_SCTP
|
||||
IPPROTO_ICMP IPProto = unix.IPPROTO_ICMP
|
||||
IPPROTO_ICMPV6 IPProto = unix.IPPROTO_ICMPV6
|
||||
)
|
||||
|
||||
func (i IPProto) Serialize() []byte {
|
||||
arr := make([]byte, 1)
|
||||
arr[0] = byte(i)
|
||||
return arr
|
||||
}
|
||||
|
||||
func (i IPProto) String() string {
|
||||
switch i {
|
||||
case IPPROTO_TCP:
|
||||
return "tcp"
|
||||
case IPPROTO_UDP:
|
||||
return "udp"
|
||||
case IPPROTO_SCTP:
|
||||
return "sctp"
|
||||
case IPPROTO_ICMP:
|
||||
return "icmp"
|
||||
case IPPROTO_ICMPV6:
|
||||
return "icmpv6"
|
||||
}
|
||||
return fmt.Sprintf("%d", i)
|
||||
}
|
||||
|
||||
const (
|
||||
MaxOffs = 128
|
||||
SizeOfPeditSel = 24
|
||||
SizeOfPeditKey = 24
|
||||
|
||||
TCA_PEDIT_KEY_EX_HTYPE = 1
|
||||
TCA_PEDIT_KEY_EX_CMD = 2
|
||||
)
|
||||
|
||||
const (
|
||||
TCA_PEDIT_UNSPEC = iota
|
||||
TCA_PEDIT_TM
|
||||
TCA_PEDIT_PARMS
|
||||
TCA_PEDIT_PAD
|
||||
TCA_PEDIT_PARMS_EX
|
||||
TCA_PEDIT_KEYS_EX
|
||||
TCA_PEDIT_KEY_EX
|
||||
)
|
||||
|
||||
// /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It
|
||||
// * means no specific header type - offset is relative to the network layer
|
||||
// */
|
||||
type PeditHeaderType uint16
|
||||
|
||||
const (
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = iota
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
__PEDIT_HDR_TYPE_MAX
|
||||
)
|
||||
|
||||
type PeditCmd uint16
|
||||
|
||||
const (
|
||||
TCA_PEDIT_KEY_EX_CMD_SET = 0
|
||||
TCA_PEDIT_KEY_EX_CMD_ADD = 1
|
||||
)
|
||||
|
||||
type TcPeditSel struct {
|
||||
TcGen
|
||||
NKeys uint8
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func DeserializeTcPeditKey(b []byte) *TcPeditKey {
|
||||
return (*TcPeditKey)(unsafe.Pointer(&b[0:SizeOfPeditKey][0]))
|
||||
}
|
||||
|
||||
func DeserializeTcPedit(b []byte) (*TcPeditSel, []TcPeditKey) {
|
||||
x := &TcPeditSel{}
|
||||
copy((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(x)))[:SizeOfPeditSel], b)
|
||||
|
||||
var keys []TcPeditKey
|
||||
|
||||
next := SizeOfPeditKey
|
||||
var i uint8
|
||||
for i = 0; i < x.NKeys; i++ {
|
||||
keys = append(keys, *DeserializeTcPeditKey(b[next:]))
|
||||
next += SizeOfPeditKey
|
||||
}
|
||||
|
||||
return x, keys
|
||||
}
|
||||
|
||||
type TcPeditKey struct {
|
||||
Mask uint32
|
||||
Val uint32
|
||||
Off uint32
|
||||
At uint32
|
||||
OffMask uint32
|
||||
Shift uint32
|
||||
}
|
||||
|
||||
type TcPeditKeyEx struct {
|
||||
HeaderType PeditHeaderType
|
||||
Cmd PeditCmd
|
||||
}
|
||||
|
||||
type TcPedit struct {
|
||||
Sel TcPeditSel
|
||||
Keys []TcPeditKey
|
||||
KeysEx []TcPeditKeyEx
|
||||
Extend uint8
|
||||
}
|
||||
|
||||
func (p *TcPedit) Encode(parent *RtAttr) {
|
||||
parent.AddRtAttr(TCA_ACT_KIND, ZeroTerminated("pedit"))
|
||||
actOpts := parent.AddRtAttr(TCA_ACT_OPTIONS, nil)
|
||||
|
||||
bbuf := bytes.NewBuffer(make([]byte, 0, int(unsafe.Sizeof(p.Sel)+unsafe.Sizeof(p.Keys))))
|
||||
|
||||
bbuf.Write((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(&p.Sel)))[:])
|
||||
|
||||
for i := uint8(0); i < p.Sel.NKeys; i++ {
|
||||
bbuf.Write((*(*[SizeOfPeditKey]byte)(unsafe.Pointer(&p.Keys[i])))[:])
|
||||
}
|
||||
actOpts.AddRtAttr(TCA_PEDIT_PARMS_EX, bbuf.Bytes())
|
||||
|
||||
exAttrs := actOpts.AddRtAttr(int(TCA_PEDIT_KEYS_EX|NLA_F_NESTED), nil)
|
||||
for i := uint8(0); i < p.Sel.NKeys; i++ {
|
||||
keyAttr := exAttrs.AddRtAttr(int(TCA_PEDIT_KEY_EX|NLA_F_NESTED), nil)
|
||||
|
||||
htypeBuf := make([]byte, 2)
|
||||
cmdBuf := make([]byte, 2)
|
||||
|
||||
NativeEndian().PutUint16(htypeBuf, uint16(p.KeysEx[i].HeaderType))
|
||||
NativeEndian().PutUint16(cmdBuf, uint16(p.KeysEx[i].Cmd))
|
||||
|
||||
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_HTYPE, htypeBuf)
|
||||
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_CMD, cmdBuf)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetEthDst(mac net.HardwareAddr) {
|
||||
u32 := NativeEndian().Uint32(mac)
|
||||
u16 := NativeEndian().Uint16(mac[4:])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = uint32(u16)
|
||||
tKey.Mask = 0xffff0000
|
||||
tKey.Off = 4
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetEthSrc(mac net.HardwareAddr) {
|
||||
u16 := NativeEndian().Uint16(mac)
|
||||
u32 := NativeEndian().Uint32(mac[2:])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = uint32(u16) << 16
|
||||
tKey.Mask = 0x0000ffff
|
||||
tKey.Off = 4
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Mask = 0
|
||||
tKey.Off = 8
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv6Src(ip6 net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip6[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 8
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[4:8])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 12
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[8:12])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 16
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[12:16])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 20
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetDstIP(ip net.IP) {
|
||||
if ip.To4() != nil {
|
||||
p.SetIPv4Dst(ip)
|
||||
} else {
|
||||
p.SetIPv6Dst(ip)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetSrcIP(ip net.IP) {
|
||||
if ip.To4() != nil {
|
||||
p.SetIPv4Src(ip)
|
||||
} else {
|
||||
p.SetIPv6Src(ip)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv6Dst(ip6 net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip6[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 24
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[4:8])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 28
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[8:12])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 32
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[12:16])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 36
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv4Src(ip net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 12
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv4Dst(ip net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 16
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
// SetDstPort only tcp and udp are supported to set port
|
||||
func (p *TcPedit) SetDstPort(dstPort uint16, protocol uint8) {
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
switch protocol {
|
||||
case unix.IPPROTO_TCP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
case unix.IPPROTO_UDP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
tKey.Val = uint32(Swap16(dstPort)) << 16
|
||||
tKey.Mask = 0x0000ffff
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
// SetSrcPort only tcp and udp are supported to set port
|
||||
func (p *TcPedit) SetSrcPort(srcPort uint16, protocol uint8) {
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
switch protocol {
|
||||
case unix.IPPROTO_TCP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
case unix.IPPROTO_UDP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
tKey.Val = uint32(Swap16(srcPort))
|
||||
tKey.Mask = 0xffff0000
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
41
vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go
generated
vendored
Normal file
41
vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package nl
|
||||
|
||||
const (
|
||||
VDPA_GENL_NAME = "vdpa"
|
||||
VDPA_GENL_VERSION = 0x1
|
||||
)
|
||||
|
||||
const (
|
||||
VDPA_CMD_UNSPEC = iota
|
||||
VDPA_CMD_MGMTDEV_NEW
|
||||
VDPA_CMD_MGMTDEV_GET /* can dump */
|
||||
VDPA_CMD_DEV_NEW
|
||||
VDPA_CMD_DEV_DEL
|
||||
VDPA_CMD_DEV_GET /* can dump */
|
||||
VDPA_CMD_DEV_CONFIG_GET /* can dump */
|
||||
VDPA_CMD_DEV_VSTATS_GET
|
||||
)
|
||||
|
||||
const (
|
||||
VDPA_ATTR_UNSPEC = iota
|
||||
VDPA_ATTR_MGMTDEV_BUS_NAME
|
||||
VDPA_ATTR_MGMTDEV_DEV_NAME
|
||||
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES
|
||||
VDPA_ATTR_DEV_NAME
|
||||
VDPA_ATTR_DEV_ID
|
||||
VDPA_ATTR_DEV_VENDOR_ID
|
||||
VDPA_ATTR_DEV_MAX_VQS
|
||||
VDPA_ATTR_DEV_MAX_VQ_SIZE
|
||||
VDPA_ATTR_DEV_MIN_VQ_SIZE
|
||||
VDPA_ATTR_DEV_NET_CFG_MACADDR
|
||||
VDPA_ATTR_DEV_NET_STATUS
|
||||
VDPA_ATTR_DEV_NET_CFG_MAX_VQP
|
||||
VDPA_ATTR_DEV_NET_CFG_MTU
|
||||
VDPA_ATTR_DEV_NEGOTIATED_FEATURES
|
||||
VDPA_ATTR_DEV_MGMTDEV_MAX_VQS
|
||||
VDPA_ATTR_DEV_SUPPORTED_FEATURES
|
||||
VDPA_ATTR_DEV_QUEUE_INDEX
|
||||
VDPA_ATTR_DEV_VENDOR_ATTR_NAME
|
||||
VDPA_ATTR_DEV_VENDOR_ATTR_VALUE
|
||||
VDPA_ATTR_DEV_FEATURES
|
||||
)
|
10
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
10
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
@ -131,7 +131,15 @@ func (x *XfrmAddress) ToIP() net.IP {
|
||||
return ip
|
||||
}
|
||||
|
||||
func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet {
|
||||
// family is only used when x and prefixlen are both 0
|
||||
func (x *XfrmAddress) ToIPNet(prefixlen uint8, family uint16) *net.IPNet {
|
||||
empty := [SizeofXfrmAddress]byte{}
|
||||
if bytes.Equal(x[:], empty[:]) && prefixlen == 0 {
|
||||
if family == FAMILY_V6 {
|
||||
return &net.IPNet{IP: net.ParseIP("::"), Mask: net.CIDRMask(int(prefixlen), 128)}
|
||||
}
|
||||
return &net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(int(prefixlen), 32)}
|
||||
}
|
||||
ip := x.ToIP()
|
||||
if GetIPFamily(ip) == FAMILY_V4 {
|
||||
return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)}
|
||||
|
27
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
generated
vendored
27
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
generated
vendored
@ -15,6 +15,7 @@ const (
|
||||
SizeofXfrmEncapTmpl = 0x18
|
||||
SizeofXfrmUsersaFlush = 0x1
|
||||
SizeofXfrmReplayStateEsn = 0x18
|
||||
SizeofXfrmReplayState = 0x0c
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,6 +29,11 @@ const (
|
||||
XFRM_STATE_ESN = 128
|
||||
)
|
||||
|
||||
const (
|
||||
XFRM_SA_XFLAG_DONT_ENCAP_DSCP = 1
|
||||
XFRM_SA_XFLAG_OSEQ_MAY_WRAP = 2
|
||||
)
|
||||
|
||||
// struct xfrm_usersa_id {
|
||||
// xfrm_address_t daddr;
|
||||
// __be32 spi;
|
||||
@ -103,6 +109,7 @@ func (msg *XfrmStats) Serialize() []byte {
|
||||
// };
|
||||
//
|
||||
// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
|
||||
// #define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
|
||||
//
|
||||
|
||||
type XfrmUsersaInfo struct {
|
||||
@ -332,3 +339,23 @@ func (msg *XfrmReplayStateEsn) Serialize() []byte {
|
||||
// We deliberately do not pass Bmp, as it gets set by the kernel.
|
||||
return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct xfrm_replay_state {
|
||||
// __u32 oseq;
|
||||
// __u32 seq;
|
||||
// __u32 bitmap;
|
||||
// };
|
||||
|
||||
type XfrmReplayState struct {
|
||||
OSeq uint32
|
||||
Seq uint32
|
||||
BitMap uint32
|
||||
}
|
||||
|
||||
func DeserializeXfrmReplayState(b []byte) *XfrmReplayState {
|
||||
return (*XfrmReplayState)(unsafe.Pointer(&b[0:SizeofXfrmReplayState][0]))
|
||||
}
|
||||
|
||||
func (msg *XfrmReplayState) Serialize() []byte {
|
||||
return (*(*[SizeofXfrmReplayState]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/proc_event_linux.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/proc_event_linux.go
generated
vendored
@ -63,15 +63,6 @@ type ExitProcEvent struct {
|
||||
ParentTgid uint32
|
||||
}
|
||||
|
||||
type ExitProcEvent2 struct {
|
||||
ProcessPid uint32
|
||||
ProcessTgid uint32
|
||||
ExitCode uint32
|
||||
ExitSignal uint32
|
||||
ParentPid uint32
|
||||
ParentTgid uint32
|
||||
}
|
||||
|
||||
func (e *ExitProcEvent) Pid() uint32 {
|
||||
return e.ProcessPid
|
||||
}
|
||||
|
24
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
24
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
@ -6,14 +6,16 @@ import (
|
||||
|
||||
// Protinfo represents bridge flags from netlink.
|
||||
type Protinfo struct {
|
||||
Hairpin bool
|
||||
Guard bool
|
||||
FastLeave bool
|
||||
RootBlock bool
|
||||
Learning bool
|
||||
Flood bool
|
||||
ProxyArp bool
|
||||
ProxyArpWiFi bool
|
||||
Hairpin bool
|
||||
Guard bool
|
||||
FastLeave bool
|
||||
RootBlock bool
|
||||
Learning bool
|
||||
Flood bool
|
||||
ProxyArp bool
|
||||
ProxyArpWiFi bool
|
||||
Isolated bool
|
||||
NeighSuppress bool
|
||||
}
|
||||
|
||||
// String returns a list of enabled flags
|
||||
@ -47,6 +49,12 @@ func (prot *Protinfo) String() string {
|
||||
if prot.ProxyArpWiFi {
|
||||
boolStrings = append(boolStrings, "ProxyArpWiFi")
|
||||
}
|
||||
if prot.Isolated {
|
||||
boolStrings = append(boolStrings, "Isolated")
|
||||
}
|
||||
if prot.NeighSuppress {
|
||||
boolStrings = append(boolStrings, "NeighSuppress")
|
||||
}
|
||||
return strings.Join(boolStrings, " ")
|
||||
}
|
||||
|
||||
|
4
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
@ -68,6 +68,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
|
||||
pi.ProxyArp = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_PROXYARP_WIFI:
|
||||
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_ISOLATED:
|
||||
pi.Isolated = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_NEIGH_SUPPRESS:
|
||||
pi.NeighSuppress = byteToBool(info.Value[0])
|
||||
}
|
||||
}
|
||||
return
|
||||
|
52
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
52
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
@ -17,19 +17,29 @@ const (
|
||||
HANDLE_MIN_EGRESS = 0xFFFFFFF3
|
||||
)
|
||||
|
||||
const (
|
||||
HORIZON_DROP_POLICY_CAP = 0
|
||||
HORIZON_DROP_POLICY_DROP = 1
|
||||
HORIZON_DROP_POLICY_DEFAULT = 255
|
||||
)
|
||||
|
||||
type Qdisc interface {
|
||||
Attrs() *QdiscAttrs
|
||||
Type() string
|
||||
}
|
||||
|
||||
type QdiscStatistics ClassStatistics
|
||||
|
||||
// QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link,
|
||||
// has a handle, a parent and a refcnt. The root qdisc of a device should
|
||||
// have parent == HANDLE_ROOT.
|
||||
type QdiscAttrs struct {
|
||||
LinkIndex int
|
||||
Handle uint32
|
||||
Parent uint32
|
||||
Refcnt uint32 // read only
|
||||
LinkIndex int
|
||||
Handle uint32
|
||||
Parent uint32
|
||||
Refcnt uint32 // read only
|
||||
IngressBlock *uint32
|
||||
Statistics *QdiscStatistics
|
||||
}
|
||||
|
||||
func (q QdiscAttrs) String() string {
|
||||
@ -113,6 +123,7 @@ type Htb struct {
|
||||
Defcls uint32
|
||||
Debug uint32
|
||||
DirectPkts uint32
|
||||
DirectQlen *uint32
|
||||
}
|
||||
|
||||
func NewHtb(attrs QdiscAttrs) *Htb {
|
||||
@ -123,6 +134,7 @@ func NewHtb(attrs QdiscAttrs) *Htb {
|
||||
Rate2Quantum: 10,
|
||||
Debug: 0,
|
||||
DirectPkts: 0,
|
||||
DirectQlen: nil,
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,6 +162,7 @@ type NetemQdiscAttrs struct {
|
||||
ReorderCorr float32 // in %
|
||||
CorruptProb float32 // in %
|
||||
CorruptCorr float32 // in %
|
||||
Rate64 uint64
|
||||
}
|
||||
|
||||
func (q NetemQdiscAttrs) String() string {
|
||||
@ -174,6 +187,7 @@ type Netem struct {
|
||||
ReorderCorr uint32
|
||||
CorruptProb uint32
|
||||
CorruptCorr uint32
|
||||
Rate64 uint64
|
||||
}
|
||||
|
||||
func (netem *Netem) String() string {
|
||||
@ -210,6 +224,19 @@ func (qdisc *Tbf) Type() string {
|
||||
return "tbf"
|
||||
}
|
||||
|
||||
// Clsact is a qdisc for adding filters
|
||||
type Clsact struct {
|
||||
QdiscAttrs
|
||||
}
|
||||
|
||||
func (qdisc *Clsact) Attrs() *QdiscAttrs {
|
||||
return &qdisc.QdiscAttrs
|
||||
}
|
||||
|
||||
func (qdisc *Clsact) Type() string {
|
||||
return "clsact"
|
||||
}
|
||||
|
||||
// Ingress is a qdisc for adding ingress filters
|
||||
type Ingress struct {
|
||||
QdiscAttrs
|
||||
@ -278,22 +305,25 @@ type Fq struct {
|
||||
FlowDefaultRate uint32
|
||||
FlowMaxRate uint32
|
||||
// called BucketsLog under the hood
|
||||
Buckets uint32
|
||||
FlowRefillDelay uint32
|
||||
LowRateThreshold uint32
|
||||
Buckets uint32
|
||||
FlowRefillDelay uint32
|
||||
LowRateThreshold uint32
|
||||
Horizon uint32
|
||||
HorizonDropPolicy uint8
|
||||
}
|
||||
|
||||
func (fq *Fq) String() string {
|
||||
return fmt.Sprintf(
|
||||
"{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}",
|
||||
fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold,
|
||||
"{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v, Horizon: %v, HorizonDropPolicy: %v}",
|
||||
fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, fq.Horizon, fq.HorizonDropPolicy,
|
||||
)
|
||||
}
|
||||
|
||||
func NewFq(attrs QdiscAttrs) *Fq {
|
||||
return &Fq{
|
||||
QdiscAttrs: attrs,
|
||||
Pacing: 1,
|
||||
QdiscAttrs: attrs,
|
||||
Pacing: 1,
|
||||
HorizonDropPolicy: HORIZON_DROP_POLICY_DEFAULT,
|
||||
}
|
||||
}
|
||||
|
||||
|
82
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
82
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
@ -17,6 +18,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
var lossCorr, delayCorr, duplicateCorr uint32
|
||||
var reorderProb, reorderCorr uint32
|
||||
var corruptProb, corruptCorr uint32
|
||||
var rate64 uint64
|
||||
|
||||
latency := nattrs.Latency
|
||||
loss := Percentage2u32(nattrs.Loss)
|
||||
@ -57,6 +59,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
|
||||
corruptProb = Percentage2u32(nattrs.CorruptProb)
|
||||
corruptCorr = Percentage2u32(nattrs.CorruptCorr)
|
||||
rate64 = nattrs.Rate64
|
||||
|
||||
return &Netem{
|
||||
QdiscAttrs: attrs,
|
||||
@ -73,6 +76,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
ReorderCorr: reorderCorr,
|
||||
CorruptProb: corruptProb,
|
||||
CorruptCorr: corruptCorr,
|
||||
Rate64: rate64,
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,6 +163,9 @@ func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
||||
func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
||||
if qdisc.Attrs().IngressBlock != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_INGRESS_BLOCK, nl.Uint32Attr(*qdisc.Attrs().IngressBlock)))
|
||||
}
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
|
||||
@ -194,7 +201,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
opt.Debug = qdisc.Debug
|
||||
opt.DirectPkts = qdisc.DirectPkts
|
||||
options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize())
|
||||
// options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
|
||||
if qdisc.DirectQlen != nil {
|
||||
options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, nl.Uint32Attr(*qdisc.DirectQlen))
|
||||
}
|
||||
case *Hfsc:
|
||||
opt := nl.TcHfscOpt{}
|
||||
opt.Defcls = qdisc.Defcls
|
||||
@ -231,6 +240,19 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if reorder.Probability > 0 {
|
||||
options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
|
||||
}
|
||||
// Rate
|
||||
if qdisc.Rate64 > 0 {
|
||||
rate := nl.TcNetemRate{}
|
||||
if qdisc.Rate64 >= uint64(1<<32) {
|
||||
options.AddRtAttr(nl.TCA_NETEM_RATE64, nl.Uint64Attr(qdisc.Rate64))
|
||||
rate.Rate = ^uint32(0)
|
||||
} else {
|
||||
rate.Rate = uint32(qdisc.Rate64)
|
||||
}
|
||||
options.AddRtAttr(nl.TCA_NETEM_RATE, rate.Serialize())
|
||||
}
|
||||
case *Clsact:
|
||||
options = nil
|
||||
case *Ingress:
|
||||
// ingress filters must use the proper handle
|
||||
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
||||
@ -265,6 +287,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if qdisc.Buckets > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
|
||||
}
|
||||
if qdisc.PacketLimit > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_PLIMIT, nl.Uint32Attr((uint32(qdisc.PacketLimit))))
|
||||
}
|
||||
if qdisc.LowRateThreshold > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
|
||||
}
|
||||
@ -286,6 +311,12 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if qdisc.FlowDefaultRate > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
|
||||
}
|
||||
if qdisc.Horizon > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_HORIZON, nl.Uint32Attr(qdisc.Horizon))
|
||||
}
|
||||
if qdisc.HorizonDropPolicy != HORIZON_DROP_POLICY_DEFAULT {
|
||||
options.AddRtAttr(nl.TCA_FQ_HORIZON_DROP, nl.Uint8Attr(qdisc.HorizonDropPolicy))
|
||||
}
|
||||
case *Sfq:
|
||||
opt := nl.TcSfqQoptV1{}
|
||||
opt.TcSfqQopt.Quantum = qdisc.Quantum
|
||||
@ -380,6 +411,8 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
||||
qdisc = &Netem{}
|
||||
case "sfq":
|
||||
qdisc = &Sfq{}
|
||||
case "clsact":
|
||||
qdisc = &Clsact{}
|
||||
default:
|
||||
qdisc = &GenericQdisc{QdiscType: qdiscType}
|
||||
}
|
||||
@ -442,6 +475,22 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
||||
|
||||
// no options for ingress
|
||||
}
|
||||
case nl.TCA_INGRESS_BLOCK:
|
||||
ingressBlock := new(uint32)
|
||||
*ingressBlock = native.Uint32(attr.Value)
|
||||
base.IngressBlock = ingressBlock
|
||||
case nl.TCA_STATS:
|
||||
s, err := parseTcStats(attr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base.Statistics = (*QdiscStatistics)(s)
|
||||
case nl.TCA_STATS2:
|
||||
s, err := parseTcStats2(attr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base.Statistics = (*QdiscStatistics)(s)
|
||||
}
|
||||
}
|
||||
*qdisc.Attrs() = base
|
||||
@ -479,8 +528,8 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||
htb.Debug = opt.Debug
|
||||
htb.DirectPkts = opt.DirectPkts
|
||||
case nl.TCA_HTB_DIRECT_QLEN:
|
||||
// TODO
|
||||
//htb.DirectQlen = native.uint32(datum.Value)
|
||||
directQlen := native.Uint32(datum.Value)
|
||||
htb.DirectQlen = &directQlen
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -546,6 +595,11 @@ func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||
fq.FlowMaxRate = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_FLOW_DEFAULT_RATE:
|
||||
fq.FlowDefaultRate = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_HORIZON:
|
||||
fq.Horizon = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_HORIZON_DROP:
|
||||
fq.HorizonDropPolicy = datum.Value[0]
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -564,6 +618,8 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rate *nl.TcNetemRate
|
||||
var rate64 uint64
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.TCA_NETEM_CORR:
|
||||
@ -579,8 +635,19 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||
opt := nl.DeserializeTcNetemReorder(datum.Value)
|
||||
netem.ReorderProb = opt.Probability
|
||||
netem.ReorderCorr = opt.Correlation
|
||||
case nl.TCA_NETEM_RATE:
|
||||
rate = nl.DeserializeTcNetemRate(datum.Value)
|
||||
case nl.TCA_NETEM_RATE64:
|
||||
rate64 = native.Uint64(datum.Value)
|
||||
}
|
||||
}
|
||||
if rate != nil {
|
||||
netem.Rate64 = uint64(rate.Rate)
|
||||
if rate64 > 0 {
|
||||
netem.Rate64 = rate64
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -624,6 +691,9 @@ var (
|
||||
tickInUsec float64
|
||||
clockFactor float64
|
||||
hz float64
|
||||
|
||||
// Without this, the go race detector may report races.
|
||||
initClockMutex sync.Mutex
|
||||
)
|
||||
|
||||
func initClock() {
|
||||
@ -658,6 +728,8 @@ func initClock() {
|
||||
}
|
||||
|
||||
func TickInUsec() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if tickInUsec == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
@ -665,6 +737,8 @@ func TickInUsec() float64 {
|
||||
}
|
||||
|
||||
func ClockFactor() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if clockFactor == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
@ -672,6 +746,8 @@ func ClockFactor() float64 {
|
||||
}
|
||||
|
||||
func Hz() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if hz == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
@ -154,8 +154,15 @@ type flagString struct {
|
||||
}
|
||||
|
||||
// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
|
||||
|
||||
// NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set:
|
||||
// - unix.NLM_F_REPLACE - Replace existing matching config object with this request
|
||||
// - unix.NLM_F_EXCL - Don't replace the config object if it already exists
|
||||
// - unix.NLM_F_CREATE - Create config object if it doesn't already exist
|
||||
// - unix.NLM_F_APPEND - Add to the end of the object list
|
||||
type RouteUpdate struct {
|
||||
Type uint16
|
||||
Type uint16
|
||||
NlFlags uint16
|
||||
Route
|
||||
}
|
||||
|
||||
|
428
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
428
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
@ -41,7 +41,6 @@ func (s Scope) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const (
|
||||
FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK
|
||||
FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
|
||||
@ -274,6 +273,16 @@ type SEG6LocalEncap struct {
|
||||
In6Addr net.IP
|
||||
Iif int
|
||||
Oif int
|
||||
bpf bpfObj
|
||||
}
|
||||
|
||||
func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error {
|
||||
if progFd <= 0 {
|
||||
return fmt.Errorf("seg6local bpf SetProg: invalid fd")
|
||||
}
|
||||
e.bpf.progFd = progFd
|
||||
e.bpf.progName = progName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *SEG6LocalEncap) Type() int {
|
||||
@ -307,6 +316,22 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
|
||||
case nl.SEG6_LOCAL_OIF:
|
||||
e.Oif = int(native.Uint32(attr.Value[0:4]))
|
||||
e.Flags[nl.SEG6_LOCAL_OIF] = true
|
||||
case nl.SEG6_LOCAL_BPF:
|
||||
var bpfAttrs []syscall.NetlinkRouteAttr
|
||||
bpfAttrs, err = nl.ParseRouteAttr(attr.Value)
|
||||
bpfobj := bpfObj{}
|
||||
for _, bpfAttr := range bpfAttrs {
|
||||
switch bpfAttr.Attr.Type {
|
||||
case nl.LWT_BPF_PROG_FD:
|
||||
bpfobj.progFd = int(native.Uint32(bpfAttr.Value))
|
||||
case nl.LWT_BPF_PROG_NAME:
|
||||
bpfobj.progName = string(bpfAttr.Value)
|
||||
default:
|
||||
err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr)
|
||||
}
|
||||
}
|
||||
e.bpf = bpfobj
|
||||
e.Flags[nl.SEG6_LOCAL_BPF] = true
|
||||
}
|
||||
}
|
||||
return err
|
||||
@ -368,6 +393,16 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
|
||||
native.PutUint32(attr[4:], uint32(e.Oif))
|
||||
res = append(res, attr...)
|
||||
}
|
||||
if e.Flags[nl.SEG6_LOCAL_BPF] {
|
||||
attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{})
|
||||
if e.bpf.progFd != 0 {
|
||||
attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd)))
|
||||
}
|
||||
if e.bpf.progName != "" {
|
||||
attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName))
|
||||
}
|
||||
res = append(res, attr.Serialize()...)
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
func (e *SEG6LocalEncap) String() string {
|
||||
@ -401,12 +436,15 @@ func (e *SEG6LocalEncap) String() string {
|
||||
}
|
||||
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.
|
||||
// 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, e.Segments[i-1].String())
|
||||
}
|
||||
strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
|
||||
}
|
||||
if e.Flags[nl.SEG6_LOCAL_BPF] {
|
||||
strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd))
|
||||
}
|
||||
return strings.Join(strs, " ")
|
||||
}
|
||||
func (e *SEG6LocalEncap) Equal(x Encap) bool {
|
||||
@ -438,7 +476,7 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
|
||||
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 {
|
||||
if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -590,6 +628,109 @@ func (e *BpfEncap) Equal(x Encap) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IP6tnlEncap definition
|
||||
type IP6tnlEncap struct {
|
||||
ID uint64
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Hoplimit uint8
|
||||
TC uint8
|
||||
Flags uint16
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Type() int {
|
||||
return nl.LWTUNNEL_ENCAP_IP6
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Decode(buf []byte) error {
|
||||
attrs, err := nl.ParseRouteAttr(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.LWTUNNEL_IP6_ID:
|
||||
e.ID = uint64(native.Uint64(attr.Value[0:4]))
|
||||
case nl.LWTUNNEL_IP6_DST:
|
||||
e.Dst = net.IP(attr.Value[:])
|
||||
case nl.LWTUNNEL_IP6_SRC:
|
||||
e.Src = net.IP(attr.Value[:])
|
||||
case nl.LWTUNNEL_IP6_HOPLIMIT:
|
||||
e.Hoplimit = attr.Value[0]
|
||||
case nl.LWTUNNEL_IP6_TC:
|
||||
// e.TC = attr.Value[0]
|
||||
err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_FLAGS:
|
||||
// e.Flags = uint16(native.Uint16(attr.Value[0:2]))
|
||||
err = fmt.Errorf("decoding FLAG in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_PAD:
|
||||
err = fmt.Errorf("decoding PAD in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_OPTS:
|
||||
err = fmt.Errorf("decoding OPTS in IP6tnlEncap is not supported")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Encode() ([]byte, error) {
|
||||
|
||||
final := []byte{}
|
||||
|
||||
resID := make([]byte, 12)
|
||||
native.PutUint16(resID, 12) // 2+2+8
|
||||
native.PutUint16(resID[2:], nl.LWTUNNEL_IP6_ID)
|
||||
native.PutUint64(resID[4:], 0)
|
||||
final = append(final, resID...)
|
||||
|
||||
resDst := make([]byte, 4)
|
||||
native.PutUint16(resDst, 20) // 2+2+16
|
||||
native.PutUint16(resDst[2:], nl.LWTUNNEL_IP6_DST)
|
||||
resDst = append(resDst, e.Dst...)
|
||||
final = append(final, resDst...)
|
||||
|
||||
resSrc := make([]byte, 4)
|
||||
native.PutUint16(resSrc, 20)
|
||||
native.PutUint16(resSrc[2:], nl.LWTUNNEL_IP6_SRC)
|
||||
resSrc = append(resSrc, e.Src...)
|
||||
final = append(final, resSrc...)
|
||||
|
||||
// resTc := make([]byte, 5)
|
||||
// native.PutUint16(resTc, 5)
|
||||
// native.PutUint16(resTc[2:], nl.LWTUNNEL_IP6_TC)
|
||||
// resTc[4] = e.TC
|
||||
// final = append(final,resTc...)
|
||||
|
||||
resHops := make([]byte, 5)
|
||||
native.PutUint16(resHops, 5)
|
||||
native.PutUint16(resHops[2:], nl.LWTUNNEL_IP6_HOPLIMIT)
|
||||
resHops[4] = e.Hoplimit
|
||||
final = append(final, resHops...)
|
||||
|
||||
// resFlags := make([]byte, 6)
|
||||
// native.PutUint16(resFlags, 6)
|
||||
// native.PutUint16(resFlags[2:], nl.LWTUNNEL_IP6_FLAGS)
|
||||
// native.PutUint16(resFlags[4:], e.Flags)
|
||||
// final = append(final,resFlags...)
|
||||
|
||||
return final, nil
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) String() string {
|
||||
return fmt.Sprintf("id %d src %s dst %s hoplimit %d tc %d flags 0x%.4x", e.ID, e.Src, e.Dst, e.Hoplimit, e.TC, e.Flags)
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Equal(x Encap) bool {
|
||||
o, ok := x.(*IP6tnlEncap)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if e.ID != o.ID || e.Flags != o.Flags || e.Hoplimit != o.Hoplimit || e.Src.Equal(o.Src) || e.Dst.Equal(o.Dst) || e.TC != o.TC {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type Via struct {
|
||||
AddrFamily int
|
||||
Addr net.IP
|
||||
@ -656,7 +797,8 @@ func RouteAdd(route *Route) error {
|
||||
func (h *Handle) RouteAdd(route *Route) error {
|
||||
flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteAppend will append a route to the system.
|
||||
@ -670,7 +812,8 @@ func RouteAppend(route *Route) error {
|
||||
func (h *Handle) RouteAppend(route *Route) error {
|
||||
flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteAddEcmp will add a route to the system.
|
||||
@ -682,7 +825,23 @@ func RouteAddEcmp(route *Route) error {
|
||||
func (h *Handle) RouteAddEcmp(route *Route) error {
|
||||
flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteChange will change an existing route in the system.
|
||||
// Equivalent to: `ip route change $route`
|
||||
func RouteChange(route *Route) error {
|
||||
return pkgHandle.RouteChange(route)
|
||||
}
|
||||
|
||||
// RouteChange will change an existing route in the system.
|
||||
// Equivalent to: `ip route change $route`
|
||||
func (h *Handle) RouteChange(route *Route) error {
|
||||
flags := unix.NLM_F_REPLACE | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteReplace will add a route to the system.
|
||||
@ -696,7 +855,8 @@ func RouteReplace(route *Route) error {
|
||||
func (h *Handle) RouteReplace(route *Route) error {
|
||||
flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
return h.routeHandle(route, req, nl.NewRtMsg())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteDel will delete a route from the system.
|
||||
@ -709,12 +869,27 @@ func RouteDel(route *Route) error {
|
||||
// Equivalent to: `ip route del $route`
|
||||
func (h *Handle) RouteDel(route *Route) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK)
|
||||
return h.routeHandle(route, req, nl.NewRtDelMsg())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtDelMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||
if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
|
||||
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
|
||||
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) {
|
||||
if err := h.prepareRouteReq(route, req, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
}
|
||||
|
||||
func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error {
|
||||
if err := h.prepareRouteReq(route, req, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f)
|
||||
}
|
||||
|
||||
func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||
if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
|
||||
return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set")
|
||||
}
|
||||
|
||||
family := -1
|
||||
@ -968,19 +1143,21 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
||||
|
||||
msg.Flags = uint32(route.Flags)
|
||||
msg.Scope = uint8(route.Scope)
|
||||
msg.Family = uint8(family)
|
||||
// only overwrite family if it was not set in msg
|
||||
if msg.Family == 0 {
|
||||
msg.Family = uint8(family)
|
||||
}
|
||||
req.AddData(msg)
|
||||
for _, attr := range rtAttrs {
|
||||
req.AddData(attr)
|
||||
}
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.LinkIndex))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
if (req.NlMsghdr.Type != unix.RTM_GETROUTE) || (req.NlMsghdr.Type == unix.RTM_GETROUTE && route.LinkIndex > 0) {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.LinkIndex))
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RouteList gets a list of routes in the system.
|
||||
@ -994,13 +1171,13 @@ func RouteList(link Link, family int) ([]Route, error) {
|
||||
// Equivalent to: `ip route show`.
|
||||
// The list can be filtered by link and ip family.
|
||||
func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
|
||||
var routeFilter *Route
|
||||
routeFilter := &Route{}
|
||||
if link != nil {
|
||||
routeFilter = &Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
}
|
||||
routeFilter.LinkIndex = link.Attrs().Index
|
||||
|
||||
return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
|
||||
}
|
||||
return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
|
||||
return h.RouteListFiltered(family, routeFilter, 0)
|
||||
}
|
||||
|
||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
||||
@ -1012,68 +1189,94 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
|
||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
||||
// All rules must be defined in RouteFilter struct
|
||||
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
||||
req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
|
||||
rtmsg := nl.NewRtMsg()
|
||||
rtmsg.Family = uint8(family)
|
||||
req.AddData(rtmsg)
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||
var res []Route
|
||||
err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) {
|
||||
res = append(res, route)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var res []Route
|
||||
for _, m := range msgs {
|
||||
// RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues
|
||||
// until all routes are loaded or the func returns false.
|
||||
func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
|
||||
return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f)
|
||||
}
|
||||
|
||||
func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
|
||||
rtmsg := &nl.RtMsg{}
|
||||
rtmsg.Family = uint8(family)
|
||||
|
||||
var parseErr error
|
||||
err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool {
|
||||
msg := nl.DeserializeRtMsg(m)
|
||||
if family != FAMILY_ALL && msg.Family != uint8(family) {
|
||||
// Ignore routes not matching requested family
|
||||
return true
|
||||
}
|
||||
if msg.Flags&unix.RTM_F_CLONED != 0 {
|
||||
// Ignore cloned routes
|
||||
continue
|
||||
return true
|
||||
}
|
||||
if msg.Table != unix.RT_TABLE_MAIN {
|
||||
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
|
||||
if filter == nil || filterMask&RT_FILTER_TABLE == 0 {
|
||||
// Ignore non-main tables
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
route, err := deserializeRoute(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
parseErr = err
|
||||
return false
|
||||
}
|
||||
if filter != nil {
|
||||
switch {
|
||||
case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_DST != 0:
|
||||
if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
|
||||
if filter.Dst == nil {
|
||||
filter.Dst = genZeroIPNet(family)
|
||||
}
|
||||
if !ipNetEqual(route.Dst, filter.Dst) {
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
res = append(res, route)
|
||||
return f(route)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return res, nil
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deserializeRoute decodes a binary netlink message into a Route struct
|
||||
@ -1257,6 +1460,27 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Same logic to generate "default" dst with iproute2 implementation
|
||||
if route.Dst == nil {
|
||||
var addLen int
|
||||
var ip net.IP
|
||||
switch msg.Family {
|
||||
case FAMILY_V4:
|
||||
addLen = net.IPv4len
|
||||
ip = net.IPv4zero
|
||||
case FAMILY_V6:
|
||||
addLen = net.IPv6len
|
||||
ip = net.IPv6zero
|
||||
}
|
||||
|
||||
if addLen != 0 {
|
||||
route.Dst = &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*addLen),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(encap.Value) != 0 && len(encapType.Value) != 0 {
|
||||
typ := int(native.Uint16(encapType.Value[0:2]))
|
||||
var e Encap
|
||||
@ -1291,10 +1515,14 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||
// RouteGetOptions contains a set of options to use with
|
||||
// RouteGetWithOptions
|
||||
type RouteGetOptions struct {
|
||||
Iif string
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
Iif string
|
||||
IifIndex int
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
UID *uint32
|
||||
Mark uint32
|
||||
FIBMatch bool
|
||||
}
|
||||
|
||||
// RouteGetWithOptions gets a route to a specific destination from the host system.
|
||||
@ -1330,6 +1558,9 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
msg.Src_len = bitlen
|
||||
}
|
||||
msg.Flags = unix.RTM_F_LOOKUP_TABLE
|
||||
if options != nil && options.FIBMatch {
|
||||
msg.Flags |= unix.RTM_F_FIB_MATCH
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
|
||||
@ -1337,7 +1568,7 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
|
||||
if options != nil {
|
||||
if options.VrfName != "" {
|
||||
link, err := LinkByName(options.VrfName)
|
||||
link, err := h.LinkByName(options.VrfName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1347,20 +1578,27 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
|
||||
iifIndex := 0
|
||||
if len(options.Iif) > 0 {
|
||||
link, err := LinkByName(options.Iif)
|
||||
link, err := h.LinkByName(options.Iif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iifIndex = link.Attrs().Index
|
||||
} else if options.IifIndex > 0 {
|
||||
iifIndex = options.IifIndex
|
||||
}
|
||||
|
||||
if iifIndex > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(link.Attrs().Index))
|
||||
native.PutUint32(b, uint32(iifIndex))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
||||
}
|
||||
|
||||
if len(options.Oif) > 0 {
|
||||
link, err := LinkByName(options.Oif)
|
||||
link, err := h.LinkByName(options.Oif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1381,6 +1619,21 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
|
||||
}
|
||||
|
||||
if options.UID != nil {
|
||||
uid := *options.UID
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uid)
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_UID, b))
|
||||
}
|
||||
|
||||
if options.Mark > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, options.Mark)
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
|
||||
}
|
||||
}
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||
@ -1408,21 +1661,24 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
||||
// RouteSubscribe takes a chan down which notifications will be sent
|
||||
// when routes are added or deleted. Close the 'done' chan to stop subscription.
|
||||
func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
|
||||
return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
|
||||
return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
|
||||
// to choose the network namespace in which to subscribe (ns).
|
||||
func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
|
||||
return routeSubscribeAt(ns, netns.None(), ch, done, nil, false)
|
||||
return routeSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// RouteSubscribeOptions contains a set of options to use with
|
||||
// RouteSubscribeWithOptions.
|
||||
type RouteSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// RouteSubscribeWithOptions work like RouteSubscribe but enable to
|
||||
@ -1433,14 +1689,27 @@ func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, opti
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -1495,7 +1764,11 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
|
||||
}
|
||||
continue
|
||||
}
|
||||
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
|
||||
ch <- RouteUpdate{
|
||||
Type: m.Header.Type,
|
||||
NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND),
|
||||
Route: route,
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -1523,7 +1796,7 @@ func (p RouteProtocol) String() string {
|
||||
return "gated"
|
||||
case unix.RTPROT_ISIS:
|
||||
return "isis"
|
||||
//case unix.RTPROT_KEEPALIVED:
|
||||
// case unix.RTPROT_KEEPALIVED:
|
||||
// return "keepalived"
|
||||
case unix.RTPROT_KERNEL:
|
||||
return "kernel"
|
||||
@ -1553,3 +1826,24 @@ func (p RouteProtocol) String() string {
|
||||
return strconv.Itoa(int(p))
|
||||
}
|
||||
}
|
||||
|
||||
// genZeroIPNet returns 0.0.0.0/0 or ::/0 for IPv4 or IPv6, otherwise nil
|
||||
func genZeroIPNet(family int) *net.IPNet {
|
||||
var addLen int
|
||||
var ip net.IP
|
||||
switch family {
|
||||
case FAMILY_V4:
|
||||
addLen = net.IPv4len
|
||||
ip = net.IPv4zero
|
||||
case FAMILY_V6:
|
||||
addLen = net.IPv6len
|
||||
ip = net.IPv6zero
|
||||
}
|
||||
if addLen != 0 {
|
||||
return &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: net.CIDRMask(0, 8*addLen),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
26
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
26
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
@ -10,8 +10,8 @@ type Rule struct {
|
||||
Priority int
|
||||
Family int
|
||||
Table int
|
||||
Mark int
|
||||
Mask int
|
||||
Mark uint32
|
||||
Mask *uint32
|
||||
Tos uint
|
||||
TunID uint
|
||||
Goto int
|
||||
@ -26,6 +26,9 @@ type Rule struct {
|
||||
Dport *RulePortRange
|
||||
Sport *RulePortRange
|
||||
IPProto int
|
||||
UIDRange *RuleUIDRange
|
||||
Protocol uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
func (r Rule) String() string {
|
||||
@ -39,8 +42,8 @@ func (r Rule) String() string {
|
||||
to = r.Dst.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("ip rule %d: from %s to %s table %d",
|
||||
r.Priority, from, to, r.Table)
|
||||
return fmt.Sprintf("ip rule %d: from %s to %s table %d %s",
|
||||
r.Priority, from, to, r.Table, r.typeString())
|
||||
}
|
||||
|
||||
// NewRule return empty rules.
|
||||
@ -49,8 +52,8 @@ func NewRule() *Rule {
|
||||
SuppressIfgroup: -1,
|
||||
SuppressPrefixlen: -1,
|
||||
Priority: -1,
|
||||
Mark: -1,
|
||||
Mask: -1,
|
||||
Mark: 0,
|
||||
Mask: nil,
|
||||
Goto: -1,
|
||||
Flow: -1,
|
||||
}
|
||||
@ -66,3 +69,14 @@ type RulePortRange struct {
|
||||
Start uint16
|
||||
End uint16
|
||||
}
|
||||
|
||||
// NewRuleUIDRange creates rule uid range.
|
||||
func NewRuleUIDRange(start, end uint32) *RuleUIDRange {
|
||||
return &RuleUIDRange{Start: start, End: end}
|
||||
}
|
||||
|
||||
// RuleUIDRange represents rule uid range.
|
||||
type RuleUIDRange struct {
|
||||
Start uint32
|
||||
End uint32
|
||||
}
|
||||
|
82
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
82
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
@ -43,8 +43,8 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
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 = rule.Type // usually 0, same as unix.RTN_UNSPEC
|
||||
if msg.Type == 0 && req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
|
||||
msg.Type = unix.RTN_UNICAST
|
||||
}
|
||||
if rule.Invert {
|
||||
@ -102,14 +102,14 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
native.PutUint32(b, uint32(rule.Priority))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
|
||||
}
|
||||
if rule.Mark >= 0 {
|
||||
if rule.Mark != 0 || rule.Mask != nil {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mark))
|
||||
native.PutUint32(b, rule.Mark)
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
|
||||
}
|
||||
if rule.Mask >= 0 {
|
||||
if rule.Mask != nil {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mask))
|
||||
native.PutUint32(b, *rule.Mask)
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
|
||||
}
|
||||
if rule.Flow >= 0 {
|
||||
@ -168,6 +168,15 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b))
|
||||
}
|
||||
|
||||
if rule.UIDRange != nil {
|
||||
b := rule.UIDRange.toRtAttrData()
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_UID_RANGE, b))
|
||||
}
|
||||
|
||||
if rule.Protocol > 0 {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PROTOCOL, nl.Uint8Attr(rule.Protocol)))
|
||||
}
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
@ -212,8 +221,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
}
|
||||
|
||||
rule := NewRule()
|
||||
rule.Priority = 0 // The default priority from kernel
|
||||
|
||||
rule.Invert = msg.Flags&FibRuleInvert > 0
|
||||
rule.Family = int(msg.Family)
|
||||
rule.Tos = uint(msg.Tos)
|
||||
|
||||
for j := range attrs {
|
||||
@ -231,9 +242,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
|
||||
}
|
||||
case nl.FRA_FWMARK:
|
||||
rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
rule.Mark = native.Uint32(attrs[j].Value[0:4])
|
||||
case nl.FRA_FWMASK:
|
||||
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
mask := native.Uint32(attrs[j].Value[0:4])
|
||||
rule.Mask = &mask
|
||||
case nl.FRA_TUN_ID:
|
||||
rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
|
||||
case nl.FRA_IIFNAME:
|
||||
@ -262,6 +274,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4]))
|
||||
case nl.FRA_SPORT_RANGE:
|
||||
rule.Sport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4]))
|
||||
case nl.FRA_UID_RANGE:
|
||||
rule.UIDRange = NewRuleUIDRange(native.Uint32(attrs[j].Value[0:4]), native.Uint32(attrs[j].Value[4:8]))
|
||||
case nl.FRA_PROTOCOL:
|
||||
rule.Protocol = uint8(attrs[j].Value[0])
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +298,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
continue
|
||||
case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark:
|
||||
continue
|
||||
case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask:
|
||||
case filterMask&RT_FILTER_MASK != 0 && !ptrEqual(rule.Mask, filter.Mask):
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -299,3 +315,51 @@ func (pr *RulePortRange) toRtAttrData() []byte {
|
||||
native.PutUint16(b[1], pr.End)
|
||||
return bytes.Join(b, []byte{})
|
||||
}
|
||||
|
||||
func (pr *RuleUIDRange) toRtAttrData() []byte {
|
||||
b := [][]byte{make([]byte, 4), make([]byte, 4)}
|
||||
native.PutUint32(b[0], pr.Start)
|
||||
native.PutUint32(b[1], pr.End)
|
||||
return bytes.Join(b, []byte{})
|
||||
}
|
||||
|
||||
func ptrEqual(a, b *uint32) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if (a == nil) || (b == nil) {
|
||||
return false
|
||||
}
|
||||
return *a == *b
|
||||
}
|
||||
|
||||
func (r Rule) typeString() string {
|
||||
switch r.Type {
|
||||
case unix.RTN_UNSPEC: // zero
|
||||
return ""
|
||||
case unix.RTN_UNICAST:
|
||||
return ""
|
||||
case unix.RTN_LOCAL:
|
||||
return "local"
|
||||
case unix.RTN_BROADCAST:
|
||||
return "broadcast"
|
||||
case unix.RTN_ANYCAST:
|
||||
return "anycast"
|
||||
case unix.RTN_MULTICAST:
|
||||
return "multicast"
|
||||
case unix.RTN_BLACKHOLE:
|
||||
return "blackhole"
|
||||
case unix.RTN_UNREACHABLE:
|
||||
return "unreachable"
|
||||
case unix.RTN_PROHIBIT:
|
||||
return "prohibit"
|
||||
case unix.RTN_THROW:
|
||||
return "throw"
|
||||
case unix.RTN_NAT:
|
||||
return "nat"
|
||||
case unix.RTN_XRESOLVE:
|
||||
return "xresolve"
|
||||
default:
|
||||
return fmt.Sprintf("type(0x%x)", r.Type)
|
||||
}
|
||||
}
|
||||
|
8
vendor/github.com/vishvananda/netlink/rule_nonlinux.go
generated
vendored
Normal file
8
vendor/github.com/vishvananda/netlink/rule_nonlinux.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package netlink
|
||||
|
||||
func (r Rule) typeString() string {
|
||||
return ""
|
||||
}
|
77
vendor/github.com/vishvananda/netlink/socket.go
generated
vendored
77
vendor/github.com/vishvananda/netlink/socket.go
generated
vendored
@ -25,3 +25,80 @@ type Socket struct {
|
||||
UID uint32
|
||||
INode uint32
|
||||
}
|
||||
|
||||
// UnixSocket represents a netlink unix socket.
|
||||
type UnixSocket struct {
|
||||
Type uint8
|
||||
Family uint8
|
||||
State uint8
|
||||
pad uint8
|
||||
INode uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
// XDPSocket represents an XDP socket (and the common diagnosis part in
|
||||
// particular). Please note that in contrast to [UnixSocket] the XDPSocket type
|
||||
// does not feature “State” information.
|
||||
type XDPSocket struct {
|
||||
// xdp_diag_msg
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
|
||||
Family uint8
|
||||
Type uint8
|
||||
pad uint16
|
||||
Ino uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
type XDPInfo struct {
|
||||
// XDP_DIAG_INFO/xdp_diag_info
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L51
|
||||
Ifindex uint32
|
||||
QueueID uint32
|
||||
|
||||
// XDP_DIAG_UID
|
||||
UID uint32
|
||||
|
||||
// XDP_RX_RING
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L56
|
||||
RxRingEntries uint32
|
||||
TxRingEntries uint32
|
||||
UmemFillRingEntries uint32
|
||||
UmemCompletionRingEntries uint32
|
||||
|
||||
// XDR_DIAG_UMEM
|
||||
Umem *XDPDiagUmem
|
||||
|
||||
// XDR_DIAG_STATS
|
||||
Stats *XDPDiagStats
|
||||
}
|
||||
|
||||
const (
|
||||
XDP_DU_F_ZEROCOPY = 1 << iota
|
||||
)
|
||||
|
||||
// XDPDiagUmem describes the umem attached to an XDP socket.
|
||||
//
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L62
|
||||
type XDPDiagUmem struct {
|
||||
Size uint64
|
||||
ID uint32
|
||||
NumPages uint32
|
||||
ChunkSize uint32
|
||||
Headroom uint32
|
||||
Ifindex uint32
|
||||
QueueID uint32
|
||||
Flags uint32
|
||||
Refs uint32
|
||||
}
|
||||
|
||||
// XDPDiagStats contains ring statistics for an XDP socket.
|
||||
//
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L74
|
||||
type XDPDiagStats struct {
|
||||
RxDropped uint64
|
||||
RxInvalid uint64
|
||||
RxFull uint64
|
||||
FillRingEmpty uint64
|
||||
TxInvalid uint64
|
||||
TxRingEmpty uint64
|
||||
}
|
||||
|
507
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
507
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
@ -11,9 +11,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofSocketID = 0x30
|
||||
sizeofSocketRequest = sizeofSocketID + 0x8
|
||||
sizeofSocket = sizeofSocketID + 0x18
|
||||
sizeofSocketID = 0x30
|
||||
sizeofSocketRequest = sizeofSocketID + 0x8
|
||||
sizeofSocket = sizeofSocketID + 0x18
|
||||
sizeofUnixSocketRequest = 0x18 // 24 byte
|
||||
sizeofUnixSocket = 0x10 // 16 byte
|
||||
)
|
||||
|
||||
type socketRequest struct {
|
||||
@ -54,10 +56,8 @@ func (r *socketRequest) Serialize() []byte {
|
||||
copy(b.Next(16), r.ID.Source)
|
||||
copy(b.Next(16), r.ID.Destination)
|
||||
} else {
|
||||
copy(b.Next(4), r.ID.Source.To4())
|
||||
b.Next(12)
|
||||
copy(b.Next(4), r.ID.Destination.To4())
|
||||
b.Next(12)
|
||||
copy(b.Next(16), r.ID.Source.To4())
|
||||
copy(b.Next(16), r.ID.Destination.To4())
|
||||
}
|
||||
native.PutUint32(b.Next(4), r.ID.Interface)
|
||||
native.PutUint32(b.Next(4), r.ID.Cookie[0])
|
||||
@ -67,6 +67,32 @@ func (r *socketRequest) Serialize() []byte {
|
||||
|
||||
func (r *socketRequest) Len() int { return sizeofSocketRequest }
|
||||
|
||||
// According to linux/include/uapi/linux/unix_diag.h
|
||||
type unixSocketRequest struct {
|
||||
Family uint8
|
||||
Protocol uint8
|
||||
pad uint16
|
||||
States uint32
|
||||
INode uint32
|
||||
Show uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
func (r *unixSocketRequest) Serialize() []byte {
|
||||
b := writeBuffer{Bytes: make([]byte, sizeofUnixSocketRequest)}
|
||||
b.Write(r.Family)
|
||||
b.Write(r.Protocol)
|
||||
native.PutUint16(b.Next(2), r.pad)
|
||||
native.PutUint32(b.Next(4), r.States)
|
||||
native.PutUint32(b.Next(4), r.INode)
|
||||
native.PutUint32(b.Next(4), r.Show)
|
||||
native.PutUint32(b.Next(4), r.Cookie[0])
|
||||
native.PutUint32(b.Next(4), r.Cookie[1])
|
||||
return b.Bytes
|
||||
}
|
||||
|
||||
func (r *unixSocketRequest) Len() int { return sizeofUnixSocketRequest }
|
||||
|
||||
type readBuffer struct {
|
||||
Bytes []byte
|
||||
pos int
|
||||
@ -115,31 +141,126 @@ func (s *Socket) deserialize(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UnixSocket) deserialize(b []byte) error {
|
||||
if len(b) < sizeofUnixSocket {
|
||||
return fmt.Errorf("unix diag data short read (%d); want %d", len(b), sizeofUnixSocket)
|
||||
}
|
||||
rb := readBuffer{Bytes: b}
|
||||
u.Type = rb.Read()
|
||||
u.Family = rb.Read()
|
||||
u.State = rb.Read()
|
||||
u.pad = rb.Read()
|
||||
u.INode = native.Uint32(rb.Next(4))
|
||||
u.Cookie[0] = native.Uint32(rb.Next(4))
|
||||
u.Cookie[1] = native.Uint32(rb.Next(4))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SocketGet returns the Socket identified by its local and remote addresses.
|
||||
func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
var protocol uint8
|
||||
var localIP, remoteIP net.IP
|
||||
var localPort, remotePort uint16
|
||||
switch l := local.(type) {
|
||||
case *net.TCPAddr:
|
||||
r, ok := remote.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
localIP = l.IP
|
||||
localPort = uint16(l.Port)
|
||||
remoteIP = r.IP
|
||||
remotePort = uint16(r.Port)
|
||||
protocol = unix.IPPROTO_TCP
|
||||
case *net.UDPAddr:
|
||||
r, ok := remote.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
localIP = l.IP
|
||||
localPort = uint16(l.Port)
|
||||
remoteIP = r.IP
|
||||
remotePort = uint16(r.Port)
|
||||
protocol = unix.IPPROTO_UDP
|
||||
default:
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
var family uint8
|
||||
if localIP.To4() != nil && remoteIP.To4() != nil {
|
||||
family = unix.AF_INET
|
||||
}
|
||||
|
||||
if family == 0 && localIP.To16() != nil && remoteIP.To16() != nil {
|
||||
family = unix.AF_INET6
|
||||
}
|
||||
|
||||
if family == 0 {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: protocol,
|
||||
States: 0xffffffff,
|
||||
ID: SocketID{
|
||||
SourcePort: localPort,
|
||||
DestinationPort: remotePort,
|
||||
Source: localIP,
|
||||
Destination: remoteIP,
|
||||
Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
|
||||
},
|
||||
})
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return nil, errors.New("no message nor error from netlink")
|
||||
}
|
||||
if len(msgs) > 2 {
|
||||
return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs))
|
||||
}
|
||||
|
||||
sock := &Socket{}
|
||||
if err := sock.deserialize(msgs[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sock, nil
|
||||
}
|
||||
|
||||
// SocketGet returns the Socket identified by its local and remote addresses.
|
||||
func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
return pkgHandle.SocketGet(local, remote)
|
||||
}
|
||||
|
||||
// SocketDestroy kills the Socket identified by its local and remote addresses.
|
||||
func (h *Handle) SocketDestroy(local, remote net.Addr) error {
|
||||
localTCP, ok := local.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
remoteTCP, ok := remote.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
localIP := localTCP.IP.To4()
|
||||
if localIP == nil {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
remoteIP := remoteTCP.IP.To4()
|
||||
if remoteIP == nil {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
|
||||
req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK)
|
||||
req.AddData(&socketRequest{
|
||||
Family: unix.AF_INET,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
@ -151,47 +272,81 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
|
||||
},
|
||||
})
|
||||
s.Send(req)
|
||||
msgs, from, err := s.Receive()
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_INET_DIAG, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// SocketDestroy kills the Socket identified by its local and remote addresses.
|
||||
func SocketDestroy(local, remote net.Addr) error {
|
||||
return pkgHandle.SocketDestroy(local, remote)
|
||||
}
|
||||
|
||||
// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
|
||||
func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*InetDiagTCPInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *InetDiagTCPInfoResp
|
||||
if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if from.Pid != nl.PidKernel {
|
||||
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return nil, errors.New("no message nor error from netlink")
|
||||
}
|
||||
if len(msgs) > 2 {
|
||||
return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs))
|
||||
}
|
||||
sock := &Socket{}
|
||||
if err := sock.deserialize(msgs[0].Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sock, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
|
||||
func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
var result []*InetDiagTCPInfoResp
|
||||
err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
|
||||
return pkgHandle.SocketDiagTCPInfo(family)
|
||||
}
|
||||
|
||||
// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
|
||||
func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*Socket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return nil
|
||||
result = append(result, sockInfo)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -201,14 +356,46 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
|
||||
// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
|
||||
func SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
var result []*Socket
|
||||
err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
|
||||
return pkgHandle.SocketDiagTCP(family)
|
||||
}
|
||||
|
||||
// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
|
||||
func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
|
||||
// Construct the request
|
||||
var extensions uint8
|
||||
extensions = 1 << (INET_DIAG_VEGASINFO - 1)
|
||||
extensions |= 1 << (INET_DIAG_INFO - 1)
|
||||
extensions |= 1 << (INET_DIAG_MEMINFO - 1)
|
||||
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_UDP,
|
||||
Ext: extensions,
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*InetDiagUDPInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, sockInfo)
|
||||
return nil
|
||||
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *InetDiagUDPInfoResp
|
||||
if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -216,76 +403,188 @@ func SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// socketDiagTCPExecutor requests INET_DIAG_INFO for TCP protocol for specified family type.
|
||||
func socketDiagTCPExecutor(family uint8, receiver func(syscall.NetlinkMessage) error) error {
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
|
||||
func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
|
||||
return pkgHandle.SocketDiagUDPInfo(family)
|
||||
}
|
||||
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
|
||||
func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
Protocol: unix.IPPROTO_UDP,
|
||||
Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
|
||||
States: uint32(0xfff), // All TCP states
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
s.Send(req)
|
||||
|
||||
loop:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if from.Pid != nl.PidKernel {
|
||||
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return errors.New("no message nor error from netlink")
|
||||
}
|
||||
|
||||
for _, m := range msgs {
|
||||
switch m.Header.Type {
|
||||
case unix.NLMSG_DONE:
|
||||
break loop
|
||||
case unix.NLMSG_ERROR:
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
return syscall.Errno(-error)
|
||||
}
|
||||
if err := receiver(m); err != nil {
|
||||
return err
|
||||
}
|
||||
// Do the query and parse the result
|
||||
var result []*Socket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, sockInfo)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
|
||||
func SocketDiagUDP(family uint8) ([]*Socket, error) {
|
||||
return pkgHandle.SocketDiagUDP(family)
|
||||
}
|
||||
|
||||
// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
|
||||
func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
|
||||
// Construct the request
|
||||
var extensions uint8
|
||||
extensions = 1 << UNIX_DIAG_NAME
|
||||
extensions |= 1 << UNIX_DIAG_PEER
|
||||
extensions |= 1 << UNIX_DIAG_RQLEN
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&unixSocketRequest{
|
||||
Family: unix.AF_UNIX,
|
||||
States: ^uint32(0), // all states
|
||||
Show: uint32(extensions),
|
||||
})
|
||||
|
||||
var result []*UnixDiagInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &UnixSocket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Diagnosis also delivers sockets with AF_INET family, filter those
|
||||
if sockInfo.Family != unix.AF_UNIX {
|
||||
return false
|
||||
}
|
||||
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *UnixDiagInfoResp
|
||||
if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
|
||||
func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
|
||||
return pkgHandle.UnixSocketDiagInfo()
|
||||
}
|
||||
|
||||
// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
|
||||
func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&unixSocketRequest{
|
||||
Family: unix.AF_UNIX,
|
||||
States: ^uint32(0), // all states
|
||||
})
|
||||
|
||||
var result []*UnixSocket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &UnixSocket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Diagnosis also delivers sockets with AF_INET family, filter those
|
||||
if sockInfo.Family == unix.AF_UNIX {
|
||||
result = append(result, sockInfo)
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
|
||||
func UnixSocketDiag() ([]*UnixSocket, error) {
|
||||
return pkgHandle.UnixSocketDiag()
|
||||
}
|
||||
|
||||
func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
|
||||
var tcpInfo *TCPInfo
|
||||
var tcpBBRInfo *TCPBBRInfo
|
||||
info := &InetDiagTCPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
if a.Attr.Type == INET_DIAG_INFO {
|
||||
tcpInfo = &TCPInfo{}
|
||||
if err := tcpInfo.deserialize(a.Value); err != nil {
|
||||
switch a.Attr.Type {
|
||||
case INET_DIAG_INFO:
|
||||
info.TCPInfo = &TCPInfo{}
|
||||
if err := info.TCPInfo.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if a.Attr.Type == INET_DIAG_BBRINFO {
|
||||
tcpBBRInfo = &TCPBBRInfo{}
|
||||
if err := tcpBBRInfo.deserialize(a.Value); err != nil {
|
||||
case INET_DIAG_BBRINFO:
|
||||
info.TCPBBRInfo = &TCPBBRInfo{}
|
||||
if err := info.TCPBBRInfo.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return &InetDiagTCPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
TCPInfo: tcpInfo,
|
||||
TCPBBRInfo: tcpBBRInfo,
|
||||
}, nil
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func attrsToInetDiagUDPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagUDPInfoResp, error) {
|
||||
info := &InetDiagUDPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case INET_DIAG_MEMINFO:
|
||||
info.Memory = &MemInfo{}
|
||||
if err := info.Memory.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func attrsToUnixDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *UnixSocket) (*UnixDiagInfoResp, error) {
|
||||
info := &UnixDiagInfoResp{
|
||||
DiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case UNIX_DIAG_NAME:
|
||||
name := string(a.Value[:a.Attr.Len])
|
||||
info.Name = &name
|
||||
case UNIX_DIAG_PEER:
|
||||
peer := native.Uint32(a.Value)
|
||||
info.Peer = &peer
|
||||
case UNIX_DIAG_RQLEN:
|
||||
info.Queue = &QueueInfo{
|
||||
RQueue: native.Uint32(a.Value[:4]),
|
||||
WQueue: native.Uint32(a.Value[4:]),
|
||||
}
|
||||
// default:
|
||||
// fmt.Println("unknown unix attribute type", a.Attr.Type, "with data", a.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
195
vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
generated
vendored
Normal file
195
vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofXDPSocketRequest = 1 + 1 + 2 + 4 + 4 + 2*4
|
||||
sizeofXDPSocket = 0x10
|
||||
)
|
||||
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L12
|
||||
type xdpSocketRequest struct {
|
||||
Family uint8
|
||||
Protocol uint8
|
||||
pad uint16
|
||||
Ino uint32
|
||||
Show uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
func (r *xdpSocketRequest) Serialize() []byte {
|
||||
b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)}
|
||||
b.Write(r.Family)
|
||||
b.Write(r.Protocol)
|
||||
native.PutUint16(b.Next(2), r.pad)
|
||||
native.PutUint32(b.Next(4), r.Ino)
|
||||
native.PutUint32(b.Next(4), r.Show)
|
||||
native.PutUint32(b.Next(4), r.Cookie[0])
|
||||
native.PutUint32(b.Next(4), r.Cookie[1])
|
||||
return b.Bytes
|
||||
}
|
||||
|
||||
func (r *xdpSocketRequest) Len() int { return sizeofXDPSocketRequest }
|
||||
|
||||
func (s *XDPSocket) deserialize(b []byte) error {
|
||||
if len(b) < sizeofXDPSocket {
|
||||
return fmt.Errorf("XDP socket data short read (%d); want %d", len(b), sizeofXDPSocket)
|
||||
}
|
||||
rb := readBuffer{Bytes: b}
|
||||
s.Family = rb.Read()
|
||||
s.Type = rb.Read()
|
||||
s.pad = native.Uint16(rb.Next(2))
|
||||
s.Ino = native.Uint32(rb.Next(4))
|
||||
s.Cookie[0] = native.Uint32(rb.Next(4))
|
||||
s.Cookie[1] = native.Uint32(rb.Next(4))
|
||||
return nil
|
||||
}
|
||||
|
||||
// XDPSocketGet returns the XDP socket identified by its inode number and/or
|
||||
// socket cookie. Specify the cookie as SOCK_ANY_COOKIE if
|
||||
func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) {
|
||||
// We have a problem here: dumping AF_XDP sockets currently does not support
|
||||
// filtering. We thus need to dump all XSKs and then only filter afterwards
|
||||
// :(
|
||||
xsks, err := SocketDiagXDP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checkCookie := cookie != SOCK_ANY_COOKIE && cookie != 0
|
||||
crumblingCookie := [2]uint32{uint32(cookie), uint32(cookie >> 32)}
|
||||
checkIno := ino != 0
|
||||
var xskinfo *XDPDiagInfoResp
|
||||
for _, xsk := range xsks {
|
||||
if checkIno && xsk.XDPDiagMsg.Ino != ino {
|
||||
continue
|
||||
}
|
||||
if checkCookie && xsk.XDPDiagMsg.Cookie != crumblingCookie {
|
||||
continue
|
||||
}
|
||||
if xskinfo != nil {
|
||||
return nil, errors.New("multiple matching XDP sockets")
|
||||
}
|
||||
xskinfo = xsk
|
||||
}
|
||||
if xskinfo == nil {
|
||||
return nil, errors.New("no matching XDP socket")
|
||||
}
|
||||
return xskinfo, nil
|
||||
}
|
||||
|
||||
// SocketDiagXDP requests XDP_DIAG_INFO for XDP family sockets.
|
||||
func SocketDiagXDP() ([]*XDPDiagInfoResp, error) {
|
||||
var result []*XDPDiagInfoResp
|
||||
err := socketDiagXDPExecutor(func(m syscall.NetlinkMessage) error {
|
||||
sockInfo := &XDPSocket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(m.Data[sizeofXDPSocket:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := attrsToXDPDiagInfoResp(attrs, sockInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// socketDiagXDPExecutor requests XDP_DIAG_INFO for XDP family sockets.
|
||||
func socketDiagXDPExecutor(receiver func(syscall.NetlinkMessage) error) error {
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&xdpSocketRequest{
|
||||
Family: unix.AF_XDP,
|
||||
Show: XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM | XDP_SHOW_STATS,
|
||||
})
|
||||
if err := s.Send(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loop:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if from.Pid != nl.PidKernel {
|
||||
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return errors.New("no message nor error from netlink")
|
||||
}
|
||||
|
||||
for _, m := range msgs {
|
||||
switch m.Header.Type {
|
||||
case unix.NLMSG_DONE:
|
||||
break loop
|
||||
case unix.NLMSG_ERROR:
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
return syscall.Errno(-error)
|
||||
}
|
||||
if err := receiver(m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func attrsToXDPDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *XDPSocket) (*XDPDiagInfoResp, error) {
|
||||
resp := &XDPDiagInfoResp{
|
||||
XDPDiagMsg: sockInfo,
|
||||
XDPInfo: &XDPInfo{},
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case XDP_DIAG_INFO:
|
||||
resp.XDPInfo.Ifindex = native.Uint32(a.Value[0:4])
|
||||
resp.XDPInfo.QueueID = native.Uint32(a.Value[4:8])
|
||||
case XDP_DIAG_UID:
|
||||
resp.XDPInfo.UID = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_RX_RING:
|
||||
resp.XDPInfo.RxRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_TX_RING:
|
||||
resp.XDPInfo.TxRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM_FILL_RING:
|
||||
resp.XDPInfo.UmemFillRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM_COMPLETION_RING:
|
||||
resp.XDPInfo.UmemCompletionRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM:
|
||||
umem := &XDPDiagUmem{}
|
||||
if err := umem.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.XDPInfo.Umem = umem
|
||||
case XDP_DIAG_STATS:
|
||||
stats := &XDPDiagStats{}
|
||||
if err := stats.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.XDPInfo.Stats = stats
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
8
vendor/github.com/vishvananda/netlink/tcp.go
generated
vendored
8
vendor/github.com/vishvananda/netlink/tcp.go
generated
vendored
@ -82,3 +82,11 @@ type TCPBBRInfo struct {
|
||||
BBRPacingGain uint32
|
||||
BBRCwndGain uint32
|
||||
}
|
||||
|
||||
// According to https://man7.org/linux/man-pages/man7/sock_diag.7.html
|
||||
type MemInfo struct {
|
||||
RMem uint32
|
||||
WMem uint32
|
||||
FMem uint32
|
||||
TMem uint32
|
||||
}
|
||||
|
15
vendor/github.com/vishvananda/netlink/tcp_linux.go
generated
vendored
15
vendor/github.com/vishvananda/netlink/tcp_linux.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
|
||||
const (
|
||||
tcpBBRInfoLen = 20
|
||||
memInfoLen = 16
|
||||
)
|
||||
|
||||
func checkDeserErr(err error) error {
|
||||
@ -351,3 +352,17 @@ func (t *TCPBBRInfo) deserialize(b []byte) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MemInfo) deserialize(b []byte) error {
|
||||
if len(b) != memInfoLen {
|
||||
return errors.New("Invalid length")
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
m.RMem = native.Uint32(rb.Next(4))
|
||||
m.WMem = native.Uint32(rb.Next(4))
|
||||
m.FMem = native.Uint32(rb.Next(4))
|
||||
m.TMem = native.Uint32(rb.Next(4))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
27
vendor/github.com/vishvananda/netlink/unix_diag.go
generated
vendored
Normal file
27
vendor/github.com/vishvananda/netlink/unix_diag.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package netlink
|
||||
|
||||
// According to linux/include/uapi/linux/unix_diag.h
|
||||
const (
|
||||
UNIX_DIAG_NAME = iota
|
||||
UNIX_DIAG_VFS
|
||||
UNIX_DIAG_PEER
|
||||
UNIX_DIAG_ICONS
|
||||
UNIX_DIAG_RQLEN
|
||||
UNIX_DIAG_MEMINFO
|
||||
UNIX_DIAG_SHUTDOWN
|
||||
UNIX_DIAG_UID
|
||||
UNIX_DIAG_MAX
|
||||
)
|
||||
|
||||
type UnixDiagInfoResp struct {
|
||||
DiagMsg *UnixSocket
|
||||
Name *string
|
||||
Peer *uint32
|
||||
Queue *QueueInfo
|
||||
Shutdown *uint8
|
||||
}
|
||||
|
||||
type QueueInfo struct {
|
||||
RQueue uint32
|
||||
WQueue uint32
|
||||
}
|
463
vendor/github.com/vishvananda/netlink/vdpa_linux.go
generated
vendored
Normal file
463
vendor/github.com/vishvananda/netlink/vdpa_linux.go
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
type vdpaDevID struct {
|
||||
Name string
|
||||
ID uint32
|
||||
}
|
||||
|
||||
// VDPADev contains info about VDPA device
|
||||
type VDPADev struct {
|
||||
vdpaDevID
|
||||
VendorID uint32
|
||||
MaxVQS uint32
|
||||
MaxVQSize uint16
|
||||
MinVQSize uint16
|
||||
}
|
||||
|
||||
// VDPADevConfig contains configuration of the VDPA device
|
||||
type VDPADevConfig struct {
|
||||
vdpaDevID
|
||||
Features uint64
|
||||
NegotiatedFeatures uint64
|
||||
Net VDPADevConfigNet
|
||||
}
|
||||
|
||||
// VDPADevVStats conatins vStats for the VDPA device
|
||||
type VDPADevVStats struct {
|
||||
vdpaDevID
|
||||
QueueIndex uint32
|
||||
Vendor []VDPADevVStatsVendor
|
||||
NegotiatedFeatures uint64
|
||||
}
|
||||
|
||||
// VDPADevVStatsVendor conatins name and value for vendor specific vstat option
|
||||
type VDPADevVStatsVendor struct {
|
||||
Name string
|
||||
Value uint64
|
||||
}
|
||||
|
||||
// VDPADevConfigNet conatins status and net config for the VDPA device
|
||||
type VDPADevConfigNet struct {
|
||||
Status VDPADevConfigNetStatus
|
||||
Cfg VDPADevConfigNetCfg
|
||||
}
|
||||
|
||||
// VDPADevConfigNetStatus contains info about net status
|
||||
type VDPADevConfigNetStatus struct {
|
||||
LinkUp bool
|
||||
Announce bool
|
||||
}
|
||||
|
||||
// VDPADevConfigNetCfg contains net config for the VDPA device
|
||||
type VDPADevConfigNetCfg struct {
|
||||
MACAddr net.HardwareAddr
|
||||
MaxVQP uint16
|
||||
MTU uint16
|
||||
}
|
||||
|
||||
// VDPAMGMTDev conatins info about VDPA management device
|
||||
type VDPAMGMTDev struct {
|
||||
BusName string
|
||||
DevName string
|
||||
SupportedClasses uint64
|
||||
SupportedFeatures uint64
|
||||
MaxVQS uint32
|
||||
}
|
||||
|
||||
// VDPANewDevParams contains parameters for new VDPA device
|
||||
// use SetBits to configure requried features for the device
|
||||
// example:
|
||||
//
|
||||
// VDPANewDevParams{Features: SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR)}
|
||||
type VDPANewDevParams struct {
|
||||
MACAddr net.HardwareAddr
|
||||
MaxVQP uint16
|
||||
MTU uint16
|
||||
Features uint64
|
||||
}
|
||||
|
||||
// SetBits set provided bits in the uint64 input value
|
||||
// usage example:
|
||||
// features := SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR)
|
||||
func SetBits(input uint64, pos ...int) uint64 {
|
||||
for _, p := range pos {
|
||||
input |= 1 << uint64(p)
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
// IsBitSet check if specific bit is set in the uint64 input value
|
||||
// usage example:
|
||||
// hasNetClass := IsBitSet(mgmtDev, VIRTIO_ID_NET)
|
||||
func IsBitSet(input uint64, pos int) bool {
|
||||
val := input & (1 << uint64(pos))
|
||||
return val > 0
|
||||
}
|
||||
|
||||
// VDPANewDev adds new VDPA device
|
||||
// Equivalent to: `vdpa dev add name <name> mgmtdev <mgmtBus>/mgmtName [params]`
|
||||
func VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
|
||||
return pkgHandle.VDPANewDev(name, mgmtBus, mgmtName, params)
|
||||
}
|
||||
|
||||
// VDPADelDev removes VDPA device
|
||||
// Equivalent to: `vdpa dev del <name>`
|
||||
func VDPADelDev(name string) error {
|
||||
return pkgHandle.VDPADelDev(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevList returns list of VDPA devices
|
||||
// Equivalent to: `vdpa dev show`
|
||||
func VDPAGetDevList() ([]*VDPADev, error) {
|
||||
return pkgHandle.VDPAGetDevList()
|
||||
}
|
||||
|
||||
// VDPAGetDevByName returns VDPA device selected by name
|
||||
// Equivalent to: `vdpa dev show <name>`
|
||||
func VDPAGetDevByName(name string) (*VDPADev, error) {
|
||||
return pkgHandle.VDPAGetDevByName(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigList returns list of VDPA devices configurations
|
||||
// Equivalent to: `vdpa dev config show`
|
||||
func VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
|
||||
return pkgHandle.VDPAGetDevConfigList()
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigByName returns VDPA device configuration selected by name
|
||||
// Equivalent to: `vdpa dev config show <name>`
|
||||
func VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
|
||||
return pkgHandle.VDPAGetDevConfigByName(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevVStats returns vstats for VDPA device
|
||||
// Equivalent to: `vdpa dev vstats show <name> qidx <queueIndex>`
|
||||
func VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
|
||||
return pkgHandle.VDPAGetDevVStats(name, queueIndex)
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevList returns list of mgmt devices
|
||||
// Equivalent to: `vdpa mgmtdev show`
|
||||
func VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
|
||||
return pkgHandle.VDPAGetMGMTDevList()
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name
|
||||
// Equivalent to: `vdpa mgmtdev show <bus>/<name>`
|
||||
func VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
|
||||
return pkgHandle.VDPAGetMGMTDevByBusAndName(bus, name)
|
||||
}
|
||||
|
||||
type vdpaNetlinkMessage []syscall.NetlinkRouteAttr
|
||||
|
||||
func (id *vdpaDevID) parseIDAttribute(attr syscall.NetlinkRouteAttr) {
|
||||
switch attr.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_NAME:
|
||||
id.Name = nl.BytesToString(attr.Value)
|
||||
case nl.VDPA_ATTR_DEV_ID:
|
||||
id.ID = native.Uint32(attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (netStatus *VDPADevConfigNetStatus) parseStatusAttribute(value []byte) {
|
||||
a := native.Uint16(value)
|
||||
netStatus.Announce = (a & VIRTIO_NET_S_ANNOUNCE) > 0
|
||||
netStatus.LinkUp = (a & VIRTIO_NET_S_LINK_UP) > 0
|
||||
}
|
||||
|
||||
func (d *VDPADev) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
d.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ID:
|
||||
d.VendorID = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MAX_VQS:
|
||||
d.MaxVQS = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MAX_VQ_SIZE:
|
||||
d.MaxVQSize = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MIN_VQ_SIZE:
|
||||
d.MinVQSize = native.Uint16(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *VDPADevConfig) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
c.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MACADDR:
|
||||
c.Net.Cfg.MACAddr = a.Value
|
||||
case nl.VDPA_ATTR_DEV_NET_STATUS:
|
||||
c.Net.Status.parseStatusAttribute(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP:
|
||||
c.Net.Cfg.MaxVQP = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MTU:
|
||||
c.Net.Cfg.MTU = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_FEATURES:
|
||||
c.Features = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
|
||||
c.NegotiatedFeatures = native.Uint64(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *VDPADevVStats) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
s.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_QUEUE_INDEX:
|
||||
s.QueueIndex = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ATTR_NAME:
|
||||
s.Vendor = append(s.Vendor, VDPADevVStatsVendor{Name: nl.BytesToString(a.Value)})
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ATTR_VALUE:
|
||||
if len(s.Vendor) == 0 {
|
||||
break
|
||||
}
|
||||
s.Vendor[len(s.Vendor)-1].Value = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
|
||||
s.NegotiatedFeatures = native.Uint64(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VDPAMGMTDev) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_MGMTDEV_BUS_NAME:
|
||||
d.BusName = nl.BytesToString(a.Value)
|
||||
case nl.VDPA_ATTR_MGMTDEV_DEV_NAME:
|
||||
d.DevName = nl.BytesToString(a.Value)
|
||||
case nl.VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES:
|
||||
d.SupportedClasses = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_SUPPORTED_FEATURES:
|
||||
d.SupportedFeatures = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MGMTDEV_MAX_VQS:
|
||||
d.MaxVQS = native.Uint32(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) ([]vdpaNetlinkMessage, error) {
|
||||
f, err := h.GenlFamilyGet(nl.VDPA_GENL_NAME)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_ACK|extraFlags)
|
||||
req.AddData(&nl.Genlmsg{
|
||||
Command: command,
|
||||
Version: nl.VDPA_GENL_VERSION,
|
||||
})
|
||||
for _, a := range attrs {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
resp, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages := make([]vdpaNetlinkMessage, 0, len(resp))
|
||||
for _, m := range resp {
|
||||
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, attrs)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
devs := make([]*VDPADev, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
d := &VDPADev{}
|
||||
d.parseAttributes(m)
|
||||
devs = append(devs, d)
|
||||
}
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfgs := make([]*VDPADevConfig, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
cfg := &VDPADevConfig{}
|
||||
cfg.parseAttributes(m)
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
return cfgs, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs,
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(*dev)),
|
||||
)
|
||||
if bus != nil {
|
||||
attrs = append(attrs,
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(*bus)),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfgs := make([]*VDPAMGMTDev, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
cfg := &VDPAMGMTDev{}
|
||||
cfg.parseAttributes(m)
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
return cfgs, nil
|
||||
}
|
||||
|
||||
// VDPANewDev adds new VDPA device
|
||||
// Equivalent to: `vdpa dev add name <name> mgmtdev <mgmtBus>/mgmtName [params]`
|
||||
func (h *Handle) VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
|
||||
attrs := []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(mgmtName)),
|
||||
}
|
||||
if mgmtBus != "" {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(mgmtBus)))
|
||||
}
|
||||
if len(params.MACAddr) != 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MACADDR, params.MACAddr))
|
||||
}
|
||||
if params.MaxVQP > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP, nl.Uint16Attr(params.MaxVQP)))
|
||||
}
|
||||
if params.MTU > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MTU, nl.Uint16Attr(params.MTU)))
|
||||
}
|
||||
if params.Features > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_FEATURES, nl.Uint64Attr(params.Features)))
|
||||
}
|
||||
_, err := h.vdpaRequest(nl.VDPA_CMD_DEV_NEW, 0, attrs)
|
||||
return err
|
||||
}
|
||||
|
||||
// VDPADelDev removes VDPA device
|
||||
// Equivalent to: `vdpa dev del <name>`
|
||||
func (h *Handle) VDPADelDev(name string) error {
|
||||
_, err := h.vdpaRequest(nl.VDPA_CMD_DEV_DEL, 0, []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name))})
|
||||
return err
|
||||
}
|
||||
|
||||
// VDPAGetDevList returns list of VDPA devices
|
||||
// Equivalent to: `vdpa dev show`
|
||||
func (h *Handle) VDPAGetDevList() ([]*VDPADev, error) {
|
||||
return h.vdpaDevGet(nil)
|
||||
}
|
||||
|
||||
// VDPAGetDevByName returns VDPA device selected by name
|
||||
// Equivalent to: `vdpa dev show <name>`
|
||||
func (h *Handle) VDPAGetDevByName(name string) (*VDPADev, error) {
|
||||
devs, err := h.vdpaDevGet(&name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, fmt.Errorf("device not found")
|
||||
}
|
||||
return devs[0], nil
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigList returns list of VDPA devices configurations
|
||||
// Equivalent to: `vdpa dev config show`
|
||||
func (h *Handle) VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
|
||||
return h.vdpaDevConfigGet(nil)
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigByName returns VDPA device configuration selected by name
|
||||
// Equivalent to: `vdpa dev config show <name>`
|
||||
func (h *Handle) VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
|
||||
cfgs, err := h.vdpaDevConfigGet(&name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cfgs) == 0 {
|
||||
return nil, fmt.Errorf("configuration not found")
|
||||
}
|
||||
return cfgs[0], nil
|
||||
}
|
||||
|
||||
// VDPAGetDevVStats returns vstats for VDPA device
|
||||
// Equivalent to: `vdpa dev vstats show <name> qidx <queueIndex>`
|
||||
func (h *Handle) VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_VSTATS_GET, 0, []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_QUEUE_INDEX, nl.Uint32Attr(queueIndex)),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(messages) == 0 {
|
||||
return nil, fmt.Errorf("stats not found")
|
||||
}
|
||||
stats := &VDPADevVStats{}
|
||||
stats.parseAttributes(messages[0])
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevList returns list of mgmt devices
|
||||
// Equivalent to: `vdpa mgmtdev show`
|
||||
func (h *Handle) VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
|
||||
return h.vdpaMGMTDevGet(nil, nil)
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name
|
||||
// Equivalent to: `vdpa mgmtdev show <bus>/<name>`
|
||||
func (h *Handle) VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
|
||||
var busPtr *string
|
||||
if bus != "" {
|
||||
busPtr = &bus
|
||||
}
|
||||
devs, err := h.vdpaMGMTDevGet(busPtr, &name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, fmt.Errorf("mgmtdev not found")
|
||||
}
|
||||
return devs[0], nil
|
||||
}
|
132
vendor/github.com/vishvananda/netlink/virtio.go
generated
vendored
Normal file
132
vendor/github.com/vishvananda/netlink/virtio.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
package netlink
|
||||
|
||||
// features for virtio net
|
||||
const (
|
||||
VIRTIO_NET_F_CSUM = 0 // Host handles pkts w/ partial csum
|
||||
VIRTIO_NET_F_GUEST_CSUM = 1 // Guest handles pkts w/ partial csum
|
||||
VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = 2 // Dynamic offload configuration.
|
||||
VIRTIO_NET_F_MTU = 3 // Initial MTU advice
|
||||
VIRTIO_NET_F_MAC = 5 // Host has given MAC address.
|
||||
VIRTIO_NET_F_GUEST_TSO4 = 7 // Guest can handle TSOv4 in.
|
||||
VIRTIO_NET_F_GUEST_TSO6 = 8 // Guest can handle TSOv6 in.
|
||||
VIRTIO_NET_F_GUEST_ECN = 9 // Guest can handle TSO[6] w/ ECN in.
|
||||
VIRTIO_NET_F_GUEST_UFO = 10 // Guest can handle UFO in.
|
||||
VIRTIO_NET_F_HOST_TSO4 = 11 // Host can handle TSOv4 in.
|
||||
VIRTIO_NET_F_HOST_TSO6 = 12 // Host can handle TSOv6 in.
|
||||
VIRTIO_NET_F_HOST_ECN = 13 // Host can handle TSO[6] w/ ECN in.
|
||||
VIRTIO_NET_F_HOST_UFO = 14 // Host can handle UFO in.
|
||||
VIRTIO_NET_F_MRG_RXBUF = 15 // Host can merge receive buffers.
|
||||
VIRTIO_NET_F_STATUS = 16 // virtio_net_config.status available
|
||||
VIRTIO_NET_F_CTRL_VQ = 17 // Control channel available
|
||||
VIRTIO_NET_F_CTRL_RX = 18 // Control channel RX mode support
|
||||
VIRTIO_NET_F_CTRL_VLAN = 19 // Control channel VLAN filtering
|
||||
VIRTIO_NET_F_CTRL_RX_EXTRA = 20 // Extra RX mode control support
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE = 21 // Guest can announce device on the* network
|
||||
VIRTIO_NET_F_MQ = 22 // Device supports Receive Flow Steering
|
||||
VIRTIO_NET_F_CTRL_MAC_ADDR = 23 // Set MAC address
|
||||
VIRTIO_NET_F_VQ_NOTF_COAL = 52 // Device supports virtqueue notification coalescing
|
||||
VIRTIO_NET_F_NOTF_COAL = 53 // Device supports notifications coalescing
|
||||
VIRTIO_NET_F_GUEST_USO4 = 54 // Guest can handle USOv4 in.
|
||||
VIRTIO_NET_F_GUEST_USO6 = 55 // Guest can handle USOv6 in.
|
||||
VIRTIO_NET_F_HOST_USO = 56 // Host can handle USO in.
|
||||
VIRTIO_NET_F_HASH_REPORT = 57 // Supports hash report
|
||||
VIRTIO_NET_F_GUEST_HDRLEN = 59 // Guest provides the exact hdr_len value.
|
||||
VIRTIO_NET_F_RSS = 60 // Supports RSS RX steering
|
||||
VIRTIO_NET_F_RSC_EXT = 61 // extended coalescing info
|
||||
VIRTIO_NET_F_STANDBY = 62 // Act as standby for another device with the same MAC.
|
||||
VIRTIO_NET_F_SPEED_DUPLEX = 63 // Device set linkspeed and duplex
|
||||
VIRTIO_NET_F_GSO = 6 // Host handles pkts any GSO type
|
||||
)
|
||||
|
||||
// virtio net status
|
||||
const (
|
||||
VIRTIO_NET_S_LINK_UP = 1 // Link is up
|
||||
VIRTIO_NET_S_ANNOUNCE = 2 // Announcement is needed
|
||||
)
|
||||
|
||||
// virtio config
|
||||
const (
|
||||
// Do we get callbacks when the ring is completely used, even if we've
|
||||
// suppressed them?
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY = 24
|
||||
// Can the device handle any descriptor layout?
|
||||
VIRTIO_F_ANY_LAYOUT = 27
|
||||
// v1.0 compliant
|
||||
VIRTIO_F_VERSION_1 = 32
|
||||
// If clear - device has the platform DMA (e.g. IOMMU) bypass quirk feature.
|
||||
// If set - use platform DMA tools to access the memory.
|
||||
// Note the reverse polarity (compared to most other features),
|
||||
// this is for compatibility with legacy systems.
|
||||
VIRTIO_F_ACCESS_PLATFORM = 33
|
||||
// Legacy name for VIRTIO_F_ACCESS_PLATFORM (for compatibility with old userspace)
|
||||
VIRTIO_F_IOMMU_PLATFORM = VIRTIO_F_ACCESS_PLATFORM
|
||||
// This feature indicates support for the packed virtqueue layout.
|
||||
VIRTIO_F_RING_PACKED = 34
|
||||
// Inorder feature indicates that all buffers are used by the device
|
||||
// in the same order in which they have been made available.
|
||||
VIRTIO_F_IN_ORDER = 35
|
||||
// This feature indicates that memory accesses by the driver and the
|
||||
// device are ordered in a way described by the platform.
|
||||
VIRTIO_F_ORDER_PLATFORM = 36
|
||||
// Does the device support Single Root I/O Virtualization?
|
||||
VIRTIO_F_SR_IOV = 37
|
||||
// This feature indicates that the driver passes extra data (besides
|
||||
// identifying the virtqueue) in its device notifications.
|
||||
VIRTIO_F_NOTIFICATION_DATA = 38
|
||||
// This feature indicates that the driver uses the data provided by the device
|
||||
// as a virtqueue identifier in available buffer notifications.
|
||||
VIRTIO_F_NOTIF_CONFIG_DATA = 39
|
||||
// This feature indicates that the driver can reset a queue individually.
|
||||
VIRTIO_F_RING_RESET = 40
|
||||
)
|
||||
|
||||
// virtio device ids
|
||||
const (
|
||||
VIRTIO_ID_NET = 1 // virtio net
|
||||
VIRTIO_ID_BLOCK = 2 // virtio block
|
||||
VIRTIO_ID_CONSOLE = 3 // virtio console
|
||||
VIRTIO_ID_RNG = 4 // virtio rng
|
||||
VIRTIO_ID_BALLOON = 5 // virtio balloon
|
||||
VIRTIO_ID_IOMEM = 6 // virtio ioMemory
|
||||
VIRTIO_ID_RPMSG = 7 // virtio remote processor messaging
|
||||
VIRTIO_ID_SCSI = 8 // virtio scsi
|
||||
VIRTIO_ID_9P = 9 // 9p virtio console
|
||||
VIRTIO_ID_MAC80211_WLAN = 10 // virtio WLAN MAC
|
||||
VIRTIO_ID_RPROC_SERIAL = 11 // virtio remoteproc serial link
|
||||
VIRTIO_ID_CAIF = 12 // Virtio caif
|
||||
VIRTIO_ID_MEMORY_BALLOON = 13 // virtio memory balloon
|
||||
VIRTIO_ID_GPU = 16 // virtio GPU
|
||||
VIRTIO_ID_CLOCK = 17 // virtio clock/timer
|
||||
VIRTIO_ID_INPUT = 18 // virtio input
|
||||
VIRTIO_ID_VSOCK = 19 // virtio vsock transport
|
||||
VIRTIO_ID_CRYPTO = 20 // virtio crypto
|
||||
VIRTIO_ID_SIGNAL_DIST = 21 // virtio signal distribution device
|
||||
VIRTIO_ID_PSTORE = 22 // virtio pstore device
|
||||
VIRTIO_ID_IOMMU = 23 // virtio IOMMU
|
||||
VIRTIO_ID_MEM = 24 // virtio mem
|
||||
VIRTIO_ID_SOUND = 25 // virtio sound
|
||||
VIRTIO_ID_FS = 26 // virtio filesystem
|
||||
VIRTIO_ID_PMEM = 27 // virtio pmem
|
||||
VIRTIO_ID_RPMB = 28 // virtio rpmb
|
||||
VIRTIO_ID_MAC80211_HWSIM = 29 // virtio mac80211-hwsim
|
||||
VIRTIO_ID_VIDEO_ENCODER = 30 // virtio video encoder
|
||||
VIRTIO_ID_VIDEO_DECODER = 31 // virtio video decoder
|
||||
VIRTIO_ID_SCMI = 32 // virtio SCMI
|
||||
VIRTIO_ID_NITRO_SEC_MOD = 33 // virtio nitro secure module
|
||||
VIRTIO_ID_I2C_ADAPTER = 34 // virtio i2c adapter
|
||||
VIRTIO_ID_WATCHDOG = 35 // virtio watchdog
|
||||
VIRTIO_ID_CAN = 36 // virtio can
|
||||
VIRTIO_ID_DMABUF = 37 // virtio dmabuf
|
||||
VIRTIO_ID_PARAM_SERV = 38 // virtio parameter server
|
||||
VIRTIO_ID_AUDIO_POLICY = 39 // virtio audio policy
|
||||
VIRTIO_ID_BT = 40 // virtio bluetooth
|
||||
VIRTIO_ID_GPIO = 41 // virtio gpio
|
||||
// Virtio Transitional IDs
|
||||
VIRTIO_TRANS_ID_NET = 0x1000 // transitional virtio net
|
||||
VIRTIO_TRANS_ID_BLOCK = 0x1001 // transitional virtio block
|
||||
VIRTIO_TRANS_ID_BALLOON = 0x1002 // transitional virtio balloon
|
||||
VIRTIO_TRANS_ID_CONSOLE = 0x1003 // transitional virtio console
|
||||
VIRTIO_TRANS_ID_SCSI = 0x1004 // transitional virtio SCSI
|
||||
VIRTIO_TRANS_ID_RNG = 0x1005 // transitional virtio rng
|
||||
VIRTIO_TRANS_ID_9P = 0x1009 // transitional virtio 9p console
|
||||
)
|
34
vendor/github.com/vishvananda/netlink/xdp_diag.go
generated
vendored
Normal file
34
vendor/github.com/vishvananda/netlink/xdp_diag.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink/nl"
|
||||
|
||||
const SOCK_ANY_COOKIE = uint64(nl.TCPDIAG_NOCOOKIE)<<32 + uint64(nl.TCPDIAG_NOCOOKIE)
|
||||
|
||||
// XDP diagnosis show flag constants to request particular information elements.
|
||||
const (
|
||||
XDP_SHOW_INFO = 1 << iota
|
||||
XDP_SHOW_RING_CFG
|
||||
XDP_SHOW_UMEM
|
||||
XDP_SHOW_MEMINFO
|
||||
XDP_SHOW_STATS
|
||||
)
|
||||
|
||||
// XDP diag element constants
|
||||
const (
|
||||
XDP_DIAG_NONE = iota
|
||||
XDP_DIAG_INFO // when using XDP_SHOW_INFO
|
||||
XDP_DIAG_UID // when using XDP_SHOW_INFO
|
||||
XDP_DIAG_RX_RING // when using XDP_SHOW_RING_CFG
|
||||
XDP_DIAG_TX_RING // when using XDP_SHOW_RING_CFG
|
||||
XDP_DIAG_UMEM // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_UMEM_FILL_RING // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_UMEM_COMPLETION_RING // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_MEMINFO // when using XDP_SHOW_MEMINFO
|
||||
XDP_DIAG_STATS // when using XDP_SHOW_STATS
|
||||
)
|
||||
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
|
||||
type XDPDiagInfoResp struct {
|
||||
XDPDiagMsg *XDPSocket
|
||||
XDPInfo *XDPInfo
|
||||
}
|
46
vendor/github.com/vishvananda/netlink/xdp_linux.go
generated
vendored
Normal file
46
vendor/github.com/vishvananda/netlink/xdp_linux.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
xdrDiagUmemLen = 8 + 8*4
|
||||
xdrDiagStatsLen = 6 * 8
|
||||
)
|
||||
|
||||
func (x *XDPDiagUmem) deserialize(b []byte) error {
|
||||
if len(b) < xdrDiagUmemLen {
|
||||
return fmt.Errorf("XDP umem diagnosis data short read (%d); want %d", len(b), xdrDiagUmemLen)
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
x.Size = native.Uint64(rb.Next(8))
|
||||
x.ID = native.Uint32(rb.Next(4))
|
||||
x.NumPages = native.Uint32(rb.Next(4))
|
||||
x.ChunkSize = native.Uint32(rb.Next(4))
|
||||
x.Headroom = native.Uint32(rb.Next(4))
|
||||
x.Ifindex = native.Uint32(rb.Next(4))
|
||||
x.QueueID = native.Uint32(rb.Next(4))
|
||||
x.Flags = native.Uint32(rb.Next(4))
|
||||
x.Refs = native.Uint32(rb.Next(4))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *XDPDiagStats) deserialize(b []byte) error {
|
||||
if len(b) < xdrDiagStatsLen {
|
||||
return fmt.Errorf("XDP diagnosis statistics short read (%d); want %d", len(b), xdrDiagStatsLen)
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
x.RxDropped = native.Uint64(rb.Next(8))
|
||||
x.RxInvalid = native.Uint64(rb.Next(8))
|
||||
x.RxFull = native.Uint64(rb.Next(8))
|
||||
x.FillRingEmpty = native.Uint64(rb.Next(8))
|
||||
x.TxInvalid = native.Uint64(rb.Next(8))
|
||||
x.TxRingEmpty = native.Uint64(rb.Next(8))
|
||||
|
||||
return nil
|
||||
}
|
@ -14,7 +14,7 @@ const (
|
||||
XFRM_PROTO_ESP Proto = unix.IPPROTO_ESP
|
||||
XFRM_PROTO_AH Proto = unix.IPPROTO_AH
|
||||
XFRM_PROTO_HAO Proto = unix.IPPROTO_DSTOPTS
|
||||
XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin
|
||||
XFRM_PROTO_COMP Proto = unix.IPPROTO_COMP
|
||||
XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW
|
||||
)
|
||||
|
97
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
97
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
@ -1,97 +0,0 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Dir is an enum representing an ipsec template direction.
|
||||
type Dir uint8
|
||||
|
||||
const (
|
||||
XFRM_DIR_IN Dir = iota
|
||||
XFRM_DIR_OUT
|
||||
XFRM_DIR_FWD
|
||||
XFRM_SOCKET_IN
|
||||
XFRM_SOCKET_OUT
|
||||
XFRM_SOCKET_FWD
|
||||
)
|
||||
|
||||
func (d Dir) String() string {
|
||||
switch d {
|
||||
case XFRM_DIR_IN:
|
||||
return "dir in"
|
||||
case XFRM_DIR_OUT:
|
||||
return "dir out"
|
||||
case XFRM_DIR_FWD:
|
||||
return "dir fwd"
|
||||
case XFRM_SOCKET_IN:
|
||||
return "socket in"
|
||||
case XFRM_SOCKET_OUT:
|
||||
return "socket out"
|
||||
case XFRM_SOCKET_FWD:
|
||||
return "socket fwd"
|
||||
}
|
||||
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
|
||||
}
|
||||
|
||||
// PolicyAction is an enum representing an ipsec policy action.
|
||||
type PolicyAction uint8
|
||||
|
||||
const (
|
||||
XFRM_POLICY_ALLOW PolicyAction = 0
|
||||
XFRM_POLICY_BLOCK PolicyAction = 1
|
||||
)
|
||||
|
||||
func (a PolicyAction) String() string {
|
||||
switch a {
|
||||
case XFRM_POLICY_ALLOW:
|
||||
return "allow"
|
||||
case XFRM_POLICY_BLOCK:
|
||||
return "block"
|
||||
default:
|
||||
return fmt.Sprintf("action %d", a)
|
||||
}
|
||||
}
|
||||
|
||||
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
|
||||
// policy. These rules are matched with XfrmState to determine encryption
|
||||
// and authentication algorithms.
|
||||
type XfrmPolicyTmpl struct {
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Proto Proto
|
||||
Mode Mode
|
||||
Spi int
|
||||
Reqid int
|
||||
Optional int
|
||||
}
|
||||
|
||||
func (t XfrmPolicyTmpl) String() string {
|
||||
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}",
|
||||
t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid)
|
||||
}
|
||||
|
||||
// XfrmPolicy represents an ipsec policy. It represents the overlay network
|
||||
// and has a list of XfrmPolicyTmpls representing the base addresses of
|
||||
// the policy.
|
||||
type XfrmPolicy struct {
|
||||
Dst *net.IPNet
|
||||
Src *net.IPNet
|
||||
Proto Proto
|
||||
DstPort int
|
||||
SrcPort int
|
||||
Dir Dir
|
||||
Priority int
|
||||
Index int
|
||||
Action PolicyAction
|
||||
Ifindex int
|
||||
Ifid int
|
||||
Mark *XfrmMark
|
||||
Tmpls []XfrmPolicyTmpl
|
||||
}
|
||||
|
||||
func (p XfrmPolicy) String() string {
|
||||
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}",
|
||||
p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls)
|
||||
}
|
99
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
99
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
@ -1,10 +1,104 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Dir is an enum representing an ipsec template direction.
|
||||
type Dir uint8
|
||||
|
||||
const (
|
||||
XFRM_DIR_IN Dir = iota
|
||||
XFRM_DIR_OUT
|
||||
XFRM_DIR_FWD
|
||||
XFRM_SOCKET_IN
|
||||
XFRM_SOCKET_OUT
|
||||
XFRM_SOCKET_FWD
|
||||
)
|
||||
|
||||
func (d Dir) String() string {
|
||||
switch d {
|
||||
case XFRM_DIR_IN:
|
||||
return "dir in"
|
||||
case XFRM_DIR_OUT:
|
||||
return "dir out"
|
||||
case XFRM_DIR_FWD:
|
||||
return "dir fwd"
|
||||
case XFRM_SOCKET_IN:
|
||||
return "socket in"
|
||||
case XFRM_SOCKET_OUT:
|
||||
return "socket out"
|
||||
case XFRM_SOCKET_FWD:
|
||||
return "socket fwd"
|
||||
}
|
||||
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
|
||||
}
|
||||
|
||||
// PolicyAction is an enum representing an ipsec policy action.
|
||||
type PolicyAction uint8
|
||||
|
||||
const (
|
||||
XFRM_POLICY_ALLOW PolicyAction = 0
|
||||
XFRM_POLICY_BLOCK PolicyAction = 1
|
||||
)
|
||||
|
||||
func (a PolicyAction) String() string {
|
||||
switch a {
|
||||
case XFRM_POLICY_ALLOW:
|
||||
return "allow"
|
||||
case XFRM_POLICY_BLOCK:
|
||||
return "block"
|
||||
default:
|
||||
return fmt.Sprintf("action %d", a)
|
||||
}
|
||||
}
|
||||
|
||||
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
|
||||
// policy. These rules are matched with XfrmState to determine encryption
|
||||
// and authentication algorithms.
|
||||
type XfrmPolicyTmpl struct {
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Proto Proto
|
||||
Mode Mode
|
||||
Spi int
|
||||
Reqid int
|
||||
Optional int
|
||||
}
|
||||
|
||||
func (t XfrmPolicyTmpl) String() string {
|
||||
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}",
|
||||
t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid)
|
||||
}
|
||||
|
||||
// XfrmPolicy represents an ipsec policy. It represents the overlay network
|
||||
// and has a list of XfrmPolicyTmpls representing the base addresses of
|
||||
// the policy.
|
||||
type XfrmPolicy struct {
|
||||
Dst *net.IPNet
|
||||
Src *net.IPNet
|
||||
Proto Proto
|
||||
DstPort int
|
||||
SrcPort int
|
||||
Dir Dir
|
||||
Priority int
|
||||
Index int
|
||||
Action PolicyAction
|
||||
Ifindex int
|
||||
Ifid int
|
||||
Mark *XfrmMark
|
||||
Tmpls []XfrmPolicyTmpl
|
||||
}
|
||||
|
||||
func (p XfrmPolicy) String() string {
|
||||
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}",
|
||||
p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls)
|
||||
}
|
||||
|
||||
func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
||||
sel.Family = uint16(nl.FAMILY_V4)
|
||||
if policy.Dst != nil {
|
||||
@ -75,6 +169,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
||||
userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
|
||||
userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
|
||||
userTmpl.Saddr.FromIP(tmpl.Src)
|
||||
userTmpl.Family = uint16(nl.GetIPFamily(tmpl.Dst))
|
||||
userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
|
||||
userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
|
||||
userTmpl.Mode = uint8(tmpl.Mode)
|
||||
@ -223,8 +318,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
||||
|
||||
var policy XfrmPolicy
|
||||
|
||||
policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
|
||||
policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
|
||||
policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, uint16(family))
|
||||
policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, uint16(family))
|
||||
policy.Proto = Proto(msg.Sel.Proto)
|
||||
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
||||
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
||||
|
131
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
131
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
@ -1,131 +0,0 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
|
||||
type XfrmStateAlgo struct {
|
||||
Name string
|
||||
Key []byte
|
||||
TruncateLen int // Auth only
|
||||
ICVLen int // AEAD only
|
||||
}
|
||||
|
||||
func (a XfrmStateAlgo) String() string {
|
||||
base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key)
|
||||
if a.TruncateLen != 0 {
|
||||
base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen)
|
||||
}
|
||||
if a.ICVLen != 0 {
|
||||
base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen)
|
||||
}
|
||||
return fmt.Sprintf("%s}", base)
|
||||
}
|
||||
|
||||
// EncapType is an enum representing the optional packet encapsulation.
|
||||
type EncapType uint8
|
||||
|
||||
const (
|
||||
XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1
|
||||
XFRM_ENCAP_ESPINUDP
|
||||
)
|
||||
|
||||
func (e EncapType) String() string {
|
||||
switch e {
|
||||
case XFRM_ENCAP_ESPINUDP_NONIKE:
|
||||
return "espinudp-non-ike"
|
||||
case XFRM_ENCAP_ESPINUDP:
|
||||
return "espinudp"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// XfrmStateEncap represents the encapsulation to use for the ipsec encryption.
|
||||
type XfrmStateEncap struct {
|
||||
Type EncapType
|
||||
SrcPort int
|
||||
DstPort int
|
||||
OriginalAddress net.IP
|
||||
}
|
||||
|
||||
func (e XfrmStateEncap) String() string {
|
||||
return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}",
|
||||
e.Type, e.SrcPort, e.DstPort, e.OriginalAddress)
|
||||
}
|
||||
|
||||
// XfrmStateLimits represents the configured limits for the state.
|
||||
type XfrmStateLimits struct {
|
||||
ByteSoft uint64
|
||||
ByteHard uint64
|
||||
PacketSoft uint64
|
||||
PacketHard uint64
|
||||
TimeSoft uint64
|
||||
TimeHard uint64
|
||||
TimeUseSoft 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
|
||||
// contains an XfrmStateAlgo for encryption and one for authentication.
|
||||
type XfrmState struct {
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Proto Proto
|
||||
Mode Mode
|
||||
Spi int
|
||||
Reqid int
|
||||
ReplayWindow int
|
||||
Limits XfrmStateLimits
|
||||
Statistics XfrmStateStats
|
||||
Mark *XfrmMark
|
||||
OutputMark *XfrmMark
|
||||
Ifid int
|
||||
Auth *XfrmStateAlgo
|
||||
Crypt *XfrmStateAlgo
|
||||
Aead *XfrmStateAlgo
|
||||
Encap *XfrmStateEncap
|
||||
ESN bool
|
||||
}
|
||||
|
||||
func (sa XfrmState) String() string {
|
||||
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
|
||||
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
|
||||
}
|
||||
func (sa XfrmState) Print(stats bool) string {
|
||||
if !stats {
|
||||
return sa.String()
|
||||
}
|
||||
at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate)
|
||||
ut := "-"
|
||||
if sa.Statistics.UseTime > 0 {
|
||||
ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate)
|
||||
}
|
||||
return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+
|
||||
"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d",
|
||||
sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
|
||||
sa.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 {
|
||||
if lmt == ^uint64(0) {
|
||||
return "(INF)"
|
||||
}
|
||||
return fmt.Sprintf("%d", lmt)
|
||||
}
|
199
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
199
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
@ -2,12 +2,154 @@ package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
|
||||
type XfrmStateAlgo struct {
|
||||
Name string
|
||||
Key []byte
|
||||
TruncateLen int // Auth only
|
||||
ICVLen int // AEAD only
|
||||
}
|
||||
|
||||
func (a XfrmStateAlgo) String() string {
|
||||
base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key)
|
||||
if a.TruncateLen != 0 {
|
||||
base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen)
|
||||
}
|
||||
if a.ICVLen != 0 {
|
||||
base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen)
|
||||
}
|
||||
return fmt.Sprintf("%s}", base)
|
||||
}
|
||||
|
||||
// EncapType is an enum representing the optional packet encapsulation.
|
||||
type EncapType uint8
|
||||
|
||||
const (
|
||||
XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1
|
||||
XFRM_ENCAP_ESPINUDP
|
||||
)
|
||||
|
||||
func (e EncapType) String() string {
|
||||
switch e {
|
||||
case XFRM_ENCAP_ESPINUDP_NONIKE:
|
||||
return "espinudp-non-ike"
|
||||
case XFRM_ENCAP_ESPINUDP:
|
||||
return "espinudp"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// XfrmStateEncap represents the encapsulation to use for the ipsec encryption.
|
||||
type XfrmStateEncap struct {
|
||||
Type EncapType
|
||||
SrcPort int
|
||||
DstPort int
|
||||
OriginalAddress net.IP
|
||||
}
|
||||
|
||||
func (e XfrmStateEncap) String() string {
|
||||
return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}",
|
||||
e.Type, e.SrcPort, e.DstPort, e.OriginalAddress)
|
||||
}
|
||||
|
||||
// XfrmStateLimits represents the configured limits for the state.
|
||||
type XfrmStateLimits struct {
|
||||
ByteSoft uint64
|
||||
ByteHard uint64
|
||||
PacketSoft uint64
|
||||
PacketHard uint64
|
||||
TimeSoft uint64
|
||||
TimeHard uint64
|
||||
TimeUseSoft 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
|
||||
}
|
||||
|
||||
// XfrmReplayState represents the sequence number states for
|
||||
// "legacy" anti-replay mode.
|
||||
type XfrmReplayState struct {
|
||||
OSeq uint32
|
||||
Seq uint32
|
||||
BitMap uint32
|
||||
}
|
||||
|
||||
func (r XfrmReplayState) String() string {
|
||||
return fmt.Sprintf("{OSeq: 0x%x, Seq: 0x%x, BitMap: 0x%x}",
|
||||
r.OSeq, r.Seq, r.BitMap)
|
||||
}
|
||||
|
||||
// XfrmState represents the state of an ipsec policy. It optionally
|
||||
// contains an XfrmStateAlgo for encryption and one for authentication.
|
||||
type XfrmState struct {
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Proto Proto
|
||||
Mode Mode
|
||||
Spi int
|
||||
Reqid int
|
||||
ReplayWindow int
|
||||
Limits XfrmStateLimits
|
||||
Statistics XfrmStateStats
|
||||
Mark *XfrmMark
|
||||
OutputMark *XfrmMark
|
||||
Ifid int
|
||||
Auth *XfrmStateAlgo
|
||||
Crypt *XfrmStateAlgo
|
||||
Aead *XfrmStateAlgo
|
||||
Encap *XfrmStateEncap
|
||||
ESN bool
|
||||
DontEncapDSCP bool
|
||||
OSeqMayWrap bool
|
||||
Replay *XfrmReplayState
|
||||
Selector *XfrmPolicy
|
||||
}
|
||||
|
||||
func (sa XfrmState) String() string {
|
||||
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v",
|
||||
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay)
|
||||
}
|
||||
func (sa XfrmState) Print(stats bool) string {
|
||||
if !stats {
|
||||
return sa.String()
|
||||
}
|
||||
at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate)
|
||||
ut := "-"
|
||||
if sa.Statistics.UseTime > 0 {
|
||||
ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate)
|
||||
}
|
||||
return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+
|
||||
"AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d",
|
||||
sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard),
|
||||
sa.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 {
|
||||
if lmt == ^uint64(0) {
|
||||
return "(INF)"
|
||||
}
|
||||
return fmt.Sprintf("%d", lmt)
|
||||
}
|
||||
func writeStateAlgo(a *XfrmStateAlgo) []byte {
|
||||
algo := nl.XfrmAlgo{
|
||||
AlgKeyLen: uint32(len(a.Key) * 8),
|
||||
@ -77,6 +219,14 @@ func writeReplayEsn(replayWindow int) []byte {
|
||||
return replayEsn.Serialize()
|
||||
}
|
||||
|
||||
func writeReplay(r *XfrmReplayState) []byte {
|
||||
return (&nl.XfrmReplayState{
|
||||
OSeq: r.OSeq,
|
||||
Seq: r.Seq,
|
||||
BitMap: r.BitMap,
|
||||
}).Serialize()
|
||||
}
|
||||
|
||||
// XfrmStateAdd will add an xfrm state to the system.
|
||||
// Equivalent to: `ip xfrm state add $state`
|
||||
func XfrmStateAdd(state *XfrmState) error {
|
||||
@ -166,6 +316,21 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
||||
req.AddData(out)
|
||||
}
|
||||
}
|
||||
if state.OSeqMayWrap || state.DontEncapDSCP {
|
||||
var flags uint32
|
||||
if state.DontEncapDSCP {
|
||||
flags |= nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP
|
||||
}
|
||||
if state.OSeqMayWrap {
|
||||
flags |= nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP
|
||||
}
|
||||
out := nl.NewRtAttr(nl.XFRMA_SA_EXTRA_FLAGS, nl.Uint32Attr(flags))
|
||||
req.AddData(out)
|
||||
}
|
||||
if state.Replay != nil {
|
||||
out := nl.NewRtAttr(nl.XFRMA_REPLAY_VAL, writeReplay(state.Replay))
|
||||
req.AddData(out)
|
||||
}
|
||||
|
||||
if state.Ifid != 0 {
|
||||
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
|
||||
@ -186,7 +351,6 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
||||
msg.Min = 0x100
|
||||
msg.Max = 0xffffffff
|
||||
req.AddData(msg)
|
||||
|
||||
if state.Mark != nil {
|
||||
out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark))
|
||||
req.AddData(out)
|
||||
@ -314,7 +478,6 @@ var familyError = fmt.Errorf("family error")
|
||||
|
||||
func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
|
||||
var state XfrmState
|
||||
|
||||
state.Dst = msg.Id.Daddr.ToIP()
|
||||
state.Src = msg.Saddr.ToIP()
|
||||
state.Proto = Proto(msg.Id.Proto)
|
||||
@ -324,20 +487,25 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
|
||||
state.ReplayWindow = int(msg.ReplayWindow)
|
||||
lftToLimits(&msg.Lft, &state.Limits)
|
||||
curToStats(&msg.Curlft, &msg.Stats, &state.Statistics)
|
||||
state.Selector = &XfrmPolicy{
|
||||
Dst: msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, msg.Sel.Family),
|
||||
Src: msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, msg.Sel.Family),
|
||||
Proto: Proto(msg.Sel.Proto),
|
||||
DstPort: int(nl.Swap16(msg.Sel.Dport)),
|
||||
SrcPort: int(nl.Swap16(msg.Sel.Sport)),
|
||||
Ifindex: int(msg.Sel.Ifindex),
|
||||
}
|
||||
|
||||
return &state
|
||||
}
|
||||
|
||||
func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||
msg := nl.DeserializeXfrmUsersaInfo(m)
|
||||
|
||||
// This is mainly for the state dump
|
||||
if family != FAMILY_ALL && family != int(msg.Family) {
|
||||
return nil, familyError
|
||||
}
|
||||
|
||||
state := xfrmStateFromXfrmUsersaInfo(msg)
|
||||
|
||||
attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -385,6 +553,14 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||
state.Mark = new(XfrmMark)
|
||||
state.Mark.Value = mark.Value
|
||||
state.Mark.Mask = mark.Mask
|
||||
case nl.XFRMA_SA_EXTRA_FLAGS:
|
||||
flags := native.Uint32(attr.Value)
|
||||
if (flags & nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP) != 0 {
|
||||
state.DontEncapDSCP = true
|
||||
}
|
||||
if (flags & nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP) != 0 {
|
||||
state.OSeqMayWrap = true
|
||||
}
|
||||
case nl.XFRMA_SET_MARK:
|
||||
if state.OutputMark == nil {
|
||||
state.OutputMark = new(XfrmMark)
|
||||
@ -400,6 +576,14 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||
}
|
||||
case nl.XFRMA_IF_ID:
|
||||
state.Ifid = int(native.Uint32(attr.Value))
|
||||
case nl.XFRMA_REPLAY_VAL:
|
||||
if state.Replay == nil {
|
||||
state.Replay = new(XfrmReplayState)
|
||||
}
|
||||
replay := nl.DeserializeXfrmReplayState(attr.Value[:])
|
||||
state.Replay.OSeq = replay.OSeq
|
||||
state.Replay.Seq = replay.Seq
|
||||
state.Replay.BitMap = replay.BitMap
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,6 +660,9 @@ func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
|
||||
msg.Id.Spi = nl.Swap32(uint32(state.Spi))
|
||||
msg.Reqid = uint32(state.Reqid)
|
||||
msg.ReplayWindow = uint8(state.ReplayWindow)
|
||||
|
||||
msg.Sel = nl.XfrmSelector{}
|
||||
if state.Selector != nil {
|
||||
selFromPolicy(&msg.Sel, state.Selector)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
7
vendor/github.com/vishvananda/netlink/xfrm_unspecified.go
generated
vendored
Normal file
7
vendor/github.com/vishvananda/netlink/xfrm_unspecified.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package netlink
|
||||
|
||||
type XfrmPolicy struct{}
|
||||
type XfrmState struct{}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -165,7 +165,7 @@ github.com/safchain/ethtool
|
||||
# github.com/sirupsen/logrus v1.9.3
|
||||
## explicit; go 1.13
|
||||
github.com/sirupsen/logrus
|
||||
# github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
# github.com/vishvananda/netlink v1.3.0
|
||||
## explicit; go 1.12
|
||||
github.com/vishvananda/netlink
|
||||
github.com/vishvananda/netlink/nl
|
||||
|
Loading…
x
Reference in New Issue
Block a user