mirror of https://github.com/containers/podman.git
fix(deps): update module github.com/vishvananda/netlink to v1.3.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
parent
811aabd3b0
commit
a5748206d1
2
go.mod
2
go.mod
|
@ -66,7 +66,7 @@ require (
|
||||||
github.com/spf13/pflag v1.0.6
|
github.com/spf13/pflag v1.0.6
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/vbauerster/mpb/v8 v8.10.0
|
github.com/vbauerster/mpb/v8 v8.10.0
|
||||||
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9
|
github.com/vishvananda/netlink v1.3.1
|
||||||
go.etcd.io/bbolt v1.4.0
|
go.etcd.io/bbolt v1.4.0
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.38.0
|
||||||
golang.org/x/net v0.40.0
|
golang.org/x/net v0.40.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -482,8 +482,8 @@ github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnn
|
||||||
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||||
github.com/vbauerster/mpb/v8 v8.10.0 h1:5ZYEWM4ovaZGAibjzW4PlQNb5k+JpzMqVwgNyk+K0M8=
|
github.com/vbauerster/mpb/v8 v8.10.0 h1:5ZYEWM4ovaZGAibjzW4PlQNb5k+JpzMqVwgNyk+K0M8=
|
||||||
github.com/vbauerster/mpb/v8 v8.10.0/go.mod h1:DYPFebxSahB+f7tuEUGauLQ7w8ij3wMr4clsVuJCV4I=
|
github.com/vbauerster/mpb/v8 v8.10.0/go.mod h1:DYPFebxSahB+f7tuEUGauLQ7w8ij3wMr4clsVuJCV4I=
|
||||||
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9 h1:ZEjCI2kamoTYIx348/Nfco4c4NPvpq972DM2HMgnBgI=
|
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
||||||
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
||||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||||
|
|
|
@ -3,11 +3,102 @@ package netlink
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BridgeVlanTunnelShow gets vlanid-tunnelid mapping.
|
||||||
|
// Equivalent to: `bridge vlan tunnelshow`
|
||||||
|
//
|
||||||
|
// If the returned error is [ErrDumpInterrupted], results may be inconsistent
|
||||||
|
// or incomplete.
|
||||||
|
func BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) {
|
||||||
|
return pkgHandle.BridgeVlanTunnelShow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) {
|
||||||
|
req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
|
||||||
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
||||||
|
req.AddData(msg)
|
||||||
|
req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
|
||||||
|
|
||||||
|
msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
|
||||||
|
if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
|
||||||
|
return nil, executeErr
|
||||||
|
}
|
||||||
|
ret := make([]nl.TunnelInfo, 0)
|
||||||
|
for _, m := range msgs {
|
||||||
|
msg := nl.DeserializeIfInfomsg(m)
|
||||||
|
|
||||||
|
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, attr := range attrs {
|
||||||
|
switch attr.Attr.Type {
|
||||||
|
case unix.IFLA_AF_SPEC:
|
||||||
|
nestedAttrs, err := nl.ParseRouteAttr(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse nested attr %v", err)
|
||||||
|
}
|
||||||
|
for _, nestAttr := range nestedAttrs {
|
||||||
|
switch nestAttr.Attr.Type {
|
||||||
|
case nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO:
|
||||||
|
ret, err = parseTunnelInfo(&nestAttr, ret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse tunnelinfo %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, executeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTunnelInfo(nestAttr *syscall.NetlinkRouteAttr, results []nl.TunnelInfo) ([]nl.TunnelInfo, error) {
|
||||||
|
tunnelInfos, err := nl.ParseRouteAttr(nestAttr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse nested attr %v", err)
|
||||||
|
}
|
||||||
|
var tunnelId uint32
|
||||||
|
var vid uint16
|
||||||
|
var flag uint16
|
||||||
|
for _, tunnelInfo := range tunnelInfos {
|
||||||
|
switch tunnelInfo.Attr.Type {
|
||||||
|
case nl.IFLA_BRIDGE_VLAN_TUNNEL_ID:
|
||||||
|
tunnelId = native.Uint32(tunnelInfo.Value)
|
||||||
|
case nl.IFLA_BRIDGE_VLAN_TUNNEL_VID:
|
||||||
|
vid = native.Uint16(tunnelInfo.Value)
|
||||||
|
case nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS:
|
||||||
|
flag = native.Uint16(tunnelInfo.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag == nl.BRIDGE_VLAN_INFO_RANGE_END {
|
||||||
|
lastTi := results[len(results)-1]
|
||||||
|
vni := lastTi.TunId + 1
|
||||||
|
for i := lastTi.Vid + 1; i < vid; i++ {
|
||||||
|
t := nl.TunnelInfo{
|
||||||
|
TunId: vni,
|
||||||
|
Vid: i,
|
||||||
|
}
|
||||||
|
results = append(results, t)
|
||||||
|
vni++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t := nl.TunnelInfo{
|
||||||
|
TunId: tunnelId,
|
||||||
|
Vid: vid,
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, t)
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
||||||
// Equivalent to: `bridge vlan show`
|
// Equivalent to: `bridge vlan show`
|
||||||
//
|
//
|
||||||
|
@ -61,6 +152,38 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
||||||
return ret, executeErr
|
return ret, executeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BridgeVlanAddTunnelInfo adds a new vlan filter entry
|
||||||
|
// Equivalent to: `bridge vlan add dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
|
||||||
|
func BridgeVlanAddTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error {
|
||||||
|
return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, 0, tunid, 0, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BridgeVlanAddRangeTunnelInfoRange adds a new vlan filter entry
|
||||||
|
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
|
||||||
|
func BridgeVlanAddRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
|
||||||
|
return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) BridgeVlanAddTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
|
||||||
|
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BridgeVlanDelTunnelInfo adds a new vlan filter entry
|
||||||
|
// Equivalent to: `bridge vlan del dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
|
||||||
|
func BridgeVlanDelTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error {
|
||||||
|
return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, 0, tunid, 0, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BridgeVlanDelRangeTunnelInfoRange adds a new vlan filter entry
|
||||||
|
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
|
||||||
|
func BridgeVlanDelRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
|
||||||
|
return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) BridgeVlanDelTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
|
||||||
|
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master)
|
||||||
|
}
|
||||||
|
|
||||||
// BridgeVlanAdd adds a new vlan filter entry
|
// BridgeVlanAdd adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||||
func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
|
@ -70,7 +193,7 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||||
// BridgeVlanAdd adds a new vlan filter entry
|
// BridgeVlanAdd adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||||
func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, pvid, untagged, self, master)
|
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, 0, 0, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BridgeVlanAddRange adds a new vlan filter entry
|
// BridgeVlanAddRange adds a new vlan filter entry
|
||||||
|
@ -82,7 +205,7 @@ func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
|
||||||
// BridgeVlanAddRange adds a new vlan filter entry
|
// BridgeVlanAddRange adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
// 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 {
|
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)
|
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BridgeVlanDel adds a new vlan filter entry
|
// BridgeVlanDel adds a new vlan filter entry
|
||||||
|
@ -94,7 +217,7 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||||
// BridgeVlanDel adds a new vlan filter entry
|
// BridgeVlanDel adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||||
func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, pvid, untagged, self, master)
|
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, 0, 0, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BridgeVlanDelRange adds a new vlan filter entry
|
// BridgeVlanDelRange adds a new vlan filter entry
|
||||||
|
@ -106,10 +229,10 @@ func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
|
||||||
// BridgeVlanDelRange adds a new vlan filter entry
|
// BridgeVlanDelRange adds a new vlan filter entry
|
||||||
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
// 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 {
|
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)
|
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, pvid, untagged, self, master bool) error {
|
||||||
base := link.Attrs()
|
base := link.Attrs()
|
||||||
h.ensureIndex(base)
|
h.ensureIndex(base)
|
||||||
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
||||||
|
@ -129,25 +252,45 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid,
|
||||||
if flags > 0 {
|
if flags > 0 {
|
||||||
br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
|
br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
|
||||||
}
|
}
|
||||||
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
|
||||||
if pvid {
|
|
||||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
|
|
||||||
}
|
|
||||||
if untagged {
|
|
||||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
|
||||||
}
|
|
||||||
|
|
||||||
if vidEnd != 0 {
|
if tunid != 0 {
|
||||||
vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
|
if tunidEnd != 0 {
|
||||||
vlanEndInfo.Flags = vlanInfo.Flags
|
tiStart := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
|
||||||
|
tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid))
|
||||||
|
tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid))
|
||||||
|
tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_BEGIN))
|
||||||
|
|
||||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN
|
tiEnd := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
|
||||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunidEnd))
|
||||||
|
tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vidEnd))
|
||||||
|
tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_END))
|
||||||
|
} else {
|
||||||
|
ti := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
|
||||||
|
ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid))
|
||||||
|
ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid))
|
||||||
|
ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(0))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
||||||
|
if pvid {
|
||||||
|
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
|
||||||
|
}
|
||||||
|
if untagged {
|
||||||
|
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
||||||
|
}
|
||||||
|
|
||||||
vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END
|
if vidEnd != 0 {
|
||||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize())
|
vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
|
||||||
} else {
|
vlanEndInfo.Flags = vlanInfo.Flags
|
||||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
|
||||||
|
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)
|
req.AddData(br)
|
||||||
|
|
|
@ -54,25 +54,30 @@ func (filter *U32) Type() string {
|
||||||
|
|
||||||
type Flower struct {
|
type Flower struct {
|
||||||
FilterAttrs
|
FilterAttrs
|
||||||
DestIP net.IP
|
ClassId uint32
|
||||||
DestIPMask net.IPMask
|
DestIP net.IP
|
||||||
SrcIP net.IP
|
DestIPMask net.IPMask
|
||||||
SrcIPMask net.IPMask
|
SrcIP net.IP
|
||||||
EthType uint16
|
SrcIPMask net.IPMask
|
||||||
EncDestIP net.IP
|
EthType uint16
|
||||||
EncDestIPMask net.IPMask
|
EncDestIP net.IP
|
||||||
EncSrcIP net.IP
|
EncDestIPMask net.IPMask
|
||||||
EncSrcIPMask net.IPMask
|
EncSrcIP net.IP
|
||||||
EncDestPort uint16
|
EncSrcIPMask net.IPMask
|
||||||
EncKeyId uint32
|
EncDestPort uint16
|
||||||
SrcMac net.HardwareAddr
|
EncKeyId uint32
|
||||||
DestMac net.HardwareAddr
|
SrcMac net.HardwareAddr
|
||||||
VlanId uint16
|
DestMac net.HardwareAddr
|
||||||
SkipHw bool
|
VlanId uint16
|
||||||
SkipSw bool
|
SkipHw bool
|
||||||
IPProto *nl.IPProto
|
SkipSw bool
|
||||||
DestPort uint16
|
IPProto *nl.IPProto
|
||||||
SrcPort uint16
|
DestPort uint16
|
||||||
|
SrcPort uint16
|
||||||
|
SrcPortRangeMin uint16
|
||||||
|
SrcPortRangeMax uint16
|
||||||
|
DstPortRangeMin uint16
|
||||||
|
DstPortRangeMax uint16
|
||||||
|
|
||||||
Actions []Action
|
Actions []Action
|
||||||
}
|
}
|
||||||
|
@ -171,6 +176,19 @@ func (filter *Flower) encode(parent *nl.RtAttr) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if filter.SrcPortRangeMin != 0 && filter.SrcPortRangeMax != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MIN, htons(filter.SrcPortRangeMin))
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MAX, htons(filter.SrcPortRangeMax))
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.DstPortRangeMin != 0 && filter.DstPortRangeMax != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MIN, htons(filter.DstPortRangeMin))
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MAX, htons(filter.DstPortRangeMax))
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.ClassId != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
|
}
|
||||||
|
|
||||||
var flags uint32 = 0
|
var flags uint32 = 0
|
||||||
if filter.SkipHw {
|
if filter.SkipHw {
|
||||||
|
@ -247,6 +265,16 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||||
if skipHw != 0 {
|
if skipHw != 0 {
|
||||||
filter.SkipHw = true
|
filter.SkipHw = true
|
||||||
}
|
}
|
||||||
|
case nl.TCA_FLOWER_KEY_PORT_SRC_MIN:
|
||||||
|
filter.SrcPortRangeMin = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_KEY_PORT_SRC_MAX:
|
||||||
|
filter.SrcPortRangeMax = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_KEY_PORT_DST_MIN:
|
||||||
|
filter.DstPortRangeMin = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_KEY_PORT_DST_MAX:
|
||||||
|
filter.DstPortRangeMax = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_CLASSID:
|
||||||
|
filter.ClassId = native.Uint32(datum.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -147,9 +147,11 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
|
||||||
|
|
||||||
|
cadtFlags := optionsToBitflag(options)
|
||||||
|
|
||||||
revision := options.Revision
|
revision := options.Revision
|
||||||
if revision == 0 {
|
if revision == 0 {
|
||||||
revision = getIpsetDefaultWithTypeName(typename)
|
revision = getIpsetDefaultRevision(typename, cadtFlags)
|
||||||
}
|
}
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(revision)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(revision)))
|
||||||
|
|
||||||
|
@ -181,18 +183,6 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
|
||||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
||||||
}
|
}
|
||||||
|
|
||||||
var cadtFlags uint32
|
|
||||||
|
|
||||||
if options.Comments {
|
|
||||||
cadtFlags |= nl.IPSET_FLAG_WITH_COMMENT
|
|
||||||
}
|
|
||||||
if options.Counters {
|
|
||||||
cadtFlags |= nl.IPSET_FLAG_WITH_COUNTERS
|
|
||||||
}
|
|
||||||
if options.Skbinfo {
|
|
||||||
cadtFlags |= nl.IPSET_FLAG_WITH_SKBINFO
|
|
||||||
}
|
|
||||||
|
|
||||||
if cadtFlags != 0 {
|
if cadtFlags != 0 {
|
||||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER, Value: cadtFlags})
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER, Value: cadtFlags})
|
||||||
}
|
}
|
||||||
|
@ -395,14 +385,89 @@ func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIpsetDefaultWithTypeName(typename string) uint8 {
|
// NOTE: This can't just take typename into account, it also has to take desired
|
||||||
|
// feature support into account, on a per-set-type basis, to return the correct revision, see e.g.
|
||||||
|
// https://github.com/Olipro/ipset/blob/9f145b49100104d6570fe5c31a5236816ebb4f8f/kernel/net/netfilter/ipset/ip_set_hash_ipport.c#L30
|
||||||
|
//
|
||||||
|
// This means that whenever a new "type" of ipset is added, returning the "correct" default revision
|
||||||
|
// requires adding a new case here for that type, and consulting the ipset C code to figure out the correct
|
||||||
|
// combination of type name, feature bit flags, and revision ranges.
|
||||||
|
//
|
||||||
|
// Care should be taken as some types share the same revision ranges for the same features, and others do not.
|
||||||
|
// When in doubt, mimic the C code.
|
||||||
|
func getIpsetDefaultRevision(typename string, featureFlags uint32) uint8 {
|
||||||
switch typename {
|
switch typename {
|
||||||
case "hash:ip,port",
|
case "hash:ip,port",
|
||||||
"hash:ip,port,ip",
|
"hash:ip,port,ip":
|
||||||
"hash:ip,port,net",
|
// Taken from
|
||||||
|
// - ipset/kernel/net/netfilter/ipset/ip_set_hash_ipport.c
|
||||||
|
// - ipset/kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_SKBINFO) != 0 {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_FORCEADD) != 0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_COMMENT) != 0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_COUNTERS) != 0 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// the min revision this library supports for this type
|
||||||
|
return 1
|
||||||
|
|
||||||
|
case "hash:ip,port,net",
|
||||||
"hash:net,port":
|
"hash:net,port":
|
||||||
|
// Taken from
|
||||||
|
// - ipset/kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
|
||||||
|
// - ipset/kernel/net/netfilter/ipset/ip_set_hash_netport.c
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_SKBINFO) != 0 {
|
||||||
|
return 7
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_FORCEADD) != 0 {
|
||||||
|
return 6
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_COMMENT) != 0 {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_COUNTERS) != 0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_NOMATCH) != 0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
// the min revision this library supports for this type
|
||||||
|
return 2
|
||||||
|
|
||||||
|
case "hash:ip":
|
||||||
|
// Taken from
|
||||||
|
// - ipset/kernel/net/netfilter/ipset/ip_set_hash_ip.c
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_SKBINFO) != 0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_FORCEADD) != 0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlags & nl.IPSET_FLAG_WITH_COMMENT) != 0 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// the min revision this library supports for this type
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// can't map the correct revision for this type.
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,3 +644,19 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func optionsToBitflag(options IpsetCreateOptions) uint32 {
|
||||||
|
var cadtFlags uint32
|
||||||
|
|
||||||
|
if options.Comments {
|
||||||
|
cadtFlags |= nl.IPSET_FLAG_WITH_COMMENT
|
||||||
|
}
|
||||||
|
if options.Counters {
|
||||||
|
cadtFlags |= nl.IPSET_FLAG_WITH_COUNTERS
|
||||||
|
}
|
||||||
|
if options.Skbinfo {
|
||||||
|
cadtFlags |= nl.IPSET_FLAG_WITH_SKBINFO
|
||||||
|
}
|
||||||
|
|
||||||
|
return cadtFlags
|
||||||
|
}
|
||||||
|
|
|
@ -290,8 +290,15 @@ func (bridge *Bridge) Type() string {
|
||||||
// Vlan links have ParentIndex set in their Attrs()
|
// Vlan links have ParentIndex set in their Attrs()
|
||||||
type Vlan struct {
|
type Vlan struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
VlanId int
|
VlanId int
|
||||||
VlanProtocol VlanProtocol
|
VlanProtocol VlanProtocol
|
||||||
|
IngressQosMap map[uint32]uint32
|
||||||
|
EgressQosMap map[uint32]uint32
|
||||||
|
ReorderHdr *bool
|
||||||
|
Gvrp *bool
|
||||||
|
LooseBinding *bool
|
||||||
|
Mvrp *bool
|
||||||
|
BridgeBinding *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vlan *Vlan) Attrs() *LinkAttrs {
|
func (vlan *Vlan) Attrs() *LinkAttrs {
|
||||||
|
@ -426,6 +433,17 @@ type Veth struct {
|
||||||
PeerName string // veth on create only
|
PeerName string // veth on create only
|
||||||
PeerHardwareAddr net.HardwareAddr
|
PeerHardwareAddr net.HardwareAddr
|
||||||
PeerNamespace interface{}
|
PeerNamespace interface{}
|
||||||
|
PeerTxQLen int
|
||||||
|
PeerNumTxQueues uint32
|
||||||
|
PeerNumRxQueues uint32
|
||||||
|
PeerMTU uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVeth(attr LinkAttrs) *Veth {
|
||||||
|
return &Veth{
|
||||||
|
LinkAttrs: attr,
|
||||||
|
PeerTxQLen: -1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (veth *Veth) Attrs() *LinkAttrs {
|
func (veth *Veth) Attrs() *LinkAttrs {
|
||||||
|
|
|
@ -1683,6 +1683,73 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||||
native.PutUint16(b, uint16(link.VlanId))
|
native.PutUint16(b, uint16(link.VlanId))
|
||||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
data.AddRtAttr(nl.IFLA_VLAN_ID, b)
|
data.AddRtAttr(nl.IFLA_VLAN_ID, b)
|
||||||
|
var vlanFlags uint32
|
||||||
|
var vlanFlagsMask uint32
|
||||||
|
if link.ReorderHdr != nil {
|
||||||
|
vlanFlagsMask |= nl.VLAN_FLAG_REORDER_HDR
|
||||||
|
if *link.ReorderHdr {
|
||||||
|
vlanFlags |= nl.VLAN_FLAG_REORDER_HDR
|
||||||
|
} else {
|
||||||
|
vlanFlags &= ^uint32(nl.VLAN_FLAG_REORDER_HDR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if link.Gvrp != nil {
|
||||||
|
vlanFlagsMask |= nl.VLAN_FLAG_GVRP
|
||||||
|
if *link.Gvrp {
|
||||||
|
vlanFlags |= nl.VLAN_FLAG_GVRP
|
||||||
|
} else {
|
||||||
|
vlanFlags &= ^uint32(nl.VLAN_FLAG_GVRP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if link.Mvrp != nil {
|
||||||
|
vlanFlagsMask |= nl.VLAN_FLAG_MVRP
|
||||||
|
if *link.Mvrp {
|
||||||
|
vlanFlags |= nl.VLAN_FLAG_MVRP
|
||||||
|
} else {
|
||||||
|
vlanFlags &= ^uint32(nl.VLAN_FLAG_MVRP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if link.LooseBinding != nil {
|
||||||
|
vlanFlagsMask |= nl.VLAN_FLAG_LOOSE_BINDING
|
||||||
|
if *link.LooseBinding {
|
||||||
|
vlanFlags |= nl.VLAN_FLAG_LOOSE_BINDING
|
||||||
|
} else {
|
||||||
|
vlanFlags &= ^uint32(nl.VLAN_FLAG_LOOSE_BINDING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if link.BridgeBinding != nil {
|
||||||
|
vlanFlagsMask |= nl.VLAN_FLAG_BRIDGE_BINDING
|
||||||
|
if *link.BridgeBinding {
|
||||||
|
vlanFlags |= nl.VLAN_FLAG_BRIDGE_BINDING
|
||||||
|
} else {
|
||||||
|
vlanFlags &= ^uint32(nl.VLAN_FLAG_BRIDGE_BINDING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
buf.Write(nl.Uint32Attr(vlanFlags))
|
||||||
|
buf.Write(nl.Uint32Attr(vlanFlagsMask))
|
||||||
|
data.AddRtAttr(nl.IFLA_VLAN_FLAGS, buf.Bytes())
|
||||||
|
|
||||||
|
if link.IngressQosMap != nil {
|
||||||
|
ingressMap := data.AddRtAttr(nl.IFLA_VLAN_INGRESS_QOS, nil)
|
||||||
|
for from, to := range link.IngressQosMap {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
buf.Write(nl.Uint32Attr(from))
|
||||||
|
buf.Write(nl.Uint32Attr(to))
|
||||||
|
ingressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if link.EgressQosMap != nil {
|
||||||
|
egressMap := data.AddRtAttr(nl.IFLA_VLAN_EGRESS_QOS, nil)
|
||||||
|
for from, to := range link.EgressQosMap {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
buf.Write(nl.Uint32Attr(from))
|
||||||
|
buf.Write(nl.Uint32Attr(to))
|
||||||
|
egressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
|
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
|
||||||
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
|
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
|
||||||
|
@ -1696,16 +1763,25 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||||
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
|
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
|
||||||
nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC)
|
nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC)
|
||||||
peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
|
peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
|
||||||
if base.TxQLen >= 0 {
|
|
||||||
|
if link.PeerTxQLen >= 0 {
|
||||||
|
peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(link.PeerTxQLen)))
|
||||||
|
} else if base.TxQLen >= 0 {
|
||||||
peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
|
peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
|
||||||
}
|
}
|
||||||
if base.NumTxQueues > 0 {
|
if link.PeerNumTxQueues > 0 {
|
||||||
|
peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(link.PeerNumTxQueues))
|
||||||
|
} else if base.NumTxQueues > 0 {
|
||||||
peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
|
peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
|
||||||
}
|
}
|
||||||
if base.NumRxQueues > 0 {
|
if link.PeerNumRxQueues > 0 {
|
||||||
|
peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(link.PeerNumRxQueues))
|
||||||
|
} else if base.NumRxQueues > 0 {
|
||||||
peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
|
peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
|
||||||
}
|
}
|
||||||
if base.MTU > 0 {
|
if link.PeerMTU > 0 {
|
||||||
|
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(link.PeerMTU))
|
||||||
|
} else if base.MTU > 0 {
|
||||||
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
|
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
|
||||||
}
|
}
|
||||||
if link.PeerHardwareAddr != nil {
|
if link.PeerHardwareAddr != nil {
|
||||||
|
@ -2544,6 +2620,14 @@ func (h *Handle) LinkSetLearning(link Link, mode bool) error {
|
||||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING)
|
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkSetVlanTunnel(link Link, mode bool) error {
|
||||||
|
return pkgHandle.LinkSetVlanTunnel(link, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetVlanTunnel(link Link, mode bool) error {
|
||||||
|
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_VLAN_TUNNEL)
|
||||||
|
}
|
||||||
|
|
||||||
func LinkSetRootBlock(link Link, mode bool) error {
|
func LinkSetRootBlock(link Link, mode bool) error {
|
||||||
return pkgHandle.LinkSetRootBlock(link, mode)
|
return pkgHandle.LinkSetRootBlock(link, mode)
|
||||||
}
|
}
|
||||||
|
@ -2784,12 +2868,65 @@ func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseVlanQosMap(data []byte) map[uint32]uint32 {
|
||||||
|
values, err := nl.ParseRouteAttr(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
qosMap := make(map[uint32]uint32)
|
||||||
|
|
||||||
|
for _, value := range values {
|
||||||
|
switch value.Attr.Type {
|
||||||
|
case nl.IFLA_VLAN_QOS_MAPPING:
|
||||||
|
from := native.Uint32(value.Value[:4])
|
||||||
|
to := native.Uint32(value.Value[4:])
|
||||||
|
qosMap[from] = to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qosMap
|
||||||
|
}
|
||||||
|
|
||||||
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
vlan := link.(*Vlan)
|
vlan := link.(*Vlan)
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
switch datum.Attr.Type {
|
switch datum.Attr.Type {
|
||||||
case nl.IFLA_VLAN_ID:
|
case nl.IFLA_VLAN_ID:
|
||||||
vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
|
vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
|
||||||
|
case nl.IFLA_VLAN_FLAGS:
|
||||||
|
flags := native.Uint32(datum.Value[0:4])
|
||||||
|
trueVal := true
|
||||||
|
falseVal := false
|
||||||
|
if flags&nl.VLAN_FLAG_REORDER_HDR != 0 {
|
||||||
|
vlan.ReorderHdr = &trueVal
|
||||||
|
} else {
|
||||||
|
vlan.ReorderHdr = &falseVal
|
||||||
|
}
|
||||||
|
if flags&nl.VLAN_FLAG_GVRP != 0 {
|
||||||
|
vlan.Gvrp = &trueVal
|
||||||
|
} else {
|
||||||
|
vlan.Gvrp = &falseVal
|
||||||
|
}
|
||||||
|
if flags&nl.VLAN_FLAG_LOOSE_BINDING != 0 {
|
||||||
|
vlan.LooseBinding = &trueVal
|
||||||
|
} else {
|
||||||
|
vlan.LooseBinding = &falseVal
|
||||||
|
}
|
||||||
|
if flags&nl.VLAN_FLAG_MVRP != 0 {
|
||||||
|
vlan.Mvrp = &trueVal
|
||||||
|
} else {
|
||||||
|
vlan.Mvrp = &falseVal
|
||||||
|
}
|
||||||
|
if flags&nl.VLAN_FLAG_BRIDGE_BINDING != 0 {
|
||||||
|
vlan.BridgeBinding = &trueVal
|
||||||
|
} else {
|
||||||
|
vlan.BridgeBinding = &falseVal
|
||||||
|
}
|
||||||
|
case nl.IFLA_VLAN_EGRESS_QOS:
|
||||||
|
vlan.EgressQosMap = parseVlanQosMap(datum.Value)
|
||||||
|
case nl.IFLA_VLAN_INGRESS_QOS:
|
||||||
|
vlan.IngressQosMap = parseVlanQosMap(datum.Value)
|
||||||
case nl.IFLA_VLAN_PROTOCOL:
|
case nl.IFLA_VLAN_PROTOCOL:
|
||||||
vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
|
vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ const (
|
||||||
IFLA_BRIDGE_FLAGS = iota
|
IFLA_BRIDGE_FLAGS = iota
|
||||||
IFLA_BRIDGE_MODE
|
IFLA_BRIDGE_MODE
|
||||||
IFLA_BRIDGE_VLAN_INFO
|
IFLA_BRIDGE_VLAN_INFO
|
||||||
|
IFLA_BRIDGE_VLAN_TUNNEL_INFO
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC = iota
|
||||||
|
IFLA_BRIDGE_VLAN_TUNNEL_ID
|
||||||
|
IFLA_BRIDGE_VLAN_TUNNEL_VID
|
||||||
|
IFLA_BRIDGE_VLAN_TUNNEL_FLAGS
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -41,6 +49,11 @@ const (
|
||||||
// __u16 vid;
|
// __u16 vid;
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
type TunnelInfo struct {
|
||||||
|
TunId uint32
|
||||||
|
Vid uint16
|
||||||
|
}
|
||||||
|
|
||||||
type BridgeVlanInfo struct {
|
type BridgeVlanInfo struct {
|
||||||
Flags uint16
|
Flags uint16
|
||||||
Vid uint16
|
Vid uint16
|
||||||
|
|
|
@ -31,6 +31,20 @@ const (
|
||||||
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
|
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IFLA_VLAN_QOS_UNSPEC = iota
|
||||||
|
IFLA_VLAN_QOS_MAPPING
|
||||||
|
IFLA_VLAN_QOS_MAX = IFLA_VLAN_QOS_MAPPING
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
VLAN_FLAG_REORDER_HDR = 1 << iota
|
||||||
|
VLAN_FLAG_GVRP
|
||||||
|
VLAN_FLAG_LOOSE_BINDING
|
||||||
|
VLAN_FLAG_MVRP
|
||||||
|
VLAN_FLAG_BRIDGE_BINDING
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IFLA_NETKIT_UNSPEC = iota
|
IFLA_NETKIT_UNSPEC = iota
|
||||||
IFLA_NETKIT_PEER_INFO
|
IFLA_NETKIT_PEER_INFO
|
||||||
|
|
|
@ -9,31 +9,41 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RDMA_NLDEV_CMD_GET = 1
|
RDMA_NLDEV_CMD_GET = 1
|
||||||
RDMA_NLDEV_CMD_SET = 2
|
RDMA_NLDEV_CMD_SET = 2
|
||||||
RDMA_NLDEV_CMD_NEWLINK = 3
|
RDMA_NLDEV_CMD_NEWLINK = 3
|
||||||
RDMA_NLDEV_CMD_DELLINK = 4
|
RDMA_NLDEV_CMD_DELLINK = 4
|
||||||
RDMA_NLDEV_CMD_SYS_GET = 6
|
RDMA_NLDEV_CMD_SYS_GET = 6
|
||||||
RDMA_NLDEV_CMD_SYS_SET = 7
|
RDMA_NLDEV_CMD_SYS_SET = 7
|
||||||
|
RDMA_NLDEV_CMD_RES_GET = 9
|
||||||
|
RDMA_NLDEV_CMD_STAT_GET = 17
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RDMA_NLDEV_ATTR_DEV_INDEX = 1
|
RDMA_NLDEV_ATTR_DEV_INDEX = 1
|
||||||
RDMA_NLDEV_ATTR_DEV_NAME = 2
|
RDMA_NLDEV_ATTR_DEV_NAME = 2
|
||||||
RDMA_NLDEV_ATTR_PORT_INDEX = 3
|
RDMA_NLDEV_ATTR_PORT_INDEX = 3
|
||||||
RDMA_NLDEV_ATTR_CAP_FLAGS = 4
|
RDMA_NLDEV_ATTR_CAP_FLAGS = 4
|
||||||
RDMA_NLDEV_ATTR_FW_VERSION = 5
|
RDMA_NLDEV_ATTR_FW_VERSION = 5
|
||||||
RDMA_NLDEV_ATTR_NODE_GUID = 6
|
RDMA_NLDEV_ATTR_NODE_GUID = 6
|
||||||
RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7
|
RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7
|
||||||
RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8
|
RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8
|
||||||
RDMA_NLDEV_ATTR_LID = 9
|
RDMA_NLDEV_ATTR_LID = 9
|
||||||
RDMA_NLDEV_ATTR_SM_LID = 10
|
RDMA_NLDEV_ATTR_SM_LID = 10
|
||||||
RDMA_NLDEV_ATTR_LMC = 11
|
RDMA_NLDEV_ATTR_LMC = 11
|
||||||
RDMA_NLDEV_ATTR_PORT_STATE = 12
|
RDMA_NLDEV_ATTR_PORT_STATE = 12
|
||||||
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
|
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
|
||||||
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
|
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
|
||||||
RDMA_NLDEV_ATTR_NDEV_NAME = 51
|
RDMA_NLDEV_ATTR_RES_SUMMARY = 15
|
||||||
RDMA_NLDEV_ATTR_LINK_TYPE = 65
|
RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY = 16
|
||||||
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
|
RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME = 17
|
||||||
RDMA_NLDEV_NET_NS_FD = 68
|
RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR = 18
|
||||||
|
RDMA_NLDEV_ATTR_NDEV_NAME = 51
|
||||||
|
RDMA_NLDEV_ATTR_LINK_TYPE = 65
|
||||||
|
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
|
||||||
|
RDMA_NLDEV_NET_NS_FD = 68
|
||||||
|
RDMA_NLDEV_ATTR_STAT_HWCOUNTERS = 80
|
||||||
|
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY = 81
|
||||||
|
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME = 82
|
||||||
|
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE = 83
|
||||||
)
|
)
|
||||||
|
|
|
@ -1123,6 +1123,13 @@ const (
|
||||||
TCA_FLOWER_KEY_ENC_OPTS
|
TCA_FLOWER_KEY_ENC_OPTS
|
||||||
TCA_FLOWER_KEY_ENC_OPTS_MASK
|
TCA_FLOWER_KEY_ENC_OPTS_MASK
|
||||||
|
|
||||||
|
TCA_FLOWER_IN_HW_COUNT
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_PORT_SRC_MIN /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_SRC_MAX /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_DST_MIN /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_DST_MAX /* be16 */
|
||||||
|
|
||||||
__TCA_FLOWER_MAX
|
__TCA_FLOWER_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1138,11 +1145,11 @@ const TCA_CLS_FLAGS_SKIP_SW = 1 << 1 /* don't use filter in SW */
|
||||||
// };
|
// };
|
||||||
|
|
||||||
type TcSfqQopt struct {
|
type TcSfqQopt struct {
|
||||||
Quantum uint8
|
Quantum uint32
|
||||||
Perturb int32
|
Perturb int32
|
||||||
Limit uint32
|
Limit uint32
|
||||||
Divisor uint8
|
Divisor uint32
|
||||||
Flows uint8
|
Flows uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TcSfqQopt) Len() int {
|
func (x *TcSfqQopt) Len() int {
|
||||||
|
@ -1580,7 +1587,7 @@ func (p *TcPedit) SetIPv6Dst(ip6 net.IP) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *TcPedit) SetIPv4Src(ip net.IP) {
|
func (p *TcPedit) SetIPv4Src(ip net.IP) {
|
||||||
u32 := NativeEndian().Uint32(ip[:4])
|
u32 := NativeEndian().Uint32(ip.To4())
|
||||||
|
|
||||||
tKey := TcPeditKey{}
|
tKey := TcPeditKey{}
|
||||||
tKeyEx := TcPeditKeyEx{}
|
tKeyEx := TcPeditKeyEx{}
|
||||||
|
@ -1596,7 +1603,7 @@ func (p *TcPedit) SetIPv4Src(ip net.IP) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *TcPedit) SetIPv4Dst(ip net.IP) {
|
func (p *TcPedit) SetIPv4Dst(ip net.IP) {
|
||||||
u32 := NativeEndian().Uint32(ip[:4])
|
u32 := NativeEndian().Uint32(ip.To4())
|
||||||
|
|
||||||
tKey := TcPeditKey{}
|
tKey := TcPeditKey{}
|
||||||
tKeyEx := TcPeditKeyEx{}
|
tKeyEx := TcPeditKeyEx{}
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Protinfo struct {
|
||||||
ProxyArpWiFi bool
|
ProxyArpWiFi bool
|
||||||
Isolated bool
|
Isolated bool
|
||||||
NeighSuppress bool
|
NeighSuppress bool
|
||||||
|
VlanTunnel bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a list of enabled flags
|
// String returns a list of enabled flags
|
||||||
|
@ -55,6 +56,9 @@ func (prot *Protinfo) String() string {
|
||||||
if prot.NeighSuppress {
|
if prot.NeighSuppress {
|
||||||
boolStrings = append(boolStrings, "NeighSuppress")
|
boolStrings = append(boolStrings, "NeighSuppress")
|
||||||
}
|
}
|
||||||
|
if prot.VlanTunnel {
|
||||||
|
boolStrings = append(boolStrings, "VlanTunnel")
|
||||||
|
}
|
||||||
return strings.Join(boolStrings, " ")
|
return strings.Join(boolStrings, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
|
||||||
pi.Isolated = byteToBool(info.Value[0])
|
pi.Isolated = byteToBool(info.Value[0])
|
||||||
case nl.IFLA_BRPORT_NEIGH_SUPPRESS:
|
case nl.IFLA_BRPORT_NEIGH_SUPPRESS:
|
||||||
pi.NeighSuppress = byteToBool(info.Value[0])
|
pi.NeighSuppress = byteToBool(info.Value[0])
|
||||||
|
case nl.IFLA_BRPORT_VLAN_TUNNEL:
|
||||||
|
pi.VlanTunnel = byteToBool(info.Value[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,10 +374,10 @@ func (qdisc *FqCodel) Type() string {
|
||||||
type Sfq struct {
|
type Sfq struct {
|
||||||
QdiscAttrs
|
QdiscAttrs
|
||||||
// TODO: Only the simplified options for SFQ are handled here. Support for the extended one can be added later.
|
// TODO: Only the simplified options for SFQ are handled here. Support for the extended one can be added later.
|
||||||
Quantum uint8
|
Quantum uint32
|
||||||
Perturb uint8
|
Perturb int32
|
||||||
Limit uint32
|
Limit uint32
|
||||||
Divisor uint8
|
Divisor uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sfq *Sfq) String() string {
|
func (sfq *Sfq) String() string {
|
||||||
|
|
|
@ -321,7 +321,7 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||||
case *Sfq:
|
case *Sfq:
|
||||||
opt := nl.TcSfqQoptV1{}
|
opt := nl.TcSfqQoptV1{}
|
||||||
opt.TcSfqQopt.Quantum = qdisc.Quantum
|
opt.TcSfqQopt.Quantum = qdisc.Quantum
|
||||||
opt.TcSfqQopt.Perturb = int32(qdisc.Perturb)
|
opt.TcSfqQopt.Perturb = qdisc.Perturb
|
||||||
opt.TcSfqQopt.Limit = qdisc.Limit
|
opt.TcSfqQopt.Limit = qdisc.Limit
|
||||||
opt.TcSfqQopt.Divisor = qdisc.Divisor
|
opt.TcSfqQopt.Divisor = qdisc.Divisor
|
||||||
|
|
||||||
|
@ -683,7 +683,7 @@ func parseSfqData(qdisc Qdisc, value []byte) error {
|
||||||
sfq := qdisc.(*Sfq)
|
sfq := qdisc.(*Sfq)
|
||||||
opt := nl.DeserializeTcSfqQoptV1(value)
|
opt := nl.DeserializeTcSfqQoptV1(value)
|
||||||
sfq.Quantum = opt.TcSfqQopt.Quantum
|
sfq.Quantum = opt.TcSfqQopt.Quantum
|
||||||
sfq.Perturb = uint8(opt.TcSfqQopt.Perturb)
|
sfq.Perturb = opt.TcSfqQopt.Perturb
|
||||||
sfq.Limit = opt.TcSfqQopt.Limit
|
sfq.Limit = opt.TcSfqQopt.Limit
|
||||||
sfq.Divisor = opt.TcSfqQopt.Divisor
|
sfq.Divisor = opt.TcSfqQopt.Divisor
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ type RdmaLinkAttrs struct {
|
||||||
FirmwareVersion string
|
FirmwareVersion string
|
||||||
NodeGuid string
|
NodeGuid string
|
||||||
SysImageGuid string
|
SysImageGuid string
|
||||||
|
NumPorts uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link represents a rdma device from netlink.
|
// Link represents a rdma device from netlink.
|
||||||
|
@ -69,6 +70,11 @@ func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) {
|
||||||
r := bytes.NewReader(value)
|
r := bytes.NewReader(value)
|
||||||
binary.Read(r, nl.NativeEndian(), &sysGuid)
|
binary.Read(r, nl.NativeEndian(), &sysGuid)
|
||||||
link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid)
|
link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid)
|
||||||
|
case nl.RDMA_NLDEV_ATTR_PORT_INDEX:
|
||||||
|
var availablePort uint32
|
||||||
|
r := bytes.NewReader(value)
|
||||||
|
binary.Read(r, nl.NativeEndian(), &availablePort)
|
||||||
|
link.Attrs.NumPorts = availablePort
|
||||||
}
|
}
|
||||||
if (len % 4) != 0 {
|
if (len % 4) != 0 {
|
||||||
// Skip pad bytes
|
// Skip pad bytes
|
||||||
|
@ -345,3 +351,212 @@ func (h *Handle) RdmaLinkAdd(linkName string, linkType string, netdev string) er
|
||||||
_, err := req.Execute(unix.NETLINK_RDMA, 0)
|
_, err := req.Execute(unix.NETLINK_RDMA, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RdmaResource represents a rdma device resource tracking summaries
|
||||||
|
type RdmaResource struct {
|
||||||
|
Index uint32
|
||||||
|
Name string
|
||||||
|
RdmaResourceSummaryEntries map[string]uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaResourceList list rdma resource tracking information
|
||||||
|
// Returns all rdma devices resource tracking summary on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma resource'
|
||||||
|
func RdmaResourceList() ([]*RdmaResource, error) {
|
||||||
|
return pkgHandle.RdmaResourceList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaResourceList list rdma resource tracking information
|
||||||
|
// Returns all rdma devices resource tracking summary on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma resource'
|
||||||
|
func (h *Handle) RdmaResourceList() ([]*RdmaResource, error) {
|
||||||
|
proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_RES_GET)
|
||||||
|
req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP)
|
||||||
|
|
||||||
|
msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(msgs) == 0 {
|
||||||
|
return nil, fmt.Errorf("No valid response from kernel")
|
||||||
|
}
|
||||||
|
var rdmaResources []*RdmaResource
|
||||||
|
for _, msg := range msgs {
|
||||||
|
res, err := executeOneGetRdmaResourceList(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rdmaResources = append(rdmaResources, res)
|
||||||
|
}
|
||||||
|
return rdmaResources, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRdmaCounters(counterType uint16, data []byte) (map[string]uint64, error) {
|
||||||
|
var counterKeyType, counterValueType uint16
|
||||||
|
switch counterType {
|
||||||
|
case nl.RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY:
|
||||||
|
counterKeyType = nl.RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
|
||||||
|
counterValueType = nl.RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
|
||||||
|
case nl.RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY:
|
||||||
|
counterKeyType = nl.RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
|
||||||
|
counterValueType = nl.RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Invalid counter type: %d", counterType)
|
||||||
|
}
|
||||||
|
counters := make(map[string]uint64)
|
||||||
|
reader := bytes.NewReader(data)
|
||||||
|
|
||||||
|
for reader.Len() >= 4 {
|
||||||
|
_, attrType, _, value := parseNfAttrTLV(reader)
|
||||||
|
if attrType != counterType {
|
||||||
|
return nil, fmt.Errorf("Invalid resource summary entry type; %d", attrType)
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryReader := bytes.NewReader(value)
|
||||||
|
for summaryReader.Len() >= 4 {
|
||||||
|
_, attrType, len, value := parseNfAttrTLV(summaryReader)
|
||||||
|
if attrType != counterKeyType {
|
||||||
|
return nil, fmt.Errorf("Invalid resource summary entry name type; %d", attrType)
|
||||||
|
}
|
||||||
|
name := string(value[0 : len-1])
|
||||||
|
// Skip pad bytes
|
||||||
|
if (len % 4) != 0 {
|
||||||
|
summaryReader.Seek(int64(4-(len%4)), seekCurrent)
|
||||||
|
}
|
||||||
|
_, attrType, len, value = parseNfAttrTLV(summaryReader)
|
||||||
|
if attrType != counterValueType {
|
||||||
|
return nil, fmt.Errorf("Invalid resource summary entry value type; %d", attrType)
|
||||||
|
}
|
||||||
|
counters[name] = native.Uint64(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counters, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeOneGetRdmaResourceList(data []byte) (*RdmaResource, error) {
|
||||||
|
var res RdmaResource
|
||||||
|
reader := bytes.NewReader(data)
|
||||||
|
for reader.Len() >= 4 {
|
||||||
|
_, attrType, len, value := parseNfAttrTLV(reader)
|
||||||
|
|
||||||
|
switch attrType {
|
||||||
|
case nl.RDMA_NLDEV_ATTR_DEV_INDEX:
|
||||||
|
var Index uint32
|
||||||
|
r := bytes.NewReader(value)
|
||||||
|
binary.Read(r, nl.NativeEndian(), &Index)
|
||||||
|
res.Index = Index
|
||||||
|
case nl.RDMA_NLDEV_ATTR_DEV_NAME:
|
||||||
|
res.Name = string(value[0 : len-1])
|
||||||
|
case nl.RDMA_NLDEV_ATTR_RES_SUMMARY:
|
||||||
|
var err error
|
||||||
|
res.RdmaResourceSummaryEntries, err = parseRdmaCounters(nl.RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY, value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len % 4) != 0 {
|
||||||
|
// Skip pad bytes
|
||||||
|
reader.Seek(int64(4-(len%4)), seekCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaPortStatistic represents a rdma port statistic counter
|
||||||
|
type RdmaPortStatistic struct {
|
||||||
|
PortIndex uint32
|
||||||
|
Statistics map[string]uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaDeviceStatistic represents a rdma device statistic counter
|
||||||
|
type RdmaDeviceStatistic struct {
|
||||||
|
RdmaPortStatistics []*RdmaPortStatistic
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaStatistic get rdma device statistic counters
|
||||||
|
// Returns rdma device statistic counters on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma statistic show link [DEV]'
|
||||||
|
func RdmaStatistic(link *RdmaLink) (*RdmaDeviceStatistic, error) {
|
||||||
|
return pkgHandle.RdmaStatistic(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaStatistic get rdma device statistic counters
|
||||||
|
// Returns rdma device statistic counters on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma statistic show link [DEV]'
|
||||||
|
func (h *Handle) RdmaStatistic(link *RdmaLink) (*RdmaDeviceStatistic, error) {
|
||||||
|
rdmaLinkStatistic := make([]*RdmaPortStatistic, 0)
|
||||||
|
for portIndex := uint32(1); portIndex <= link.Attrs.NumPorts; portIndex++ {
|
||||||
|
portStatistic, err := h.RdmaPortStatisticList(link, portIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rdmaLinkStatistic = append(rdmaLinkStatistic, portStatistic)
|
||||||
|
}
|
||||||
|
return &RdmaDeviceStatistic{RdmaPortStatistics: rdmaLinkStatistic}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaPortStatisticList get rdma device port statistic counters
|
||||||
|
// Returns rdma device port statistic counters on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma statistic show link [DEV/PORT]'
|
||||||
|
func RdmaPortStatisticList(link *RdmaLink, port uint32) (*RdmaPortStatistic, error) {
|
||||||
|
return pkgHandle.RdmaPortStatisticList(link, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RdmaPortStatisticList get rdma device port statistic counters
|
||||||
|
// Returns rdma device port statistic counters on success or returns error
|
||||||
|
// otherwise.
|
||||||
|
// Equivalent to: `rdma statistic show link [DEV/PORT]'
|
||||||
|
func (h *Handle) RdmaPortStatisticList(link *RdmaLink, port uint32) (*RdmaPortStatistic, error) {
|
||||||
|
proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_STAT_GET)
|
||||||
|
req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_REQUEST)
|
||||||
|
b := make([]byte, 4)
|
||||||
|
native.PutUint32(b, link.Attrs.Index)
|
||||||
|
data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b)
|
||||||
|
req.AddData(data)
|
||||||
|
|
||||||
|
b = make([]byte, 4)
|
||||||
|
native.PutUint32(b, port)
|
||||||
|
data = nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_PORT_INDEX, b)
|
||||||
|
req.AddData(data)
|
||||||
|
|
||||||
|
msgs, err := req.Execute(unix.NETLINK_RDMA, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(msgs) != 1 {
|
||||||
|
return nil, fmt.Errorf("No valid response from kernel")
|
||||||
|
}
|
||||||
|
return executeOneGetRdmaPortStatistics(msgs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeOneGetRdmaPortStatistics(data []byte) (*RdmaPortStatistic, error) {
|
||||||
|
var stat RdmaPortStatistic
|
||||||
|
reader := bytes.NewReader(data)
|
||||||
|
for reader.Len() >= 4 {
|
||||||
|
_, attrType, len, value := parseNfAttrTLV(reader)
|
||||||
|
|
||||||
|
switch attrType {
|
||||||
|
case nl.RDMA_NLDEV_ATTR_PORT_INDEX:
|
||||||
|
var Index uint32
|
||||||
|
r := bytes.NewReader(value)
|
||||||
|
binary.Read(r, nl.NativeEndian(), &Index)
|
||||||
|
stat.PortIndex = Index
|
||||||
|
case nl.RDMA_NLDEV_ATTR_STAT_HWCOUNTERS:
|
||||||
|
var err error
|
||||||
|
stat.Statistics, err = parseRdmaCounters(nl.RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY, value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len % 4) != 0 {
|
||||||
|
// Skip pad bytes
|
||||||
|
reader.Seek(int64(4-(len%4)), seekCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &stat, nil
|
||||||
|
}
|
||||||
|
|
|
@ -996,7 +996,7 @@ github.com/vbauerster/mpb/v8
|
||||||
github.com/vbauerster/mpb/v8/cwriter
|
github.com/vbauerster/mpb/v8/cwriter
|
||||||
github.com/vbauerster/mpb/v8/decor
|
github.com/vbauerster/mpb/v8/decor
|
||||||
github.com/vbauerster/mpb/v8/internal
|
github.com/vbauerster/mpb/v8/internal
|
||||||
# github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9
|
# github.com/vishvananda/netlink v1.3.1
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/vishvananda/netlink
|
github.com/vishvananda/netlink
|
||||||
github.com/vishvananda/netlink/nl
|
github.com/vishvananda/netlink/nl
|
||||||
|
|
Loading…
Reference in New Issue