mirror of https://github.com/containers/podman.git
Merge pull request #26039 from containers/renovate/github.com-vishvananda-netlink-digest
fix(deps): update github.com/vishvananda/netlink digest to 9d88d83
This commit is contained in:
commit
a2f486feb3
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.20250221194427-0af32151e72b
|
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9
|
||||||
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.39.0
|
golang.org/x/net v0.39.0
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -482,9 +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.20250221194427-0af32151e72b h1:hYWtmuzlR0jpWu+ljWfPMi7oNiZ9x/D3GbBqgZTOhyI=
|
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9 h1:ZEjCI2kamoTYIx348/Nfco4c4NPvpq972DM2HMgnBgI=
|
||||||
github.com/vishvananda/netlink v1.3.1-0.20250221194427-0af32151e72b/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
|
||||||
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=
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
@ -81,9 +80,6 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
||||||
msg.Index = uint32(addr.LinkIndex)
|
msg.Index = uint32(addr.LinkIndex)
|
||||||
} else {
|
} else {
|
||||||
base := link.Attrs()
|
base := link.Attrs()
|
||||||
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
|
|
||||||
return fmt.Errorf("label must begin with interface name")
|
|
||||||
}
|
|
||||||
h.ensureIndex(base)
|
h.ensureIndex(base)
|
||||||
msg.Index = uint32(base.Index)
|
msg.Index = uint32(base.Index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,6 +398,29 @@ func NewPoliceAction() *PoliceAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SampleAction struct {
|
||||||
|
ActionAttrs
|
||||||
|
Group uint32
|
||||||
|
Rate uint32
|
||||||
|
TruncSize uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *SampleAction) Type() string {
|
||||||
|
return "sample"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *SampleAction) Attrs() *ActionAttrs {
|
||||||
|
return &action.ActionAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSampleAction() *SampleAction {
|
||||||
|
return &SampleAction{
|
||||||
|
ActionAttrs: ActionAttrs{
|
||||||
|
Action: TC_ACT_PIPE,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MatchAll filters match all packets
|
// MatchAll filters match all packets
|
||||||
type MatchAll struct {
|
type MatchAll struct {
|
||||||
FilterAttrs
|
FilterAttrs
|
||||||
|
|
|
@ -740,6 +740,17 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||||
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
||||||
aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
||||||
aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
||||||
|
case *SampleAction:
|
||||||
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
|
tabIndex++
|
||||||
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("sample"))
|
||||||
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
|
gen := nl.TcGen{}
|
||||||
|
toTcGen(action.Attrs(), &gen)
|
||||||
|
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PARMS, gen.Serialize())
|
||||||
|
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_RATE, nl.Uint32Attr(action.Rate))
|
||||||
|
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP, nl.Uint32Attr(action.Group))
|
||||||
|
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_TRUNC_SIZE, nl.Uint32Attr(action.TruncSize))
|
||||||
case *GenericAction:
|
case *GenericAction:
|
||||||
table := attr.AddRtAttr(tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
|
@ -752,6 +763,7 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||||
table := attr.AddRtAttr(tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
pedit := nl.TcPedit{}
|
pedit := nl.TcPedit{}
|
||||||
|
toTcGen(action.Attrs(), &pedit.Sel.TcGen)
|
||||||
if action.SrcMacAddr != nil {
|
if action.SrcMacAddr != nil {
|
||||||
pedit.SetEthSrc(action.SrcMacAddr)
|
pedit.SetEthSrc(action.SrcMacAddr)
|
||||||
}
|
}
|
||||||
|
@ -825,6 +837,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||||
action = &ConnmarkAction{}
|
action = &ConnmarkAction{}
|
||||||
case "csum":
|
case "csum":
|
||||||
action = &CsumAction{}
|
action = &CsumAction{}
|
||||||
|
case "sample":
|
||||||
|
action = &SampleAction{}
|
||||||
case "gact":
|
case "gact":
|
||||||
action = &GenericAction{}
|
action = &GenericAction{}
|
||||||
case "vlan":
|
case "vlan":
|
||||||
|
@ -949,6 +963,18 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||||
actionTimestamp = toTimeStamp(tcTs)
|
actionTimestamp = toTimeStamp(tcTs)
|
||||||
}
|
}
|
||||||
|
case "sample":
|
||||||
|
switch adatum.Attr.Type {
|
||||||
|
case nl.TCA_ACT_SAMPLE_PARMS:
|
||||||
|
gen := *nl.DeserializeTcGen(adatum.Value)
|
||||||
|
toAttrs(&gen, action.Attrs())
|
||||||
|
case nl.TCA_ACT_SAMPLE_RATE:
|
||||||
|
action.(*SampleAction).Rate = native.Uint32(adatum.Value[0:4])
|
||||||
|
case nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP:
|
||||||
|
action.(*SampleAction).Group = native.Uint32(adatum.Value[0:4])
|
||||||
|
case nl.TCA_ACT_SAMPLE_TRUNC_SIZE:
|
||||||
|
action.(*SampleAction).TruncSize = native.Uint32(adatum.Value[0:4])
|
||||||
|
}
|
||||||
case "gact":
|
case "gact":
|
||||||
switch adatum.Attr.Type {
|
switch adatum.Attr.Type {
|
||||||
case nl.TCA_GACT_PARMS:
|
case nl.TCA_GACT_PARMS:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package netlink
|
package netlink
|
||||||
|
@ -183,6 +184,10 @@ func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetIP6AddrGenMode(link Link, mode int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,5 +86,5 @@ func newIocltStringSetReq(linkName string) (*Ifreq, *ethtoolSset) {
|
||||||
// getSocketUDP returns file descriptor to new UDP socket
|
// getSocketUDP returns file descriptor to new UDP socket
|
||||||
// It is used for communication with ioctl interface.
|
// It is used for communication with ioctl interface.
|
||||||
func getSocketUDP() (int, error) {
|
func getSocketUDP() (int, error) {
|
||||||
return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0)
|
return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM|unix.SOCK_CLOEXEC, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,13 +348,14 @@ type TuntapFlag uint16
|
||||||
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
||||||
type Tuntap struct {
|
type Tuntap struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Mode TuntapMode
|
Mode TuntapMode
|
||||||
Flags TuntapFlag
|
Flags TuntapFlag
|
||||||
NonPersist bool
|
NonPersist bool
|
||||||
Queues int
|
Queues int
|
||||||
Fds []*os.File
|
DisabledQueues int
|
||||||
Owner uint32
|
Fds []*os.File
|
||||||
Group uint32
|
Owner uint32
|
||||||
|
Group uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
||||||
|
@ -1058,6 +1059,8 @@ type Geneve struct {
|
||||||
FlowBased bool
|
FlowBased bool
|
||||||
InnerProtoInherit bool
|
InnerProtoInherit bool
|
||||||
Df GeneveDf
|
Df GeneveDf
|
||||||
|
PortLow int
|
||||||
|
PortHigh int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (geneve *Geneve) Attrs() *LinkAttrs {
|
func (geneve *Geneve) Attrs() *LinkAttrs {
|
||||||
|
|
|
@ -2670,9 +2670,38 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LinkSetIP6AddrGenMode sets the IPv6 address generation mode of the link device.
|
||||||
|
// Equivalent to: `ip link set $link addrgenmode $mode`
|
||||||
|
func LinkSetIP6AddrGenMode(link Link, mode int) error {
|
||||||
|
return pkgHandle.LinkSetIP6AddrGenMode(link, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkSetIP6AddrGenMode sets the IPv6 address generation mode of the link device.
|
||||||
|
// Equivalent to: `ip link set $link addrgenmode $mode`
|
||||||
|
func (h *Handle) LinkSetIP6AddrGenMode(link Link, mode 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, 1)
|
||||||
|
b[0] = uint8(mode)
|
||||||
|
|
||||||
|
data := nl.NewRtAttr(unix.IFLA_INET6_ADDR_GEN_MODE, b)
|
||||||
|
af := nl.NewRtAttr(unix.AF_INET6, data.Serialize())
|
||||||
|
spec := nl.NewRtAttr(unix.IFLA_AF_SPEC, af.Serialize())
|
||||||
|
req.AddData(spec)
|
||||||
|
|
||||||
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
|
func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
|
||||||
if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
|
if nk.Mode != NETKIT_MODE_L2 && (nk.LinkAttrs.HardwareAddr != nil || nk.peerLinkAttrs.HardwareAddr != nil) {
|
||||||
return fmt.Errorf("netkit doesn't support setting Ethernet")
|
return fmt.Errorf("netkit only allows setting Ethernet in L2 mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
|
@ -2724,6 +2753,9 @@ func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
|
||||||
peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
|
peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if nk.peerLinkAttrs.HardwareAddr != nil {
|
||||||
|
peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(nk.peerLinkAttrs.HardwareAddr))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3068,6 +3100,10 @@ func linkFlags(rawFlags uint32) net.Flags {
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type genevePortRange struct {
|
||||||
|
Lo, Hi uint16
|
||||||
|
}
|
||||||
|
|
||||||
func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
|
|
||||||
|
@ -3104,6 +3140,15 @@ func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||||
data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
|
data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if geneve.PortLow > 0 || geneve.PortHigh > 0 {
|
||||||
|
pr := genevePortRange{uint16(geneve.PortLow), uint16(geneve.PortHigh)}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
binary.Write(buf, binary.BigEndian, &pr)
|
||||||
|
|
||||||
|
data.AddRtAttr(nl.IFLA_GENEVE_PORT_RANGE, buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df)))
|
data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3125,6 +3170,13 @@ func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
geneve.FlowBased = true
|
geneve.FlowBased = true
|
||||||
case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
|
case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
|
||||||
geneve.InnerProtoInherit = true
|
geneve.InnerProtoInherit = true
|
||||||
|
case nl.IFLA_GENEVE_PORT_RANGE:
|
||||||
|
buf := bytes.NewBuffer(datum.Value[0:4])
|
||||||
|
var pr genevePortRange
|
||||||
|
if binary.Read(buf, binary.BigEndian, &pr) == nil {
|
||||||
|
geneve.PortLow = int(pr.Lo)
|
||||||
|
geneve.PortHigh = int(pr.Hi)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3900,11 +3952,27 @@ func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
tuntap.Group = native.Uint32(datum.Value)
|
tuntap.Group = native.Uint32(datum.Value)
|
||||||
case nl.IFLA_TUN_TYPE:
|
case nl.IFLA_TUN_TYPE:
|
||||||
tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
|
tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
|
||||||
|
case nl.IFLA_TUN_PI:
|
||||||
|
if datum.Value[0] == 0 {
|
||||||
|
tuntap.Flags |= TUNTAP_NO_PI
|
||||||
|
}
|
||||||
|
case nl.IFLA_TUN_VNET_HDR:
|
||||||
|
if datum.Value[0] == 1 {
|
||||||
|
tuntap.Flags |= TUNTAP_VNET_HDR
|
||||||
|
}
|
||||||
case nl.IFLA_TUN_PERSIST:
|
case nl.IFLA_TUN_PERSIST:
|
||||||
tuntap.NonPersist = false
|
tuntap.NonPersist = false
|
||||||
if uint8(datum.Value[0]) == 0 {
|
if uint8(datum.Value[0]) == 0 {
|
||||||
tuntap.NonPersist = true
|
tuntap.NonPersist = true
|
||||||
}
|
}
|
||||||
|
case nl.IFLA_TUN_MULTI_QUEUE:
|
||||||
|
if datum.Value[0] == 1 {
|
||||||
|
tuntap.Flags |= TUNTAP_MULTI_QUEUE
|
||||||
|
}
|
||||||
|
case nl.IFLA_TUN_NUM_QUEUES:
|
||||||
|
tuntap.Queues = int(native.Uint32(datum.Value))
|
||||||
|
case nl.IFLA_TUN_NUM_DISABLED_QUEUES:
|
||||||
|
tuntap.DisabledQueues = int(native.Uint32(datum.Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
// ideally golang.org/x/sys/unix would define IfReq but it only has
|
// ideally golang.org/x/sys/unix would define IfReq but it only has
|
||||||
// IFNAMSIZ, hence this minimalistic implementation
|
// IFNAMSIZ, hence this minimalistic implementation
|
||||||
const (
|
const (
|
||||||
|
@ -7,8 +16,136 @@ const (
|
||||||
IFNAMSIZ = 16
|
IFNAMSIZ = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const TUN = "/dev/net/tun"
|
||||||
|
|
||||||
type ifReq struct {
|
type ifReq struct {
|
||||||
Name [IFNAMSIZ]byte
|
Name [IFNAMSIZ]byte
|
||||||
Flags uint16
|
Flags uint16
|
||||||
pad [SizeOfIfReq - IFNAMSIZ - 2]byte
|
pad [SizeOfIfReq - IFNAMSIZ - 2]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddQueues opens and attaches multiple queue file descriptors to an existing
|
||||||
|
// TUN/TAP interface in multi-queue mode.
|
||||||
|
//
|
||||||
|
// It performs TUNSETIFF ioctl on each opened file descriptor with the current
|
||||||
|
// tuntap configuration. Each resulting fd is set to non-blocking mode and
|
||||||
|
// returned as *os.File.
|
||||||
|
//
|
||||||
|
// If the interface was created with a name pattern (e.g. "tap%d"),
|
||||||
|
// the first successful TUNSETIFF call will return the resolved name,
|
||||||
|
// which is saved back into tuntap.Name.
|
||||||
|
//
|
||||||
|
// This method assumes that the interface already exists and is in multi-queue mode.
|
||||||
|
// The returned FDs are also appended to tuntap.Fds and tuntap.Queues is updated.
|
||||||
|
//
|
||||||
|
// It is the caller's responsibility to close the FDs when they are no longer needed.
|
||||||
|
func (tuntap *Tuntap) AddQueues(count int) ([]*os.File, error) {
|
||||||
|
if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP {
|
||||||
|
return nil, fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode)
|
||||||
|
}
|
||||||
|
if tuntap.Flags&TUNTAP_MULTI_QUEUE == 0 {
|
||||||
|
return nil, fmt.Errorf("TUNTAP_MULTI_QUEUE not set")
|
||||||
|
}
|
||||||
|
if count < 1 {
|
||||||
|
return nil, fmt.Errorf("count must be >= 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := unix.NewIfreq(tuntap.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.SetUint16(uint16(tuntap.Mode) | uint16(tuntap.Flags))
|
||||||
|
|
||||||
|
var fds []*os.File
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
localReq := req
|
||||||
|
fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0)
|
||||||
|
if err != nil {
|
||||||
|
cleanupFds(fds)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = unix.IoctlIfreq(fd, unix.TUNSETIFF, req)
|
||||||
|
if err != nil {
|
||||||
|
// close the new fd
|
||||||
|
unix.Close(fd)
|
||||||
|
// and the already opened ones
|
||||||
|
cleanupFds(fds)
|
||||||
|
return nil, fmt.Errorf("tuntap IOCTL TUNSETIFF failed [%d]: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the tun device to non-blocking before use. The below comment
|
||||||
|
// taken from:
|
||||||
|
//
|
||||||
|
// https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea
|
||||||
|
//
|
||||||
|
// Note there is a complication because in go, if a device node is
|
||||||
|
// opened, go sets it to use nonblocking I/O. However a /dev/net/tun
|
||||||
|
// doesn't work with epoll until after the TUNSETIFF ioctl has been
|
||||||
|
// done. So we open the unix fd directly, do the ioctl, then put the
|
||||||
|
// fd in nonblocking mode, an then finally wrap it in a os.File,
|
||||||
|
// which will see the nonblocking mode and add the fd to the
|
||||||
|
// pollable set, so later on when we Read() from it blocked the
|
||||||
|
// calling thread in the kernel.
|
||||||
|
//
|
||||||
|
// See
|
||||||
|
// https://github.com/golang/go/issues/30426
|
||||||
|
// which got exposed in go 1.13 by the fix to
|
||||||
|
// https://github.com/golang/go/issues/30624
|
||||||
|
err = unix.SetNonblock(fd, true)
|
||||||
|
if err != nil {
|
||||||
|
cleanupFds(fds)
|
||||||
|
return nil, fmt.Errorf("tuntap set to non-blocking failed [%d]: %w", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the file from the file descriptor and store it
|
||||||
|
file := os.NewFile(uintptr(fd), TUN)
|
||||||
|
fds = append(fds, file)
|
||||||
|
|
||||||
|
// 1) we only care for the name of the first tap in the multi queue set
|
||||||
|
// 2) if the original name was empty, the localReq has now the actual name
|
||||||
|
//
|
||||||
|
// In addition:
|
||||||
|
// This ensures that the link name is always identical to what the kernel returns.
|
||||||
|
// Not only in case of an empty name, but also when using name templates.
|
||||||
|
// e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number.
|
||||||
|
if i == 0 {
|
||||||
|
tuntap.Name = strings.Trim(localReq.Name(), "\x00")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tuntap.Fds = append(tuntap.Fds, fds...)
|
||||||
|
tuntap.Queues = len(tuntap.Fds)
|
||||||
|
return fds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveQueues closes the given TAP queue file descriptors and removes them
|
||||||
|
// from the tuntap.Fds list.
|
||||||
|
//
|
||||||
|
// This is a logical counterpart to AddQueues and allows releasing specific queues
|
||||||
|
// (e.g., to simulate queue failure or perform partial detach).
|
||||||
|
//
|
||||||
|
// The method updates tuntap.Queues to reflect the number of remaining active queues.
|
||||||
|
//
|
||||||
|
// It is safe to call with a subset of tuntap.Fds, but the caller must ensure
|
||||||
|
// that the passed *os.File descriptors belong to this interface.
|
||||||
|
func (tuntap *Tuntap) RemoveQueues(fds ...*os.File) error {
|
||||||
|
toClose := make(map[uintptr]struct{}, len(fds))
|
||||||
|
for _, fd := range fds {
|
||||||
|
toClose[fd.Fd()] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newFds []*os.File
|
||||||
|
for _, fd := range tuntap.Fds {
|
||||||
|
if _, shouldClose := toClose[fd.Fd()]; shouldClose {
|
||||||
|
if err := fd.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close queue fd %d: %w", fd.Fd(), err)
|
||||||
|
}
|
||||||
|
tuntap.Queues--
|
||||||
|
} else {
|
||||||
|
newFds = append(newFds, fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tuntap.Fds = newFds
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,14 @@ type Neigh struct {
|
||||||
Vlan int
|
Vlan int
|
||||||
VNI int
|
VNI int
|
||||||
MasterIndex int
|
MasterIndex int
|
||||||
|
|
||||||
|
// These values are expressed as "clock ticks ago". To
|
||||||
|
// convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK).
|
||||||
|
// When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed
|
||||||
|
// in centiseconds.
|
||||||
|
Confirmed uint32 // The last time ARP/ND succeeded OR higher layer confirmation was received
|
||||||
|
Used uint32 // The last time ARP/ND took place for this neighbor
|
||||||
|
Updated uint32 // The time when the current NUD state was entered
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns $ip/$hwaddr $label
|
// String returns $ip/$hwaddr $label
|
||||||
|
|
|
@ -349,6 +349,10 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
||||||
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
|
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
|
||||||
case NDA_MASTER:
|
case NDA_MASTER:
|
||||||
neigh.MasterIndex = int(native.Uint32(attr.Value[0:4]))
|
neigh.MasterIndex = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
case NDA_CACHEINFO:
|
||||||
|
neigh.Confirmed = native.Uint32(attr.Value[0:4])
|
||||||
|
neigh.Used = native.Uint32(attr.Value[4:8])
|
||||||
|
neigh.Updated = native.Uint32(attr.Value[8:12])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package netlink
|
package netlink
|
||||||
|
@ -144,6 +145,10 @@ func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkSetIP6AddrGenMode(link Link, mode int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func LinkAdd(link Link) error {
|
func LinkAdd(link Link) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,7 @@ const (
|
||||||
IFLA_GENEVE_TTL_INHERIT
|
IFLA_GENEVE_TTL_INHERIT
|
||||||
IFLA_GENEVE_DF
|
IFLA_GENEVE_DF
|
||||||
IFLA_GENEVE_INNER_PROTO_INHERIT
|
IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||||
|
IFLA_GENEVE_PORT_RANGE
|
||||||
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
|
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -818,3 +819,10 @@ const (
|
||||||
IFLA_BAREUDP_MULTIPROTO_MODE
|
IFLA_BAREUDP_MULTIPROTO_MODE
|
||||||
IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE
|
IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IN6_ADDR_GEN_MODE_EUI64 = iota
|
||||||
|
IN6_ADDR_GEN_MODE_NONE
|
||||||
|
IN6_ADDR_GEN_MODE_STABLE_PRIVACY
|
||||||
|
IN6_ADDR_GEN_MODE_RANDOM
|
||||||
|
)
|
||||||
|
|
|
@ -789,7 +789,7 @@ func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
|
||||||
// Returns the netlink socket on which Receive() method can be called
|
// Returns the netlink socket on which Receive() method can be called
|
||||||
// to retrieve the messages from the kernel.
|
// to retrieve the messages from the kernel.
|
||||||
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
||||||
fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol)
|
fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ const (
|
||||||
SEG6_LOCAL_IIF
|
SEG6_LOCAL_IIF
|
||||||
SEG6_LOCAL_OIF
|
SEG6_LOCAL_OIF
|
||||||
SEG6_LOCAL_BPF
|
SEG6_LOCAL_BPF
|
||||||
|
SEG6_LOCAL_VRFTABLE
|
||||||
__SEG6_LOCAL_MAX
|
__SEG6_LOCAL_MAX
|
||||||
)
|
)
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -77,6 +77,17 @@ const (
|
||||||
TCA_ACT_MAX
|
TCA_ACT_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_ACT_SAMPLE_UNSPEC = iota
|
||||||
|
TCA_ACT_SAMPLE_TM
|
||||||
|
TCA_ACT_SAMPLE_PARMS
|
||||||
|
TCA_ACT_SAMPLE_RATE
|
||||||
|
TCA_ACT_SAMPLE_TRUNC_SIZE
|
||||||
|
TCA_ACT_SAMPLE_PSAMPLE_GROUP
|
||||||
|
TCA_ACT_SAMPLE_PAD
|
||||||
|
TCA_ACT_SAMPLE_MAX
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TCA_PRIO_UNSPEC = iota
|
TCA_PRIO_UNSPEC = iota
|
||||||
TCA_PRIO_MQ
|
TCA_PRIO_MQ
|
||||||
|
|
|
@ -78,10 +78,14 @@ const (
|
||||||
XFRMA_PROTO /* __u8 */
|
XFRMA_PROTO /* __u8 */
|
||||||
XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */
|
XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */
|
||||||
XFRMA_PAD
|
XFRMA_PAD
|
||||||
XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
|
XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
|
||||||
XFRMA_SET_MARK /* __u32 */
|
XFRMA_SET_MARK /* __u32 */
|
||||||
XFRMA_SET_MARK_MASK /* __u32 */
|
XFRMA_SET_MARK_MASK /* __u32 */
|
||||||
XFRMA_IF_ID /* __u32 */
|
XFRMA_IF_ID /* __u32 */
|
||||||
|
XFRMA_MTIMER_THRESH /* __u32 in seconds for input SA */
|
||||||
|
XFRMA_SA_DIR /* __u8 */
|
||||||
|
XFRMA_NAT_KEEPALIVE_INTERVAL /* __u32 in seconds for NAT keepalive */
|
||||||
|
XFRMA_SA_PCPU /* __u32 */
|
||||||
|
|
||||||
XFRMA_MAX = iota - 1
|
XFRMA_MAX = iota - 1
|
||||||
)
|
)
|
||||||
|
|
|
@ -45,7 +45,7 @@ type Encap interface {
|
||||||
Equal(Encap) bool
|
Equal(Encap) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//Protocol describe what was the originator of the route
|
// Protocol describe what was the originator of the route
|
||||||
type RouteProtocol int
|
type RouteProtocol int
|
||||||
|
|
||||||
// Route represents a netlink route.
|
// Route represents a netlink route.
|
||||||
|
@ -70,6 +70,7 @@ type Route struct {
|
||||||
Via Destination
|
Via Destination
|
||||||
Realm int
|
Realm int
|
||||||
MTU int
|
MTU int
|
||||||
|
MTULock bool
|
||||||
Window int
|
Window int
|
||||||
Rtt int
|
Rtt int
|
||||||
RttVar int
|
RttVar int
|
||||||
|
@ -81,6 +82,7 @@ type Route struct {
|
||||||
InitCwnd int
|
InitCwnd int
|
||||||
Features int
|
Features int
|
||||||
RtoMin int
|
RtoMin int
|
||||||
|
RtoMinLock bool
|
||||||
InitRwnd int
|
InitRwnd int
|
||||||
QuickACK int
|
QuickACK int
|
||||||
Congctl string
|
Congctl string
|
||||||
|
|
|
@ -270,6 +270,7 @@ type SEG6LocalEncap struct {
|
||||||
Action int
|
Action int
|
||||||
Segments []net.IP // from SRH in seg6_local_lwt
|
Segments []net.IP // from SRH in seg6_local_lwt
|
||||||
Table int // table id for End.T and End.DT6
|
Table int // table id for End.T and End.DT6
|
||||||
|
VrfTable int // vrftable id for END.DT4 and END.DT6
|
||||||
InAddr net.IP
|
InAddr net.IP
|
||||||
In6Addr net.IP
|
In6Addr net.IP
|
||||||
Iif int
|
Iif int
|
||||||
|
@ -305,6 +306,9 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
|
||||||
case nl.SEG6_LOCAL_TABLE:
|
case nl.SEG6_LOCAL_TABLE:
|
||||||
e.Table = int(native.Uint32(attr.Value[0:4]))
|
e.Table = int(native.Uint32(attr.Value[0:4]))
|
||||||
e.Flags[nl.SEG6_LOCAL_TABLE] = true
|
e.Flags[nl.SEG6_LOCAL_TABLE] = true
|
||||||
|
case nl.SEG6_LOCAL_VRFTABLE:
|
||||||
|
e.VrfTable = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
e.Flags[nl.SEG6_LOCAL_VRFTABLE] = true
|
||||||
case nl.SEG6_LOCAL_NH4:
|
case nl.SEG6_LOCAL_NH4:
|
||||||
e.InAddr = net.IP(attr.Value[0:4])
|
e.InAddr = net.IP(attr.Value[0:4])
|
||||||
e.Flags[nl.SEG6_LOCAL_NH4] = true
|
e.Flags[nl.SEG6_LOCAL_NH4] = true
|
||||||
|
@ -361,6 +365,15 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
|
||||||
native.PutUint32(attr[4:], uint32(e.Table))
|
native.PutUint32(attr[4:], uint32(e.Table))
|
||||||
res = append(res, attr...)
|
res = append(res, attr...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.Flags[nl.SEG6_LOCAL_VRFTABLE] {
|
||||||
|
attr := make([]byte, 8)
|
||||||
|
native.PutUint16(attr, 8)
|
||||||
|
native.PutUint16(attr[2:], nl.SEG6_LOCAL_VRFTABLE)
|
||||||
|
native.PutUint32(attr[4:], uint32(e.VrfTable))
|
||||||
|
res = append(res, attr...)
|
||||||
|
}
|
||||||
|
|
||||||
if e.Flags[nl.SEG6_LOCAL_NH4] {
|
if e.Flags[nl.SEG6_LOCAL_NH4] {
|
||||||
attr := make([]byte, 4)
|
attr := make([]byte, 4)
|
||||||
native.PutUint16(attr, 8)
|
native.PutUint16(attr, 8)
|
||||||
|
@ -413,6 +426,11 @@ func (e *SEG6LocalEncap) String() string {
|
||||||
if e.Flags[nl.SEG6_LOCAL_TABLE] {
|
if e.Flags[nl.SEG6_LOCAL_TABLE] {
|
||||||
strs = append(strs, fmt.Sprintf("table %d", e.Table))
|
strs = append(strs, fmt.Sprintf("table %d", e.Table))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.Flags[nl.SEG6_LOCAL_VRFTABLE] {
|
||||||
|
strs = append(strs, fmt.Sprintf("vrftable %d", e.VrfTable))
|
||||||
|
}
|
||||||
|
|
||||||
if e.Flags[nl.SEG6_LOCAL_NH4] {
|
if e.Flags[nl.SEG6_LOCAL_NH4] {
|
||||||
strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr))
|
strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr))
|
||||||
}
|
}
|
||||||
|
@ -477,7 +495,7 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
|
||||||
if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
|
if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
|
if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf || e.VrfTable != o.VrfTable {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -1072,6 +1090,10 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R
|
||||||
if route.MTU > 0 {
|
if route.MTU > 0 {
|
||||||
b := nl.Uint32Attr(uint32(route.MTU))
|
b := nl.Uint32Attr(uint32(route.MTU))
|
||||||
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
|
||||||
|
if route.MTULock {
|
||||||
|
b := nl.Uint32Attr(uint32(1 << unix.RTAX_MTU))
|
||||||
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_LOCK, b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if route.Window > 0 {
|
if route.Window > 0 {
|
||||||
b := nl.Uint32Attr(uint32(route.Window))
|
b := nl.Uint32Attr(uint32(route.Window))
|
||||||
|
@ -1116,6 +1138,10 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R
|
||||||
if route.RtoMin > 0 {
|
if route.RtoMin > 0 {
|
||||||
b := nl.Uint32Attr(uint32(route.RtoMin))
|
b := nl.Uint32Attr(uint32(route.RtoMin))
|
||||||
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTO_MIN, b))
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTO_MIN, b))
|
||||||
|
if route.RtoMinLock {
|
||||||
|
b := nl.Uint32Attr(uint32(1 << unix.RTAX_RTO_MIN))
|
||||||
|
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_LOCK, b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if route.InitRwnd > 0 {
|
if route.InitRwnd > 0 {
|
||||||
b := nl.Uint32Attr(uint32(route.InitRwnd))
|
b := nl.Uint32Attr(uint32(route.InitRwnd))
|
||||||
|
@ -1440,6 +1466,9 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||||
switch metric.Attr.Type {
|
switch metric.Attr.Type {
|
||||||
case unix.RTAX_MTU:
|
case unix.RTAX_MTU:
|
||||||
route.MTU = int(native.Uint32(metric.Value[0:4]))
|
route.MTU = int(native.Uint32(metric.Value[0:4]))
|
||||||
|
case unix.RTAX_LOCK:
|
||||||
|
route.MTULock = native.Uint32(metric.Value[0:4]) == uint32(1<<unix.RTAX_MTU)
|
||||||
|
route.RtoMinLock = native.Uint32(metric.Value[0:4]) == uint32(1<<unix.RTAX_RTO_MIN)
|
||||||
case unix.RTAX_WINDOW:
|
case unix.RTAX_WINDOW:
|
||||||
route.Window = int(native.Uint32(metric.Value[0:4]))
|
route.Window = int(native.Uint32(metric.Value[0:4]))
|
||||||
case unix.RTAX_RTT:
|
case unix.RTAX_RTT:
|
||||||
|
@ -1533,6 +1562,7 @@ type RouteGetOptions struct {
|
||||||
Iif string
|
Iif string
|
||||||
IifIndex int
|
IifIndex int
|
||||||
Oif string
|
Oif string
|
||||||
|
OifIndex int
|
||||||
VrfName string
|
VrfName string
|
||||||
SrcAddr net.IP
|
SrcAddr net.IP
|
||||||
UID *uint32
|
UID *uint32
|
||||||
|
@ -1612,14 +1642,20 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||||
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oifIndex := uint32(0)
|
||||||
if len(options.Oif) > 0 {
|
if len(options.Oif) > 0 {
|
||||||
link, err := h.LinkByName(options.Oif)
|
link, err := h.LinkByName(options.Oif)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
oifIndex = uint32(link.Attrs().Index)
|
||||||
|
} else if options.OifIndex > 0 {
|
||||||
|
oifIndex = uint32(options.OifIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
if oifIndex > 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, uint32(link.Attrs().Index))
|
native.PutUint32(b, oifIndex)
|
||||||
|
|
||||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,14 @@ const (
|
||||||
XFRM_MODE_MAX
|
XFRM_MODE_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SADir is an enum representing an ipsec template direction.
|
||||||
|
type SADir uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
XFRM_SA_DIR_IN SADir = iota + 1
|
||||||
|
XFRM_SA_DIR_OUT
|
||||||
|
)
|
||||||
|
|
||||||
func (m Mode) String() string {
|
func (m Mode) String() string {
|
||||||
switch m {
|
switch m {
|
||||||
case XFRM_MODE_TRANSPORT:
|
case XFRM_MODE_TRANSPORT:
|
||||||
|
|
|
@ -113,7 +113,9 @@ type XfrmState struct {
|
||||||
Statistics XfrmStateStats
|
Statistics XfrmStateStats
|
||||||
Mark *XfrmMark
|
Mark *XfrmMark
|
||||||
OutputMark *XfrmMark
|
OutputMark *XfrmMark
|
||||||
|
SADir SADir
|
||||||
Ifid int
|
Ifid int
|
||||||
|
Pcpunum *uint32
|
||||||
Auth *XfrmStateAlgo
|
Auth *XfrmStateAlgo
|
||||||
Crypt *XfrmStateAlgo
|
Crypt *XfrmStateAlgo
|
||||||
Aead *XfrmStateAlgo
|
Aead *XfrmStateAlgo
|
||||||
|
@ -126,8 +128,8 @@ type XfrmState struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa XfrmState) String() string {
|
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",
|
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, SADir: %d, Ifid: %d, Pcpunum: %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)
|
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.SADir, sa.Ifid, *sa.Pcpunum, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay)
|
||||||
}
|
}
|
||||||
func (sa XfrmState) Print(stats bool) string {
|
func (sa XfrmState) Print(stats bool) string {
|
||||||
if !stats {
|
if !stats {
|
||||||
|
@ -333,11 +335,21 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.SADir != 0 {
|
||||||
|
saDir := nl.NewRtAttr(nl.XFRMA_SA_DIR, nl.Uint8Attr(uint8(state.SADir)))
|
||||||
|
req.AddData(saDir)
|
||||||
|
}
|
||||||
|
|
||||||
if state.Ifid != 0 {
|
if state.Ifid != 0 {
|
||||||
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
|
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
|
||||||
req.AddData(ifId)
|
req.AddData(ifId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.Pcpunum != nil {
|
||||||
|
pcpuNum := nl.NewRtAttr(nl.XFRMA_SA_PCPU, nl.Uint32Attr(uint32(*state.Pcpunum)))
|
||||||
|
req.AddData(pcpuNum)
|
||||||
|
}
|
||||||
|
|
||||||
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -459,6 +471,11 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
|
||||||
req.AddData(ifId)
|
req.AddData(ifId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.Pcpunum != nil {
|
||||||
|
pcpuNum := nl.NewRtAttr(nl.XFRMA_SA_PCPU, nl.Uint32Attr(uint32(*state.Pcpunum)))
|
||||||
|
req.AddData(pcpuNum)
|
||||||
|
}
|
||||||
|
|
||||||
resType := nl.XFRM_MSG_NEWSA
|
resType := nl.XFRM_MSG_NEWSA
|
||||||
if nlProto == nl.XFRM_MSG_DELSA {
|
if nlProto == nl.XFRM_MSG_DELSA {
|
||||||
resType = 0
|
resType = 0
|
||||||
|
@ -581,8 +598,13 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||||
if state.OutputMark.Mask == 0xffffffff {
|
if state.OutputMark.Mask == 0xffffffff {
|
||||||
state.OutputMark.Mask = 0
|
state.OutputMark.Mask = 0
|
||||||
}
|
}
|
||||||
|
case nl.XFRMA_SA_DIR:
|
||||||
|
state.SADir = SADir(attr.Value[0])
|
||||||
case nl.XFRMA_IF_ID:
|
case nl.XFRMA_IF_ID:
|
||||||
state.Ifid = int(native.Uint32(attr.Value))
|
state.Ifid = int(native.Uint32(attr.Value))
|
||||||
|
case nl.XFRMA_SA_PCPU:
|
||||||
|
pcpuNum := native.Uint32(attr.Value)
|
||||||
|
state.Pcpunum = &pcpuNum
|
||||||
case nl.XFRMA_REPLAY_VAL:
|
case nl.XFRMA_REPLAY_VAL:
|
||||||
if state.Replay == nil {
|
if state.Replay == nil {
|
||||||
state.Replay = new(XfrmReplayState)
|
state.Replay = new(XfrmReplayState)
|
||||||
|
|
|
@ -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.20250221194427-0af32151e72b
|
# github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9
|
||||||
## 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