Bump netlink

Signed-off-by: Adrian Moisey <adrian@changeover.za.net>
This commit is contained in:
Adrian Moisey
2025-03-16 13:13:59 +02:00
committed by Casey Callendrello
parent 35831f3d23
commit dcf43557ef
35 changed files with 766 additions and 239 deletions

View File

@@ -3,6 +3,7 @@ package netlink
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io/ioutil"
"net"
@@ -1807,20 +1808,20 @@ func (h *Handle) LinkDel(link Link) error {
}
func (h *Handle) linkByNameDump(name string) (Link, error) {
links, err := h.LinkList()
if err != nil {
return nil, err
links, executeErr := h.LinkList()
if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
return nil, executeErr
}
for _, link := range links {
if link.Attrs().Name == name {
return link, nil
return link, executeErr
}
// support finding interfaces also via altnames
for _, altName := range link.Attrs().AltNames {
if altName == name {
return link, nil
return link, executeErr
}
}
}
@@ -1828,25 +1829,33 @@ func (h *Handle) linkByNameDump(name string) (Link, error) {
}
func (h *Handle) linkByAliasDump(alias string) (Link, error) {
links, err := h.LinkList()
if err != nil {
return nil, err
links, executeErr := h.LinkList()
if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
return nil, executeErr
}
for _, link := range links {
if link.Attrs().Alias == alias {
return link, nil
return link, executeErr
}
}
return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)}
}
// LinkByName finds a link by name and returns a pointer to the object.
//
// If the kernel doesn't support IFLA_IFNAME, this method will fall back to
// filtering a dump of all link names. In this case, if the returned error is
// [ErrDumpInterrupted] the result may be missing or outdated.
func LinkByName(name string) (Link, error) {
return pkgHandle.LinkByName(name)
}
// LinkByName finds a link by name and returns a pointer to the object.
//
// If the kernel doesn't support IFLA_IFNAME, this method will fall back to
// filtering a dump of all link names. In this case, if the returned error is
// [ErrDumpInterrupted] the result may be missing or outdated.
func (h *Handle) LinkByName(name string) (Link, error) {
if h.lookupByDump {
return h.linkByNameDump(name)
@@ -1879,12 +1888,20 @@ func (h *Handle) LinkByName(name string) (Link, error) {
// LinkByAlias finds a link by its alias and returns a pointer to the object.
// If there are multiple links with the alias it returns the first one
//
// If the kernel doesn't support IFLA_IFALIAS, this method will fall back to
// filtering a dump of all link names. In this case, if the returned error is
// [ErrDumpInterrupted] the result may be missing or outdated.
func LinkByAlias(alias string) (Link, error) {
return pkgHandle.LinkByAlias(alias)
}
// LinkByAlias finds a link by its alias and returns a pointer to the object.
// If there are multiple links with the alias it returns the first one
//
// If the kernel doesn't support IFLA_IFALIAS, this method will fall back to
// filtering a dump of all link names. In this case, if the returned error is
// [ErrDumpInterrupted] the result may be missing or outdated.
func (h *Handle) LinkByAlias(alias string) (Link, error) {
if h.lookupByDump {
return h.linkByAliasDump(alias)
@@ -2246,6 +2263,10 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
break
}
}
case unix.IFLA_PARENT_DEV_NAME:
base.ParentDev = string(attr.Value[:len(attr.Value)-1])
case unix.IFLA_PARENT_DEV_BUS_NAME:
base.ParentDevBus = string(attr.Value[:len(attr.Value)-1])
}
}
@@ -2321,6 +2342,9 @@ func LinkList() ([]Link, error) {
// LinkList gets a list of link devices.
// Equivalent to: `ip link show`
//
// If the returned error is [ErrDumpInterrupted], results may be inconsistent
// or incomplete.
func (h *Handle) LinkList() ([]Link, error) {
// NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need
// to get the message ourselves to parse link type.
@@ -2331,9 +2355,9 @@ func (h *Handle) LinkList() ([]Link, error) {
attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
req.AddData(attr)
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
if err != nil {
return nil, err
msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
return nil, executeErr
}
var res []Link
@@ -2345,7 +2369,7 @@ func (h *Handle) LinkList() ([]Link, error) {
res = append(res, link)
}
return res, nil
return res, executeErr
}
// LinkUpdate is used to pass information back from LinkSubscribe()
@@ -2381,6 +2405,10 @@ type LinkSubscribeOptions struct {
// LinkSubscribeWithOptions work like LinkSubscribe but enable to
// provide additional options to modify the behavior. Currently, the
// namespace can be provided as well as an error callback.
//
// When options.ListExisting is true, options.ErrorCallback may be
// called with [ErrDumpInterrupted] to indicate that results from
// the initial dump of links may be inconsistent or incomplete.
func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error {
if options.Namespace == nil {
none := netns.None()
@@ -2440,6 +2468,9 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
continue
}
for _, m := range msgs {
if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 && cberr != nil {
cberr(ErrDumpInterrupted)
}
if m.Header.Type == unix.NLMSG_DONE {
continue
}
@@ -2640,8 +2671,8 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
}
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)
@@ -2649,6 +2680,8 @@ func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
data.AddRtAttr(nl.IFLA_NETKIT_SCRUB, nl.Uint32Attr(uint32(nk.Scrub)))
data.AddRtAttr(nl.IFLA_NETKIT_PEER_SCRUB, nl.Uint32Attr(uint32(nk.PeerScrub)))
if (flag & unix.NLM_F_EXCL) == 0 {
// Modifying peer link attributes will not take effect
@@ -2691,6 +2724,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
}
@@ -2709,6 +2745,12 @@ func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
case nl.IFLA_NETKIT_PEER_POLICY:
netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
case nl.IFLA_NETKIT_SCRUB:
netkit.supportsScrub = true
netkit.Scrub = NetkitScrub(native.Uint32(datum.Value[0:4]))
case nl.IFLA_NETKIT_PEER_SCRUB:
netkit.supportsScrub = true
netkit.PeerScrub = NetkitScrub(native.Uint32(datum.Value[0:4]))
}
}
}
@@ -2782,7 +2824,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_VXLAN_PORT_RANGE:
buf := bytes.NewBuffer(datum.Value[0:4])
var pr vxlanPortRange
if binary.Read(buf, binary.BigEndian, &pr) != nil {
if binary.Read(buf, binary.BigEndian, &pr) == nil {
vxlan.PortLow = int(pr.Lo)
vxlan.PortHigh = int(pr.Hi)
}
@@ -3006,7 +3048,6 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
// copied from pkg/net_linux.go
func linkFlags(rawFlags uint32) net.Flags {
var f net.Flags
if rawFlags&unix.IFF_UP != 0 {
@@ -3024,6 +3065,9 @@ func linkFlags(rawFlags uint32) net.Flags {
if rawFlags&unix.IFF_MULTICAST != 0 {
f |= net.FlagMulticast
}
if rawFlags&unix.IFF_RUNNING != 0 {
f |= net.FlagRunning
}
return f
}