fix(deps): update github.com/vishvananda/netlink digest to 9d88d83

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
renovate[bot]
2025-05-05 18:28:00 +00:00
committed by GitHub
parent 865c2c2b91
commit 1f7d8e2273
23 changed files with 395 additions and 29 deletions

2
go.mod
View File

@ -66,7 +66,7 @@ require (
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.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
golang.org/x/crypto v0.37.0
golang.org/x/net v0.39.0

5
go.sum
View File

@ -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/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/vishvananda/netlink v1.3.1-0.20250221194427-0af32151e72b h1:hYWtmuzlR0jpWu+ljWfPMi7oNiZ9x/D3GbBqgZTOhyI=
github.com/vishvananda/netlink v1.3.1-0.20250221194427-0af32151e72b/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9 h1:ZEjCI2kamoTYIx348/Nfco4c4NPvpq972DM2HMgnBgI=
github.com/vishvananda/netlink v1.3.1-0.20250425193846-9d88d8385bf9/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
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=

View File

@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"net"
"strings"
"syscall"
"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)
} else {
base := link.Attrs()
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
return fmt.Errorf("label must begin with interface name")
}
h.ensureIndex(base)
msg.Index = uint32(base.Index)
}

View File

@ -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
type MatchAll struct {
FilterAttrs

View File

@ -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_FD, nl.Uint32Attr(uint32(action.Fd)))
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:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
@ -752,6 +763,7 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
pedit := nl.TcPedit{}
toTcGen(action.Attrs(), &pedit.Sel.TcGen)
if action.SrcMacAddr != nil {
pedit.SetEthSrc(action.SrcMacAddr)
}
@ -825,6 +837,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &ConnmarkAction{}
case "csum":
action = &CsumAction{}
case "sample":
action = &SampleAction{}
case "gact":
action = &GenericAction{}
case "vlan":
@ -949,6 +963,18 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
tcTs := nl.DeserializeTcf(adatum.Value)
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":
switch adatum.Attr.Type {
case nl.TCA_GACT_PARMS:

View File

@ -1,3 +1,4 @@
//go:build !linux
// +build !linux
package netlink
@ -183,6 +184,10 @@ func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
return ErrNotImplemented
}
func (h *Handle) LinkSetIP6AddrGenMode(link Link, mode int) error {
return ErrNotImplemented
}
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
return ErrNotImplemented
}

View File

@ -86,5 +86,5 @@ func newIocltStringSetReq(linkName string) (*Ifreq, *ethtoolSset) {
// getSocketUDP returns file descriptor to new UDP socket
// It is used for communication with ioctl interface.
func getSocketUDP() (int, error) {
return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0)
return syscall.Socket(unix.AF_INET, unix.SOCK_DGRAM|unix.SOCK_CLOEXEC, 0)
}

View File

@ -348,13 +348,14 @@ type TuntapFlag uint16
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
type Tuntap struct {
LinkAttrs
Mode TuntapMode
Flags TuntapFlag
NonPersist bool
Queues int
Fds []*os.File
Owner uint32
Group uint32
Mode TuntapMode
Flags TuntapFlag
NonPersist bool
Queues int
DisabledQueues int
Fds []*os.File
Owner uint32
Group uint32
}
func (tuntap *Tuntap) Attrs() *LinkAttrs {
@ -1058,6 +1059,8 @@ type Geneve struct {
FlowBased bool
InnerProtoInherit bool
Df GeneveDf
PortLow int
PortHigh int
}
func (geneve *Geneve) Attrs() *LinkAttrs {

View File

@ -2670,9 +2670,38 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
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 {
if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
return fmt.Errorf("netkit doesn't support setting Ethernet")
if nk.Mode != NETKIT_MODE_L2 && (nk.LinkAttrs.HardwareAddr != nil || nk.peerLinkAttrs.HardwareAddr != nil) {
return fmt.Errorf("netkit only allows setting Ethernet in L2 mode")
}
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)))
}
}
if nk.peerLinkAttrs.HardwareAddr != nil {
peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(nk.peerLinkAttrs.HardwareAddr))
}
return nil
}
@ -3068,6 +3100,10 @@ func linkFlags(rawFlags uint32) net.Flags {
return f
}
type genevePortRange struct {
Lo, Hi uint16
}
func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
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))
}
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)))
}
@ -3125,6 +3170,13 @@ func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
geneve.FlowBased = true
case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
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)
case nl.IFLA_TUN_TYPE:
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:
tuntap.NonPersist = false
if uint8(datum.Value[0]) == 0 {
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))
}
}
}

View File

@ -1,5 +1,14 @@
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
// IFNAMSIZ, hence this minimalistic implementation
const (
@ -7,8 +16,136 @@ const (
IFNAMSIZ = 16
)
const TUN = "/dev/net/tun"
type ifReq struct {
Name [IFNAMSIZ]byte
Flags uint16
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
}

View File

@ -19,6 +19,14 @@ type Neigh struct {
Vlan int
VNI 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

View File

@ -349,6 +349,10 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
case NDA_MASTER:
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])
}
}

View File

@ -1,3 +1,4 @@
//go:build !linux
// +build !linux
package netlink
@ -144,6 +145,10 @@ func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
return ErrNotImplemented
}
func LinkSetIP6AddrGenMode(link Link, mode int) error {
return ErrNotImplemented
}
func LinkAdd(link Link) error {
return ErrNotImplemented
}

View File

@ -234,6 +234,7 @@ const (
IFLA_GENEVE_TTL_INHERIT
IFLA_GENEVE_DF
IFLA_GENEVE_INNER_PROTO_INHERIT
IFLA_GENEVE_PORT_RANGE
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
)
@ -818,3 +819,10 @@ const (
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
)

View File

@ -789,7 +789,7 @@ func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
// Returns the netlink socket on which Receive() method can be called
// to retrieve the messages from the kernel.
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 {
return nil, err
}

View File

@ -13,6 +13,7 @@ const (
SEG6_LOCAL_IIF
SEG6_LOCAL_OIF
SEG6_LOCAL_BPF
SEG6_LOCAL_VRFTABLE
__SEG6_LOCAL_MAX
)
const (

View File

@ -77,6 +77,17 @@ const (
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 (
TCA_PRIO_UNSPEC = iota
TCA_PRIO_MQ

View File

@ -78,10 +78,14 @@ const (
XFRMA_PROTO /* __u8 */
XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */
XFRMA_PAD
XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
XFRMA_SET_MARK /* __u32 */
XFRMA_SET_MARK_MASK /* __u32 */
XFRMA_IF_ID /* __u32 */
XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */
XFRMA_SET_MARK /* __u32 */
XFRMA_SET_MARK_MASK /* __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
)

View File

@ -45,7 +45,7 @@ type Encap interface {
Equal(Encap) bool
}
//Protocol describe what was the originator of the route
// Protocol describe what was the originator of the route
type RouteProtocol int
// Route represents a netlink route.
@ -70,6 +70,7 @@ type Route struct {
Via Destination
Realm int
MTU int
MTULock bool
Window int
Rtt int
RttVar int
@ -81,6 +82,7 @@ type Route struct {
InitCwnd int
Features int
RtoMin int
RtoMinLock bool
InitRwnd int
QuickACK int
Congctl string

View File

@ -270,6 +270,7 @@ type SEG6LocalEncap struct {
Action int
Segments []net.IP // from SRH in seg6_local_lwt
Table int // table id for End.T and End.DT6
VrfTable int // vrftable id for END.DT4 and END.DT6
InAddr net.IP
In6Addr net.IP
Iif int
@ -305,6 +306,9 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
case nl.SEG6_LOCAL_TABLE:
e.Table = int(native.Uint32(attr.Value[0:4]))
e.Flags[nl.SEG6_LOCAL_TABLE] = true
case nl.SEG6_LOCAL_VRFTABLE:
e.VrfTable = int(native.Uint32(attr.Value[0:4]))
e.Flags[nl.SEG6_LOCAL_VRFTABLE] = true
case nl.SEG6_LOCAL_NH4:
e.InAddr = net.IP(attr.Value[0:4])
e.Flags[nl.SEG6_LOCAL_NH4] = true
@ -361,6 +365,15 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
native.PutUint32(attr[4:], uint32(e.Table))
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] {
attr := make([]byte, 4)
native.PutUint16(attr, 8)
@ -413,6 +426,11 @@ func (e *SEG6LocalEncap) String() string {
if e.Flags[nl.SEG6_LOCAL_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] {
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) {
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 true
@ -1072,6 +1090,10 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R
if route.MTU > 0 {
b := nl.Uint32Attr(uint32(route.MTU))
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 {
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 {
b := nl.Uint32Attr(uint32(route.RtoMin))
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 {
b := nl.Uint32Attr(uint32(route.InitRwnd))
@ -1440,6 +1466,9 @@ func deserializeRoute(m []byte) (Route, error) {
switch metric.Attr.Type {
case unix.RTAX_MTU:
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:
route.Window = int(native.Uint32(metric.Value[0:4]))
case unix.RTAX_RTT:
@ -1533,6 +1562,7 @@ type RouteGetOptions struct {
Iif string
IifIndex int
Oif string
OifIndex int
VrfName string
SrcAddr net.IP
UID *uint32
@ -1612,14 +1642,20 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
}
oifIndex := uint32(0)
if len(options.Oif) > 0 {
link, err := h.LinkByName(options.Oif)
if err != nil {
return nil, err
}
oifIndex = uint32(link.Attrs().Index)
} else if options.OifIndex > 0 {
oifIndex = uint32(options.OifIndex)
}
if oifIndex > 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(link.Attrs().Index))
native.PutUint32(b, oifIndex)
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
}

View File

@ -48,6 +48,14 @@ const (
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 {
switch m {
case XFRM_MODE_TRANSPORT:

View File

@ -113,7 +113,9 @@ type XfrmState struct {
Statistics XfrmStateStats
Mark *XfrmMark
OutputMark *XfrmMark
SADir SADir
Ifid int
Pcpunum *uint32
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
Aead *XfrmStateAlgo
@ -126,8 +128,8 @@ type XfrmState struct {
}
func (sa XfrmState) String() string {
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay)
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.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 {
if !stats {
@ -333,11 +335,21 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
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 {
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.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)
return err
}
@ -459,6 +471,11 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
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
if nlProto == nl.XFRM_MSG_DELSA {
resType = 0
@ -581,8 +598,13 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
if state.OutputMark.Mask == 0xffffffff {
state.OutputMark.Mask = 0
}
case nl.XFRMA_SA_DIR:
state.SADir = SADir(attr.Value[0])
case nl.XFRMA_IF_ID:
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:
if state.Replay == nil {
state.Replay = new(XfrmReplayState)

2
vendor/modules.txt vendored
View File

@ -996,7 +996,7 @@ github.com/vbauerster/mpb/v8
github.com/vbauerster/mpb/v8/cwriter
github.com/vbauerster/mpb/v8/decor
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
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl