diff --git a/.golangci.yml b/.golangci.yml index 8ba6f9d02..82e41c117 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,6 +15,7 @@ linters: enable: - contextcheck - durationcheck + - forbidigo - gci - ginkgolinter - gocritic @@ -39,6 +40,14 @@ linters-settings: - default - prefix(github.com/containernetworking) + forbidigo: + forbid: + # Copied from https://github.com/moby/moby/pull/48407 + - pkg: ^github.com/vishvananda/netlink$ + p: ^netlink\.(Handle\.)?(AddrList|BridgeVlanList|ChainList|ClassList|ConntrackTableList|ConntrackDeleteFilter$|ConntrackDeleteFilters|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByName|LinkByAlias|LinkList|LinkSubscribeWithOptions|NeighList$|NeighProxyList|NeighListExecute|NeighSubscribeWithOptions|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteList|RouteListFilteredIter|RuleListFiltered$|RouteSubscribeWithOptions|RuleList$|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|VDPAGetDevConfigList|VDPAGetDevList|VDPAGetMGMTDevList|XfrmPolicyList|XfrmStateList) + msg: Use internal netlinksafe package for EINTR handling. + analyze-types: true + run: timeout: 5m modules-download-mode: vendor diff --git a/go.mod b/go.mod index d81a6f492..a9fa368ae 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,10 @@ require ( github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/opencontainers/selinux v1.11.1 + github.com/pkg/errors v0.9.1 github.com/safchain/ethtool v0.5.10 - github.com/vishvananda/netlink v1.3.0 + github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 + github.com/vishvananda/netns v0.0.4 golang.org/x/sys v0.30.0 sigs.k8s.io/knftables v0.0.18 ) @@ -38,10 +40,8 @@ require ( github.com/mdlayher/packet v1.1.2 // indirect github.com/mdlayher/socket v0.5.1 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect - github.com/vishvananda/netns v0.0.4 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/sync v0.10.0 // indirect diff --git a/go.sum b/go.sum index d5dc9ac3f..5fc4bab01 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= -github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= -github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= +github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 h1:Y4egeTrP7sccowz2GWTJVtHlwkZippgBTpUmMteFUWQ= +github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/ip/addr_linux.go b/pkg/ip/addr_linux.go index b4db50b9a..aefa100cc 100644 --- a/pkg/ip/addr_linux.go +++ b/pkg/ip/addr_linux.go @@ -20,6 +20,8 @@ import ( "time" "github.com/vishvananda/netlink" + + "github.com/containernetworking/plugins/pkg/netlinksafe" ) const SETTLE_INTERVAL = 50 * time.Millisecond @@ -30,14 +32,14 @@ const SETTLE_INTERVAL = 50 * time.Millisecond // addresses are no longer tentative. // If any addresses are still tentative after timeout seconds, then error. func SettleAddresses(ifName string, timeout int) error { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to retrieve link: %v", err) } deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { - addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) if err != nil { return fmt.Errorf("could not list addresses: %v", err) } diff --git a/pkg/ip/link_linux.go b/pkg/ip/link_linux.go index e5bb6caff..8f677bf36 100644 --- a/pkg/ip/link_linux.go +++ b/pkg/ip/link_linux.go @@ -24,6 +24,7 @@ import ( "github.com/safchain/ethtool" "github.com/vishvananda/netlink" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/utils/sysctl" ) @@ -52,7 +53,7 @@ func makeVethPair(name, peer string, mtu int, mac string, hostNS ns.NetNS) (netl return nil, err } // Re-fetch the container link to get its creation-time parameters, e.g. index and mac - veth2, err := netlink.LinkByName(name) + veth2, err := netlinksafe.LinkByName(name) if err != nil { netlink.LinkDel(veth) // try and clean up the link if possible. return nil, err @@ -62,7 +63,7 @@ func makeVethPair(name, peer string, mtu int, mac string, hostNS ns.NetNS) (netl } func peerExists(name string) bool { - if _, err := netlink.LinkByName(name); err != nil { + if _, err := netlinksafe.LinkByName(name); err != nil { return false } return true @@ -114,7 +115,7 @@ func RandomVethName() (string, error) { } func RenameLink(curName, newName string) error { - link, err := netlink.LinkByName(curName) + link, err := netlinksafe.LinkByName(curName) if err == nil { err = netlink.LinkSetName(link, newName) } @@ -145,7 +146,7 @@ func SetupVethWithName(contVethName, hostVethName string, mtu int, contVethMac s var hostVeth netlink.Link err = hostNS.Do(func(_ ns.NetNS) error { - hostVeth, err = netlink.LinkByName(hostVethName) + hostVeth, err = netlinksafe.LinkByName(hostVethName) if err != nil { return fmt.Errorf("failed to lookup %q in %q: %v", hostVethName, hostNS.Path(), err) } @@ -174,7 +175,7 @@ func SetupVeth(contVethName string, mtu int, contVethMac string, hostNS ns.NetNS // DelLinkByName removes an interface link. func DelLinkByName(ifName string) error { - iface, err := netlink.LinkByName(ifName) + iface, err := netlinksafe.LinkByName(ifName) if err != nil { if _, ok := err.(netlink.LinkNotFoundError); ok { return ErrLinkNotFound @@ -191,7 +192,7 @@ func DelLinkByName(ifName string) error { // DelLinkByNameAddr remove an interface and returns its addresses func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) { - iface, err := netlink.LinkByName(ifName) + iface, err := netlinksafe.LinkByName(ifName) if err != nil { if _, ok := err.(netlink.LinkNotFoundError); ok { return nil, ErrLinkNotFound @@ -199,7 +200,7 @@ func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) { return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err) } - addrs, err := netlink.AddrList(iface, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(iface, netlink.FAMILY_ALL) if err != nil { return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err) } @@ -222,7 +223,7 @@ func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) { // veth, or an error. This peer ifindex will only be valid in the peer's // network namespace. func GetVethPeerIfindex(ifName string) (netlink.Link, int, error) { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return nil, -1, fmt.Errorf("could not look up %q: %v", ifName, err) } diff --git a/pkg/ip/link_linux_test.go b/pkg/ip/link_linux_test.go index 90938c45c..1d1dfceab 100644 --- a/pkg/ip/link_linux_test.go +++ b/pkg/ip/link_linux_test.go @@ -22,9 +22,9 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/vishvananda/netlink" "github.com/containernetworking/plugins/pkg/ip" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -127,7 +127,7 @@ var _ = Describe("Link", func() { _ = containerNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - containerVethFromName, err := netlink.LinkByName(containerVethName) + containerVethFromName, err := netlinksafe.LinkByName(containerVethName) Expect(err).NotTo(HaveOccurred()) Expect(containerVethFromName.Attrs().Index).To(Equal(containerVeth.Index)) @@ -137,7 +137,7 @@ var _ = Describe("Link", func() { _ = hostNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - hostVethFromName, err := netlink.LinkByName(hostVethName) + hostVethFromName, err := netlinksafe.LinkByName(hostVethName) Expect(err).NotTo(HaveOccurred()) Expect(hostVethFromName.Attrs().Index).To(Equal(hostVeth.Index)) @@ -207,7 +207,7 @@ var _ = Describe("Link", func() { _ = containerNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(containerVethName) + _, err := netlinksafe.LinkByName(containerVethName) Expect(err).NotTo(HaveOccurred()) return nil @@ -216,7 +216,7 @@ var _ = Describe("Link", func() { _ = hostNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(hostVethName) + _, err := netlinksafe.LinkByName(hostVethName) Expect(err).NotTo(HaveOccurred()) return nil @@ -232,7 +232,7 @@ var _ = Describe("Link", func() { Expect(err).NotTo(HaveOccurred()) hostVethName = hostVeth.Name - link, err := netlink.LinkByName(containerVethName) + link, err := netlinksafe.LinkByName(containerVethName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(mac)) @@ -242,7 +242,7 @@ var _ = Describe("Link", func() { _ = hostNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(hostVethName) + link, err := netlinksafe.LinkByName(hostVethName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).NotTo(Equal(mac)) @@ -259,7 +259,7 @@ var _ = Describe("Link", func() { err := ip.DelLinkByName(containerVethName) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(containerVethName) + _, err = netlinksafe.LinkByName(containerVethName) Expect(err).To(HaveOccurred()) return nil @@ -268,7 +268,7 @@ var _ = Describe("Link", func() { _ = hostNetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(hostVethName) + _, err := netlinksafe.LinkByName(hostVethName) Expect(err).To(HaveOccurred()) return nil diff --git a/pkg/ip/utils_linux.go b/pkg/ip/utils_linux.go index 12a6175b4..2926def92 100644 --- a/pkg/ip/utils_linux.go +++ b/pkg/ip/utils_linux.go @@ -25,6 +25,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" ) func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) error { @@ -33,12 +34,12 @@ func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) ourAddr := netlink.Addr{IPNet: &ips.Address} match := false - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("Cannot find container link %v", ifName) } - addrList, err := netlink.AddrList(link, netlink.FAMILY_ALL) + addrList, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) if err != nil { return fmt.Errorf("Cannot obtain List of IP Addresses") } @@ -67,7 +68,7 @@ func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) family = netlink.FAMILY_V4 } - gwy, err := netlink.RouteListFiltered(family, findGwy, routeFilter) + gwy, err := netlinksafe.RouteListFiltered(family, findGwy, routeFilter) if err != nil { return fmt.Errorf("Error %v trying to find Gateway %v for interface %v", err, ips.Gateway, ifName) } @@ -108,7 +109,7 @@ func ValidateExpectedRoute(resultRoutes []*types.Route) error { return fmt.Errorf("Invalid static route found %v", route) } - wasFound, err := netlink.RouteListFiltered(family, find, routeFilter) + wasFound, err := netlinksafe.RouteListFiltered(family, find, routeFilter) if err != nil { return fmt.Errorf("Expected Route %v not route table lookup error %v", route, err) } diff --git a/pkg/ipam/ipam_linux.go b/pkg/ipam/ipam_linux.go index 61c673a7c..4c5af0456 100644 --- a/pkg/ipam/ipam_linux.go +++ b/pkg/ipam/ipam_linux.go @@ -23,6 +23,7 @@ import ( current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/plugins/pkg/ip" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/utils/sysctl" ) @@ -38,7 +39,7 @@ func ConfigureIface(ifName string, res *current.Result) error { return fmt.Errorf("no interfaces to configure") } - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to lookup %q: %v", ifName, err) } diff --git a/pkg/ipam/ipam_linux_test.go b/pkg/ipam/ipam_linux_test.go index ddccdac64..9afbcc1c5 100644 --- a/pkg/ipam/ipam_linux_test.go +++ b/pkg/ipam/ipam_linux_test.go @@ -24,6 +24,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -64,7 +65,7 @@ var _ = Describe("ConfigureIface", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(LINK_NAME) + _, err = netlinksafe.LinkByName(LINK_NAME) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -148,16 +149,16 @@ var _ = Describe("ConfigureIface", func() { err := ConfigureIface(LINK_NAME, result) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(LINK_NAME) + link, err := netlinksafe.LinkByName(LINK_NAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(LINK_NAME)) - v4addrs, err := netlink.AddrList(link, syscall.AF_INET) + v4addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(v4addrs).To(HaveLen(1)) Expect(ipNetEqual(v4addrs[0].IPNet, ipv4)).To(BeTrue()) - v6addrs, err := netlink.AddrList(link, syscall.AF_INET6) + v6addrs, err := netlinksafe.AddrList(link, syscall.AF_INET6) Expect(err).NotTo(HaveOccurred()) Expect(v6addrs).To(HaveLen(2)) @@ -171,7 +172,7 @@ var _ = Describe("ConfigureIface", func() { Expect(found).To(BeTrue()) // Ensure the v4 route, v6 route, and subnet route - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var v4found, v6found, v4Scopefound bool @@ -209,12 +210,12 @@ var _ = Describe("ConfigureIface", func() { err := ConfigureIface(LINK_NAME, result) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(LINK_NAME) + link, err := netlinksafe.LinkByName(LINK_NAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(LINK_NAME)) // Ensure the v4 route, v6 route, and subnet route - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var v4found, v6found, v4Tablefound bool @@ -239,7 +240,7 @@ var _ = Describe("ConfigureIface", func() { Table: routeTable, } - routes, err = netlink.RouteListFiltered(netlink.FAMILY_ALL, + routes, err = netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, routeFilter, netlink.RT_FILTER_TABLE) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/netlinksafe/netlink.go b/pkg/netlinksafe/netlink.go new file mode 100644 index 000000000..0f7f45b6d --- /dev/null +++ b/pkg/netlinksafe/netlink.go @@ -0,0 +1,321 @@ +// Package netlinksafe wraps vishvandanda/netlink functions that may return EINTR. +// +// A Handle instantiated using [NewHandle] or [NewHandleAt] can be used in place +// of a netlink.Handle, it's a wrapper that replaces methods that need to be +// wrapped. Functions that use the package handle need to be called as "netlinksafe.X" +// instead of "netlink.X". +// +// The wrapped functions currently return EINTR when NLM_F_DUMP_INTR flagged +// in a netlink response, meaning something changed during the dump so results +// may be incomplete or inconsistent. +// +// At present, the possibly incomplete/inconsistent results are not returned +// by netlink functions along with the EINTR. So, it's not possible to do +// anything but retry. After maxAttempts the EINTR will be returned to the +// caller. +package netlinksafe + +import ( + "log" + + "github.com/pkg/errors" + "github.com/vishvananda/netlink" + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" +) + +// Arbitrary limit on max attempts at netlink calls if they are repeatedly interrupted. +const maxAttempts = 5 + +type Handle struct { + *netlink.Handle +} + +func NewHandle(nlFamilies ...int) (Handle, error) { + nlh, err := netlink.NewHandle(nlFamilies...) + if err != nil { + return Handle{}, err + } + return Handle{nlh}, nil +} + +func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (Handle, error) { + nlh, err := netlink.NewHandleAt(ns, nlFamilies...) + if err != nil { + return Handle{}, err + } + return Handle{nlh}, nil +} + +func (h Handle) Close() { + if h.Handle != nil { + h.Handle.Close() + } +} + +func retryOnIntr(f func() error) { + for attempt := 0; attempt < maxAttempts; attempt++ { + if err := f(); !errors.Is(err, netlink.ErrDumpInterrupted) { + return + } + } + log.Printf("netlink call interrupted after %d attempts", maxAttempts) +} + +func discardErrDumpInterrupted(err error) error { + if errors.Is(err, netlink.ErrDumpInterrupted) { + // The netlink function has returned possibly-inconsistent data along with the + // error. Discard the error and return the data. This restores the behaviour of + // the netlink package prior to v1.2.1, in which NLM_F_DUMP_INTR was ignored in + // the netlink response. + log.Printf("discarding ErrDumpInterrupted: %+v", errors.WithStack(err)) + return nil + } + return err +} + +// AddrList calls netlink.AddrList, retrying if necessary. +func AddrList(link netlink.Link, family int) ([]netlink.Addr, error) { + var addrs []netlink.Addr + var err error + retryOnIntr(func() error { + addrs, err = netlink.AddrList(link, family) //nolint:forbidigo + return err + }) + return addrs, discardErrDumpInterrupted(err) +} + +// LinkByName calls h.Handle.LinkByName, retrying if necessary. The netlink function +// doesn't normally ask the kernel for a dump of links. But, on an old kernel, it +// will do as a fallback and that dump may get inconsistent results. +func (h Handle) LinkByName(name string) (netlink.Link, error) { + var link netlink.Link + var err error + retryOnIntr(func() error { + link, err = h.Handle.LinkByName(name) //nolint:forbidigo + return err + }) + return link, discardErrDumpInterrupted(err) +} + +// LinkByName calls netlink.LinkByName, retrying if necessary. The netlink +// function doesn't normally ask the kernel for a dump of links. But, on an old +// kernel, it will do as a fallback and that dump may get inconsistent results. +func LinkByName(name string) (netlink.Link, error) { + var link netlink.Link + var err error + retryOnIntr(func() error { + link, err = netlink.LinkByName(name) //nolint:forbidigo + return err + }) + return link, discardErrDumpInterrupted(err) +} + +// LinkList calls h.Handle.LinkList, retrying if necessary. +func (h Handle) LinkList() ([]netlink.Link, error) { + var links []netlink.Link + var err error + retryOnIntr(func() error { + links, err = h.Handle.LinkList() //nolint:forbidigo + return err + }) + return links, discardErrDumpInterrupted(err) +} + +// LinkList calls netlink.Handle.LinkList, retrying if necessary. +func LinkList() ([]netlink.Link, error) { + var links []netlink.Link + var err error + retryOnIntr(func() error { + links, err = netlink.LinkList() //nolint:forbidigo + return err + }) + return links, discardErrDumpInterrupted(err) +} + +// RouteList calls h.Handle.RouteList, retrying if necessary. +func (h Handle) RouteList(link netlink.Link, family int) ([]netlink.Route, error) { + var routes []netlink.Route + var err error + retryOnIntr(func() error { + routes, err = h.Handle.RouteList(link, family) //nolint:forbidigo + return err + }) + return routes, err +} + +// RouteList calls netlink.RouteList, retrying if necessary. +func RouteList(link netlink.Link, family int) ([]netlink.Route, error) { + var route []netlink.Route + var err error + retryOnIntr(func() error { + route, err = netlink.RouteList(link, family) //nolint:forbidigo + return err + }) + return route, discardErrDumpInterrupted(err) +} + +// BridgeVlanList calls netlink.BridgeVlanList, retrying if necessary. +func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { + var err error + var info map[int32][]*nl.BridgeVlanInfo + retryOnIntr(func() error { + info, err = netlink.BridgeVlanList() //nolint:forbidigo + return err + }) + return info, discardErrDumpInterrupted(err) +} + +// RouteListFiltered calls h.Handle.RouteListFiltered, retrying if necessary. +func (h Handle) RouteListFiltered(family int, filter *netlink.Route, filterMask uint64) ([]netlink.Route, error) { + var routes []netlink.Route + var err error + retryOnIntr(func() error { + routes, err = h.Handle.RouteListFiltered(family, filter, filterMask) //nolint:forbidigo + return err + }) + return routes, err +} + +// RouteListFiltered calls netlink.RouteListFiltered, retrying if necessary. +func RouteListFiltered(family int, filter *netlink.Route, filterMask uint64) ([]netlink.Route, error) { + var route []netlink.Route + var err error + retryOnIntr(func() error { + route, err = netlink.RouteListFiltered(family, filter, filterMask) //nolint:forbidigo + return err + }) + return route, discardErrDumpInterrupted(err) +} + +// QdiscList calls netlink.QdiscList, retrying if necessary. +func QdiscList(link netlink.Link) ([]netlink.Qdisc, error) { + var qdisc []netlink.Qdisc + var err error + retryOnIntr(func() error { + qdisc, err = netlink.QdiscList(link) //nolint:forbidigo + return err + }) + return qdisc, discardErrDumpInterrupted(err) +} + +// QdiscList calls h.Handle.QdiscList, retrying if necessary. +func (h *Handle) QdiscList(link netlink.Link) ([]netlink.Qdisc, error) { + var qdisc []netlink.Qdisc + var err error + retryOnIntr(func() error { + qdisc, err = h.Handle.QdiscList(link) //nolint:forbidigo + return err + }) + return qdisc, err +} + +// LinkGetProtinfo calls netlink.LinkGetProtinfo, retrying if necessary. +func LinkGetProtinfo(link netlink.Link) (netlink.Protinfo, error) { + var protinfo netlink.Protinfo + var err error + retryOnIntr(func() error { + protinfo, err = netlink.LinkGetProtinfo(link) //nolint:forbidigo + return err + }) + return protinfo, discardErrDumpInterrupted(err) +} + +// LinkGetProtinfo calls h.Handle.LinkGetProtinfo, retrying if necessary. +func (h *Handle) LinkGetProtinfo(link netlink.Link) (netlink.Protinfo, error) { + var protinfo netlink.Protinfo + var err error + retryOnIntr(func() error { + protinfo, err = h.Handle.LinkGetProtinfo(link) //nolint:forbidigo + return err + }) + return protinfo, err +} + +// RuleListFiltered calls netlink.RuleListFiltered, retrying if necessary. +func RuleListFiltered(family int, filter *netlink.Rule, filterMask uint64) ([]netlink.Rule, error) { + var rules []netlink.Rule + var err error + retryOnIntr(func() error { + rules, err = netlink.RuleListFiltered(family, filter, filterMask) //nolint:forbidigo + return err + }) + return rules, discardErrDumpInterrupted(err) +} + +// RuleListFiltered calls h.Handle.RuleListFiltered, retrying if necessary. +func (h *Handle) RuleListFiltered(family int, filter *netlink.Rule, filterMask uint64) ([]netlink.Rule, error) { + var rules []netlink.Rule + var err error + retryOnIntr(func() error { + rules, err = h.Handle.RuleListFiltered(family, filter, filterMask) //nolint:forbidigo + return err + }) + return rules, err +} + +// FilterList calls netlink.FilterList, retrying if necessary. +func FilterList(link netlink.Link, parent uint32) ([]netlink.Filter, error) { + var filters []netlink.Filter + var err error + retryOnIntr(func() error { + filters, err = netlink.FilterList(link, parent) //nolint:forbidigo + return err + }) + return filters, discardErrDumpInterrupted(err) +} + +// FilterList calls h.Handle.FilterList, retrying if necessary. +func (h *Handle) FilterList(link netlink.Link, parent uint32) ([]netlink.Filter, error) { + var filters []netlink.Filter + var err error + retryOnIntr(func() error { + filters, err = h.Handle.FilterList(link, parent) //nolint:forbidigo + return err + }) + return filters, err +} + +// RuleList calls netlink.RuleList, retrying if necessary. +func RuleList(family int) ([]netlink.Rule, error) { + var rules []netlink.Rule + var err error + retryOnIntr(func() error { + rules, err = netlink.RuleList(family) //nolint:forbidigo + return err + }) + return rules, discardErrDumpInterrupted(err) +} + +// RuleList calls h.Handle.RuleList, retrying if necessary. +func (h *Handle) RuleList(family int) ([]netlink.Rule, error) { + var rules []netlink.Rule + var err error + retryOnIntr(func() error { + rules, err = h.Handle.RuleList(family) //nolint:forbidigo + return err + }) + return rules, err +} + +// ConntrackDeleteFilters calls netlink.ConntrackDeleteFilters, retrying if necessary. +func ConntrackDeleteFilters(table netlink.ConntrackTableType, family netlink.InetFamily, filters ...netlink.CustomConntrackFilter) (uint, error) { + var deleted uint + var err error + retryOnIntr(func() error { + deleted, err = netlink.ConntrackDeleteFilters(table, family, filters...) //nolint:forbidigo + return err + }) + return deleted, discardErrDumpInterrupted(err) +} + +// ConntrackDeleteFilters calls h.Handle.ConntrackDeleteFilters, retrying if necessary. +func (h *Handle) ConntrackDeleteFilters(table netlink.ConntrackTableType, family netlink.InetFamily, filters ...netlink.CustomConntrackFilter) (uint, error) { + var deleted uint + var err error + retryOnIntr(func() error { + deleted, err = h.Handle.ConntrackDeleteFilters(table, family, filters...) //nolint:forbidigo + return err + }) + return deleted, err +} diff --git a/pkg/utils/conntrack.go b/pkg/utils/conntrack.go index 3dd0c2611..f4cc2627c 100644 --- a/pkg/utils/conntrack.go +++ b/pkg/utils/conntrack.go @@ -20,6 +20,8 @@ import ( "github.com/vishvananda/netlink" "golang.org/x/sys/unix" + + "github.com/containernetworking/plugins/pkg/netlinksafe" ) // Assigned Internet Protocol Numbers @@ -51,7 +53,7 @@ func DeleteConntrackEntriesForDstIP(dstIP string, protocol uint8) error { filter.AddIP(netlink.ConntrackOrigDstIP, ip) filter.AddProtocol(protocol) - _, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter) + _, err := netlinksafe.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter) if err != nil { return fmt.Errorf("error deleting connection tracking state for protocol: %d IP: %s, error: %v", protocol, ip, err) } @@ -65,7 +67,7 @@ func DeleteConntrackEntriesForDstPort(port uint16, protocol uint8, family netlin filter.AddProtocol(protocol) filter.AddPort(netlink.ConntrackOrigDstPort, port) - _, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter) + _, err := netlinksafe.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter) if err != nil { return fmt.Errorf("error deleting connection tracking state for protocol: %d Port: %d, error: %v", protocol, port, err) } diff --git a/plugins/ipam/dhcp/dhcp2_test.go b/plugins/ipam/dhcp/dhcp2_test.go index 7f424348f..0bbae33d6 100644 --- a/plugins/ipam/dhcp/dhcp2_test.go +++ b/plugins/ipam/dhcp/dhcp2_test.go @@ -27,6 +27,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -48,12 +49,12 @@ var _ = Describe("DHCP Multiple Lease Operations", func() { err = targetNS.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(contVethName0) + link, err := netlinksafe.LinkByName(contVethName0) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) - link1, err := netlink.LinkByName(contVethName1) + link1, err := netlinksafe.LinkByName(contVethName1) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link1) Expect(err).NotTo(HaveOccurred()) diff --git a/plugins/ipam/dhcp/dhcp_test.go b/plugins/ipam/dhcp/dhcp_test.go index 327e591a5..78cd11c9f 100644 --- a/plugins/ipam/dhcp/dhcp_test.go +++ b/plugins/ipam/dhcp/dhcp_test.go @@ -31,6 +31,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -181,7 +182,7 @@ var _ = Describe("DHCP Operations", func() { }) Expect(err).NotTo(HaveOccurred()) - host, err := netlink.LinkByName(hostVethName) + host, err := netlinksafe.LinkByName(hostVethName) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(host) Expect(err).NotTo(HaveOccurred()) @@ -197,7 +198,7 @@ var _ = Describe("DHCP Operations", func() { }) Expect(err).NotTo(HaveOccurred()) - cont, err := netlink.LinkByName(contVethName) + cont, err := netlinksafe.LinkByName(contVethName) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetNsFd(cont, int(targetNS.Fd())) Expect(err).NotTo(HaveOccurred()) @@ -210,7 +211,7 @@ var _ = Describe("DHCP Operations", func() { err = targetNS.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(contVethName) + link, err := netlinksafe.LinkByName(contVethName) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) @@ -455,16 +456,16 @@ func dhcpSetupOriginalNS() (chan bool, string, ns.NetNS, ns.NetNS, error) { err = netlink.LinkSetUp(veth) Expect(err).NotTo(HaveOccurred()) - bridgeLink, err := netlink.LinkByName(hostBridgeName) + bridgeLink, err := netlinksafe.LinkByName(hostBridgeName) Expect(err).NotTo(HaveOccurred()) - hostVethLink, err := netlink.LinkByName(hostVethName0) + hostVethLink, err := netlinksafe.LinkByName(hostVethName0) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetMaster(hostVethLink, bridgeLink.(*netlink.Bridge)) Expect(err).NotTo(HaveOccurred()) - cont, err := netlink.LinkByName(contVethName0) + cont, err := netlinksafe.LinkByName(contVethName0) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetNsFd(cont, int(targetNS.Fd())) Expect(err).NotTo(HaveOccurred()) @@ -483,16 +484,16 @@ func dhcpSetupOriginalNS() (chan bool, string, ns.NetNS, ns.NetNS, error) { err = netlink.LinkSetUp(veth1) Expect(err).NotTo(HaveOccurred()) - bridgeLink, err = netlink.LinkByName(hostBridgeName) + bridgeLink, err = netlinksafe.LinkByName(hostBridgeName) Expect(err).NotTo(HaveOccurred()) - hostVethLink1, err := netlink.LinkByName(hostVethName1) + hostVethLink1, err := netlinksafe.LinkByName(hostVethName1) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetMaster(hostVethLink1, bridgeLink.(*netlink.Bridge)) Expect(err).NotTo(HaveOccurred()) - cont1, err := netlink.LinkByName(contVethName1) + cont1, err := netlinksafe.LinkByName(contVethName1) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetNsFd(cont1, int(targetNS.Fd())) @@ -521,12 +522,12 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() { err = targetNS.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(contVethName0) + link, err := netlinksafe.LinkByName(contVethName0) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) - link1, err := netlink.LinkByName(contVethName1) + link1, err := netlinksafe.LinkByName(contVethName1) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link1) Expect(err).NotTo(HaveOccurred()) diff --git a/plugins/ipam/dhcp/lease.go b/plugins/ipam/dhcp/lease.go index 537bbdfcc..2bdf401dd 100644 --- a/plugins/ipam/dhcp/lease.go +++ b/plugins/ipam/dhcp/lease.go @@ -31,6 +31,7 @@ import ( "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" ) @@ -193,7 +194,7 @@ func AcquireLease( errCh <- ns.WithNetNSPath(netns, func(_ ns.NetNS) error { defer l.wg.Done() - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("error looking up %q: %v", ifName, err) } @@ -382,7 +383,7 @@ func checkLinkExistsWithBackoff(ctx context.Context, linkName string) (bool, err } func checkLinkByName(linkName string) (bool, error) { - _, err := netlink.LinkByName(linkName) + _, err := netlinksafe.LinkByName(linkName) if err != nil { var linkNotFoundErr *netlink.LinkNotFoundError = &netlink.LinkNotFoundError{} if errors.As(err, linkNotFoundErr) { diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index 905676e42..056a6983f 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -34,6 +34,7 @@ import ( "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" "github.com/containernetworking/plugins/pkg/link" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" "github.com/containernetworking/plugins/pkg/utils/sysctl" @@ -271,7 +272,7 @@ func calcGateways(result *current.Result, n *NetConf) (*gwInfo, *gwInfo, error) } func ensureAddr(br netlink.Link, family int, ipn *net.IPNet, forceAddress bool) error { - addrs, err := netlink.AddrList(br, family) + addrs, err := netlinksafe.AddrList(br, family) if err != nil && err != syscall.ENOENT { return fmt.Errorf("could not get list of IP addresses: %v", err) } @@ -324,7 +325,7 @@ func deleteAddr(br netlink.Link, ipn *net.IPNet) error { } func bridgeByName(name string) (*netlink.Bridge, error) { - l, err := netlink.LinkByName(name) + l, err := netlinksafe.LinkByName(name) if err != nil { return nil, fmt.Errorf("could not lookup %q: %v", name, err) } @@ -377,7 +378,7 @@ func ensureBridge(brName string, mtu int, promiscMode, vlanFiltering bool) (*net func ensureVlanInterface(br *netlink.Bridge, vlanID int, preserveDefaultVlan bool) (netlink.Link, error) { name := fmt.Sprintf("%s.%d", br.Name, vlanID) - brGatewayVeth, err := netlink.LinkByName(name) + brGatewayVeth, err := netlinksafe.LinkByName(name) if err != nil { if err.Error() != "Link not found" { return nil, fmt.Errorf("failed to find interface %q: %v", name, err) @@ -393,7 +394,7 @@ func ensureVlanInterface(br *netlink.Bridge, vlanID int, preserveDefaultVlan boo return nil, fmt.Errorf("faild to create vlan gateway %q: %v", name, err) } - brGatewayVeth, err = netlink.LinkByName(brGatewayIface.Name) + brGatewayVeth, err = netlinksafe.LinkByName(brGatewayIface.Name) if err != nil { return nil, fmt.Errorf("failed to lookup %q: %v", brGatewayIface.Name, err) } @@ -439,7 +440,7 @@ func setupVeth( } // need to lookup hostVeth again as its index has changed during ns move - hostVeth, err := netlink.LinkByName(hostIface.Name) + hostVeth, err := netlinksafe.LinkByName(hostIface.Name) if err != nil { return nil, nil, fmt.Errorf("failed to lookup %q: %v", hostIface.Name, err) } @@ -486,7 +487,7 @@ func setupVeth( } func removeDefaultVlan(hostVeth netlink.Link) error { - vlanInfo, err := netlink.BridgeVlanList() + vlanInfo, err := netlinksafe.BridgeVlanList() if err != nil { return err } @@ -695,7 +696,7 @@ func cmdAdd(args *skel.CmdArgs) error { } } else if !n.DisableContainerInterface { if err := netns.Do(func(_ ns.NetNS) error { - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) if err != nil { return fmt.Errorf("failed to retrieve link: %v", err) } @@ -710,7 +711,7 @@ func cmdAdd(args *skel.CmdArgs) error { } } - hostVeth, err := netlink.LinkByName(hostInterface.Name) + hostVeth, err := netlinksafe.LinkByName(hostInterface.Name) if err != nil { return err } @@ -721,7 +722,7 @@ func cmdAdd(args *skel.CmdArgs) error { for idx, sleep := range retries { time.Sleep(time.Duration(sleep) * time.Millisecond) - hostVeth, err = netlink.LinkByName(hostInterface.Name) + hostVeth, err = netlinksafe.LinkByName(hostInterface.Name) if err != nil { return err } @@ -858,7 +859,7 @@ func validateInterface(intf current.Interface, expectInSb bool) (cniBridgeIf, ne return ifFound, nil, fmt.Errorf("Interface name missing ") } - link, err := netlink.LinkByName(intf.Name) + link, err := netlinksafe.LinkByName(intf.Name) if err != nil { return ifFound, nil, fmt.Errorf("Interface name %s not found", intf.Name) } diff --git a/plugins/main/bridge/bridge_test.go b/plugins/main/bridge/bridge_test.go index 4e6939afd..744f046df 100644 --- a/plugins/main/bridge/bridge_test.go +++ b/plugins/main/bridge/bridge_test.go @@ -35,6 +35,7 @@ import ( types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/plugins/pkg/ip" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -411,9 +412,9 @@ func delBridgeAddrs(testNS ns.NetNS) { err := testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - br, err := netlink.LinkByName(BRNAME) + br, err := netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) - addrs, err := netlink.AddrList(br, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(br, netlink.FAMILY_ALL) Expect(err).NotTo(HaveOccurred()) for _, addr := range addrs { if !addr.IP.IsLinkLocalUnicast() { @@ -422,9 +423,9 @@ func delBridgeAddrs(testNS ns.NetNS) { } } - br, err = netlink.LinkByName(BRNAMEVLAN) + br, err = netlinksafe.LinkByName(BRNAMEVLAN) if err == nil { - addrs, err = netlink.AddrList(br, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(br, netlink.FAMILY_ALL) Expect(err).NotTo(HaveOccurred()) for _, addr := range addrs { if !addr.IP.IsLinkLocalUnicast() { @@ -443,9 +444,9 @@ func delVlanAddrs(testNS ns.NetNS, vlan int) { err := testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - vlanLink, err := netlink.LinkByName(fmt.Sprintf("%s.%d", BRNAME, vlan)) + vlanLink, err := netlinksafe.LinkByName(fmt.Sprintf("%s.%d", BRNAME, vlan)) Expect(err).NotTo(HaveOccurred()) - addrs, err := netlink.AddrList(vlanLink, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(vlanLink, netlink.FAMILY_ALL) Expect(err).NotTo(HaveOccurred()) for _, addr := range addrs { if !addr.IP.IsLinkLocalUnicast() { @@ -583,7 +584,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(result.Interfaces[2].Sandbox).To(Equal(tester.targetNS.Path())) // Make sure bridge link exists - link, err := netlink.LinkByName(result.Interfaces[0].Name) + link, err := netlinksafe.LinkByName(result.Interfaces[0].Name) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Bridge{})) @@ -593,7 +594,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, var vlanLink netlink.Link if !tc.isLayer2 && tc.vlan != 0 { // Make sure vlan link exists - vlanLink, err = netlink.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) + vlanLink, err = netlinksafe.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) Expect(err).NotTo(HaveOccurred()) Expect(vlanLink.Attrs().Name).To(Equal(fmt.Sprintf("%s.%d", BRNAME, tc.vlan))) Expect(vlanLink).To(BeAssignableToTypeOf(&netlink.Veth{})) @@ -601,7 +602,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Check the bridge dot vlan interface have the vlan tag peerLink, err := netlink.LinkByIndex(vlanLink.Attrs().Index - 1) Expect(err).NotTo(HaveOccurred()) - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -621,9 +622,9 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Ensure bridge has expected gateway address(es) var addrs []netlink.Addr if tc.vlan == 0 { - addrs, err = netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_ALL) } else { - addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(vlanLink, netlink.FAMILY_ALL) } Expect(err).NotTo(HaveOccurred()) Expect(addrs).ToNot(BeEmpty()) @@ -644,7 +645,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, } // Check for the veth link in the main namespace - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() Expect(err).NotTo(HaveOccurred()) if !tc.isLayer2 && tc.vlan != 0 { Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback @@ -652,18 +653,18 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback } - link, err = netlink.LinkByName(result.Interfaces[1].Name) + link, err = netlinksafe.LinkByName(result.Interfaces[1].Name) Expect(err).NotTo(HaveOccurred()) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) tester.vethName = result.Interfaces[1].Name - protInfo, err := netlink.LinkGetProtinfo(link) + protInfo, err := netlinksafe.LinkGetProtinfo(link) Expect(err).NotTo(HaveOccurred()) Expect(protInfo.Isolated).To(Equal(tc.portIsolation), "link isolation should be on when portIsolation is set") // check vlan exist on the veth interface if tc.vlan != 0 { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -675,7 +676,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, // check VlanTrunks exist on the veth interface if tc.vlanTrunk != nil { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -713,17 +714,17 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) assertContainerInterfaceLinkState(&tc, link) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(err).NotTo(HaveOccurred()) assertIPv6Addresses(&tc, addrs, expCIDRsV6) @@ -738,7 +739,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -800,16 +801,16 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, _ string) { err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local Expect(err).NotTo(HaveOccurred()) // Ignore link local address which may or may not be @@ -823,7 +824,7 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, _ string) { Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -870,7 +871,7 @@ func (tester *testerV10x) cmdDelTest(tc testCase, dataDir string) { err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -881,7 +882,7 @@ func (tester *testerV10x) cmdDelTest(tc testCase, dataDir string) { err = tester.testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(tester.vethName) + link, err := netlinksafe.LinkByName(tester.vethName) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -928,7 +929,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(result.Interfaces[2].Sandbox).To(Equal(tester.targetNS.Path())) // Make sure bridge link exists - link, err := netlink.LinkByName(result.Interfaces[0].Name) + link, err := netlinksafe.LinkByName(result.Interfaces[0].Name) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Bridge{})) @@ -938,7 +939,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, var vlanLink netlink.Link if !tc.isLayer2 && tc.vlan != 0 { // Make sure vlan link exists - vlanLink, err = netlink.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) + vlanLink, err = netlinksafe.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) Expect(err).NotTo(HaveOccurred()) Expect(vlanLink.Attrs().Name).To(Equal(fmt.Sprintf("%s.%d", BRNAME, tc.vlan))) Expect(vlanLink).To(BeAssignableToTypeOf(&netlink.Veth{})) @@ -946,7 +947,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Check the bridge dot vlan interface have the vlan tag peerLink, err := netlink.LinkByIndex(vlanLink.Attrs().Index - 1) Expect(err).NotTo(HaveOccurred()) - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -966,9 +967,9 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Ensure bridge has expected gateway address(es) var addrs []netlink.Addr if tc.vlan == 0 { - addrs, err = netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_ALL) } else { - addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(vlanLink, netlink.FAMILY_ALL) } Expect(err).NotTo(HaveOccurred()) Expect(addrs).ToNot(BeEmpty()) @@ -989,7 +990,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, } // Check for the veth link in the main namespace - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() Expect(err).NotTo(HaveOccurred()) if !tc.isLayer2 && tc.vlan != 0 { Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback @@ -997,14 +998,14 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback } - link, err = netlink.LinkByName(result.Interfaces[1].Name) + link, err = netlinksafe.LinkByName(result.Interfaces[1].Name) Expect(err).NotTo(HaveOccurred()) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) tester.vethName = result.Interfaces[1].Name // check vlan exist on the veth interface if tc.vlan != 0 { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1016,7 +1017,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, // check VlanTrunks exist on the veth interface if tc.vlanTrunk != nil { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1049,16 +1050,16 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(err).NotTo(HaveOccurred()) assertIPv6Addresses(&tc, addrs, expCIDRsV6) @@ -1073,7 +1074,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -1134,16 +1135,16 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, _ string) { err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(addrs).To(HaveLen(len(expCIDRsV6) + 1)) // add one for the link-local Expect(err).NotTo(HaveOccurred()) // Ignore link local address which may or may not be @@ -1157,7 +1158,7 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, _ string) { Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -1204,7 +1205,7 @@ func (tester *testerV04x) cmdDelTest(tc testCase, dataDir string) { err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -1215,7 +1216,7 @@ func (tester *testerV04x) cmdDelTest(tc testCase, dataDir string) { err = tester.testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(tester.vethName) + link, err := netlinksafe.LinkByName(tester.vethName) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -1262,7 +1263,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(result.Interfaces[2].Sandbox).To(Equal(tester.targetNS.Path())) // Make sure bridge link exists - link, err := netlink.LinkByName(result.Interfaces[0].Name) + link, err := netlinksafe.LinkByName(result.Interfaces[0].Name) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Bridge{})) @@ -1272,7 +1273,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, var vlanLink netlink.Link if !tc.isLayer2 && tc.vlan != 0 { // Make sure vlan link exists - vlanLink, err = netlink.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) + vlanLink, err = netlinksafe.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) Expect(err).NotTo(HaveOccurred()) Expect(vlanLink.Attrs().Name).To(Equal(fmt.Sprintf("%s.%d", BRNAME, tc.vlan))) Expect(vlanLink).To(BeAssignableToTypeOf(&netlink.Veth{})) @@ -1280,7 +1281,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Check the bridge dot vlan interface have the vlan tag peerLink, err := netlink.LinkByIndex(vlanLink.Attrs().Index - 1) Expect(err).NotTo(HaveOccurred()) - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1300,9 +1301,9 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, // Ensure bridge has expected gateway address(es) var addrs []netlink.Addr if tc.vlan == 0 { - addrs, err = netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_ALL) } else { - addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(vlanLink, netlink.FAMILY_ALL) } Expect(err).NotTo(HaveOccurred()) Expect(addrs).ToNot(BeEmpty()) @@ -1323,7 +1324,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, } // Check for the veth link in the main namespace - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() Expect(err).NotTo(HaveOccurred()) if !tc.isLayer2 && tc.vlan != 0 { Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback @@ -1331,14 +1332,14 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(links).To(HaveLen(3)) // Bridge, veth, and loopback } - link, err = netlink.LinkByName(result.Interfaces[1].Name) + link, err = netlinksafe.LinkByName(result.Interfaces[1].Name) Expect(err).NotTo(HaveOccurred()) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) tester.vethName = result.Interfaces[1].Name // check vlan exist on the veth interface if tc.vlan != 0 { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1350,7 +1351,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, // check VlanTrunks exist on the veth interface if tc.vlanTrunk != nil { - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(link.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1383,16 +1384,16 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(err).NotTo(HaveOccurred()) // Ignore link local address which may or may not be // ready when we read addresses. @@ -1405,7 +1406,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result, Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -1455,7 +1456,7 @@ func (tester *testerV03x) cmdDelTest(_ testCase, _ string) { err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -1466,7 +1467,7 @@ func (tester *testerV03x) cmdDelTest(_ testCase, _ string) { err = tester.testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(tester.vethName) + link, err := netlinksafe.LinkByName(tester.vethName) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -1523,7 +1524,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re Expect(err).NotTo(HaveOccurred()) // Make sure bridge link exists - link, err := netlink.LinkByName(BRNAME) + link, err := netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Bridge{})) @@ -1531,7 +1532,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re var vlanLink netlink.Link if !tc.isLayer2 && tc.vlan != 0 { // Make sure vlan link exists - vlanLink, err = netlink.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) + vlanLink, err = netlinksafe.LinkByName(fmt.Sprintf("%s.%d", BRNAME, tc.vlan)) Expect(err).NotTo(HaveOccurred()) Expect(vlanLink.Attrs().Name).To(Equal(fmt.Sprintf("%s.%d", BRNAME, tc.vlan))) Expect(vlanLink).To(BeAssignableToTypeOf(&netlink.Veth{})) @@ -1539,7 +1540,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re // Check the bridge dot vlan interface have the vlan tag peerLink, err := netlink.LinkByIndex(vlanLink.Attrs().Index - 1) Expect(err).NotTo(HaveOccurred()) - interfaceMap, err := netlink.BridgeVlanList() + interfaceMap, err := netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) vlans, isExist := interfaceMap[int32(peerLink.Attrs().Index)] Expect(isExist).To(BeTrue()) @@ -1559,9 +1560,9 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re // Ensure bridge has expected gateway address(es) var addrs []netlink.Addr if tc.vlan == 0 { - addrs, err = netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_ALL) } else { - addrs, err = netlink.AddrList(vlanLink, netlink.FAMILY_ALL) + addrs, err = netlinksafe.AddrList(vlanLink, netlink.FAMILY_ALL) } Expect(err).NotTo(HaveOccurred()) Expect(addrs).ToNot(BeEmpty()) @@ -1584,7 +1585,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re // Check for the veth link in the main namespace; can't // check the for the specific link since version 0.1.0 // doesn't report interfaces - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() Expect(err).NotTo(HaveOccurred()) if !tc.isLayer2 && tc.vlan != 0 { Expect(links).To(HaveLen(5)) // Bridge, Bridge vlan veth, veth, and loopback @@ -1594,7 +1595,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re // Grab the vlan map in the host NS for checking later if tc.vlan != 0 { - hostNSVlanMap, err = netlink.BridgeVlanList() + hostNSVlanMap, err = netlinksafe.BridgeVlanList() Expect(err).NotTo(HaveOccurred()) } return nil @@ -1612,16 +1613,16 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re err = tester.targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link).To(BeAssignableToTypeOf(&netlink.Veth{})) expCIDRsV4, expCIDRsV6 := tc.expectedCIDRs() - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(len(expCIDRsV4))) - addrs, err = netlink.AddrList(link, netlink.FAMILY_V6) + addrs, err = netlinksafe.AddrList(link, netlink.FAMILY_V6) Expect(err).NotTo(HaveOccurred()) // Ignore link local address which may or may not be // ready when we read addresses. @@ -1634,7 +1635,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re Expect(foundAddrs).To(Equal(len(expCIDRsV6))) // Ensure the default route(s) - routes, err := netlink.RouteList(link, 0) + routes, err := netlinksafe.RouteList(link, 0) Expect(err).NotTo(HaveOccurred()) var defaultRouteFound4, defaultRouteFound6 bool @@ -1707,7 +1708,7 @@ func (tester *testerV01xOr02x) cmdDelTest(tc testCase, _ string) { err = tester.testNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -1902,7 +1903,7 @@ var _ = Describe("bridge Operations", func() { Expect(bridge.Attrs().Name).To(Equal(BRNAME)) // Double check that the link was added - link, err := netlink.LinkByName(BRNAME) + link, err := netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link.Attrs().Promisc).To(Equal(0)) @@ -1921,7 +1922,7 @@ var _ = Describe("bridge Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(BRNAME) + link, err := netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) ifindex := link.Attrs().Index @@ -1935,7 +1936,7 @@ var _ = Describe("bridge Operations", func() { Expect(bridge.Attrs().Index).To(Equal(ifindex)) // Double check that the link has the same ifindex - link, err = netlink.LinkByName(BRNAME) + link, err = netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(BRNAME)) Expect(link.Attrs().Index).To(Equal(ifindex)) @@ -2210,7 +2211,7 @@ var _ = Describe("bridge Operations", func() { // Function to check IP address(es) on bridge checkBridgeIPs := func(cidr0, cidr1 string) { - addrs, err := netlink.AddrList(bridge, family) + addrs, err := netlinksafe.AddrList(bridge, family) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(expNumAddrs)) addr := addrs[0].IPNet.String() @@ -2294,7 +2295,7 @@ var _ = Describe("bridge Operations", func() { Expect(conf.ForceAddress).To(BeFalse()) // Check if promiscuous mode is set correctly - link, err := netlink.LinkByName("bridge0") + link, err := netlinksafe.LinkByName("bridge0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Promisc).To(Equal(1)) @@ -2320,13 +2321,13 @@ var _ = Describe("bridge Operations", func() { tc.cniVersion = ver _, _, err := setupBridge(tc.netConf()) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(BRNAME) + link, err := netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) origMac := link.Attrs().HardwareAddr cmdAddDelTest(originalNS, targetNS, tc, dataDir) - link, err = netlink.LinkByName(BRNAME) + link, err = netlinksafe.LinkByName(BRNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origMac)) return nil diff --git a/plugins/main/dummy/dummy.go b/plugins/main/dummy/dummy.go index 9a2ba0c9e..dadd57537 100644 --- a/plugins/main/dummy/dummy.go +++ b/plugins/main/dummy/dummy.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -58,7 +59,7 @@ func createDummy(ifName string, netns ns.NetNS) (*current.Interface, error) { err := netns.Do(func(_ ns.NetNS) error { // Re-fetch interface to get all properties/attributes - contDummy, err := netlink.LinkByName(ifName) + contDummy, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to fetch dummy%q: %v", ifName, err) } @@ -270,7 +271,7 @@ func validateCniContainerInterface(intf current.Interface) error { if intf.Name == "" { return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("Container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/dummy/dummy_test.go b/plugins/main/dummy/dummy_test.go index 594c5cac0..3d83f0348 100644 --- a/plugins/main/dummy/dummy_test.go +++ b/plugins/main/dummy/dummy_test.go @@ -32,6 +32,7 @@ import ( types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -187,7 +188,7 @@ var _ = Describe("dummy Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - m, err := netlink.LinkByName(MASTER_NAME) + m, err := netlinksafe.LinkByName(MASTER_NAME) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(m) Expect(err).NotTo(HaveOccurred()) @@ -224,7 +225,7 @@ var _ = Describe("dummy Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName("foobar0") + link, err := netlinksafe.LinkByName("foobar0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal("foobar0")) return nil @@ -281,7 +282,7 @@ var _ = Describe("dummy Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -291,7 +292,7 @@ var _ = Describe("dummy Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -341,7 +342,7 @@ var _ = Describe("dummy Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil diff --git a/plugins/main/host-device/host-device.go b/plugins/main/host-device/host-device.go index 330b44a36..8a101fe03 100644 --- a/plugins/main/host-device/host-device.go +++ b/plugins/main/host-device/host-device.go @@ -33,6 +33,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -257,7 +258,7 @@ func moveLinkIn(hostDev netlink.Link, containerNs ns.NetNS, containerIfName stri defer func() { if err != nil { // lookup the device again (index might have changed) - if hostDev, err := netlink.LinkByName(hostDevName); err == nil { + if hostDev, err := netlinksafe.LinkByName(hostDevName); err == nil { _ = netlink.LinkSetUp(hostDev) } } @@ -275,7 +276,7 @@ func moveLinkIn(hostDev netlink.Link, containerNs ns.NetNS, containerIfName stri // but host / container naming is easier to follow. if err = tempNS.Do(func(hostNS ns.NetNS) error { // lookup the device in tempNS (index might have changed) - tempNSDev, err := netlink.LinkByName(hostDevName) + tempNSDev, err := netlinksafe.LinkByName(hostDevName) if err != nil { return fmt.Errorf("failed to find %q in tempNS: %v", hostDevName, err) } @@ -321,13 +322,13 @@ func moveLinkIn(hostDev netlink.Link, containerNs ns.NetNS, containerIfName stri // Lookup the device again on error, the index might have changed defer func() { if err != nil { - tempNSDev, _ = netlink.LinkByName(containerIfName) + tempNSDev, _ = netlinksafe.LinkByName(containerIfName) } }() err = containerNs.Do(func(_ ns.NetNS) error { var err error - contDev, err = netlink.LinkByName(containerIfName) + contDev, err = netlinksafe.LinkByName(containerIfName) if err != nil { return fmt.Errorf("failed to find %q in container NS: %v", containerIfName, err) } @@ -375,7 +376,7 @@ func moveLinkOut(containerNs ns.NetNS, containerIfName string) error { if err != nil && contDev != nil && contDev.Attrs().Flags&net.FlagUp == net.FlagUp { containerNs.Do(func(_ ns.NetNS) error { // lookup the device again (index might have changed) - if contDev, err := netlink.LinkByName(containerIfName); err == nil { + if contDev, err := netlinksafe.LinkByName(containerIfName); err == nil { _ = netlink.LinkSetUp(contDev) } return nil @@ -386,7 +387,7 @@ func moveLinkOut(containerNs ns.NetNS, containerIfName string) error { err = containerNs.Do(func(_ ns.NetNS) error { var err error // Lookup the device in the containerNS - contDev, err = netlink.LinkByName(containerIfName) + contDev, err = netlinksafe.LinkByName(containerIfName) if err != nil { return fmt.Errorf("failed to find %q in containerNS: %v", containerIfName, err) } @@ -408,7 +409,7 @@ func moveLinkOut(containerNs ns.NetNS, containerIfName string) error { err = tempNS.Do(func(hostNS ns.NetNS) error { // Lookup the device in tempNS (index might have changed) - tempNSDev, err := netlink.LinkByName(containerIfName) + tempNSDev, err := netlinksafe.LinkByName(containerIfName) if err != nil { return fmt.Errorf("failed to find %q in tempNS: %v", containerIfName, err) } @@ -502,7 +503,7 @@ func linkFromPath(path string) (netlink.Link, error) { } if len(entries) > 0 { // grab the first net device - return netlink.LinkByName(entries[0].Name()) + return netlinksafe.LinkByName(entries[0].Name()) } return nil, fmt.Errorf("failed to find network device in path %s", path) } @@ -511,14 +512,14 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string, auxDev string) (netlin switch { case len(devname) > 0: - return netlink.LinkByName(devname) + return netlinksafe.LinkByName(devname) case len(hwaddr) > 0: hwAddr, err := net.ParseMAC(hwaddr) if err != nil { return nil, fmt.Errorf("failed to parse MAC address %q: %v", hwaddr, err) } - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() if err != nil { return nil, fmt.Errorf("failed to list node links: %v", err) } @@ -651,7 +652,7 @@ func validateCniContainerInterface(intf current.Interface) error { if intf.Name == "" { return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("Container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/host-device/host-device_test.go b/plugins/main/host-device/host-device_test.go index 895e29fff..d1a26f720 100644 --- a/plugins/main/host-device/host-device_test.go +++ b/plugins/main/host-device/host-device_test.go @@ -32,6 +32,7 @@ import ( types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -362,7 +363,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -408,7 +409,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -418,7 +419,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -431,7 +432,7 @@ var _ = Describe("base functionality", func() { }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(ifname) + _, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -452,7 +453,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -489,7 +490,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -499,7 +500,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -513,7 +514,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - conflictLink, err = netlink.LinkByName(ifname) + conflictLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(conflictLink) Expect(err).NotTo(HaveOccurred()) @@ -533,7 +534,7 @@ var _ = Describe("base functionality", func() { // assert container interface "eth0" still exists in target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -561,7 +562,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now back in the original namespace _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -638,7 +639,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -684,13 +685,13 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) // get the IP address of the interface in the target namespace - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) addr := addrs[0].IPNet.String() // assert that IP address is what we set @@ -702,7 +703,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -715,7 +716,7 @@ var _ = Describe("base functionality", func() { }) Expect(err).NotTo(HaveOccurred()) - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -750,7 +751,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -787,7 +788,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -797,7 +798,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -833,7 +834,7 @@ var _ = Describe("base functionality", func() { }) Expect(err).NotTo(HaveOccurred()) - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -942,7 +943,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -999,7 +1000,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -1045,13 +1046,13 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) // get the IP address of the interface in the target namespace - addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) addr := addrs[0].IPNet.String() // assert that IP address is what we set @@ -1063,7 +1064,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -1102,7 +1103,7 @@ var _ = Describe("base functionality", func() { }) Expect(err).NotTo(HaveOccurred()) - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -1123,7 +1124,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(ifname) + origLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -1160,7 +1161,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -1170,7 +1171,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now NOT in the original namespace anymore _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).To(HaveOccurred()) return nil }) @@ -1184,7 +1185,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - conflictLink, err = netlink.LinkByName(ifname) + conflictLink, err = netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(conflictLink) Expect(err).NotTo(HaveOccurred()) @@ -1204,7 +1205,7 @@ var _ = Describe("base functionality", func() { // assert container interface "eth0" still exists in target namespace and is up err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -1233,7 +1234,7 @@ var _ = Describe("base functionality", func() { // assert that dummy0 is now back in the original namespace _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(ifname) + _, err := netlinksafe.LinkByName(ifname) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -1257,7 +1258,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - origLink, err = netlink.LinkByName(hostIfname) + origLink, err = netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(origLink) Expect(err).NotTo(HaveOccurred()) @@ -1273,7 +1274,7 @@ var _ = Describe("base functionality", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - containerLink, err = netlink.LinkByName(containerAdditionalIfname) + containerLink, err = netlinksafe.LinkByName(containerAdditionalIfname) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(containerLink) Expect(err).NotTo(HaveOccurred()) @@ -1310,7 +1311,7 @@ var _ = Describe("base functionality", func() { // assert that host device is now in the target namespace and is up _ = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(cniName) + link, err := netlinksafe.LinkByName(cniName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(origLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -1330,7 +1331,7 @@ var _ = Describe("base functionality", func() { // assert container interface "eth0" still exists in target namespace and is up err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(containerAdditionalIfname) + link, err := netlinksafe.LinkByName(containerAdditionalIfname) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(containerLink.Attrs().HardwareAddr)) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) @@ -1341,7 +1342,7 @@ var _ = Describe("base functionality", func() { // assert that host device is now back in the original namespace _ = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(hostIfname) + _, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) return nil }) diff --git a/plugins/main/ipvlan/ipvlan.go b/plugins/main/ipvlan/ipvlan.go index 37736fd2c..9dbd78ada 100644 --- a/plugins/main/ipvlan/ipvlan.go +++ b/plugins/main/ipvlan/ipvlan.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" "github.com/containernetworking/plugins/pkg/utils/sysctl" @@ -127,11 +128,11 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf var m netlink.Link if conf.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) return err }) } else { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) } if err != nil { return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) @@ -173,7 +174,7 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf ipvlan.Name = ifName // Re-fetch ipvlan to get all properties/attributes - contIpvlan, err := netlink.LinkByName(ipvlan.Name) + contIpvlan, err := netlinksafe.LinkByName(ipvlan.Name) if err != nil { return fmt.Errorf("failed to refetch ipvlan %q: %v", ipvlan.Name, err) } @@ -190,7 +191,7 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf } func getDefaultRouteInterfaceName() (string, error) { - routeToDstIP, err := netlink.RouteList(nil, netlink.FAMILY_ALL) + routeToDstIP, err := netlinksafe.RouteList(nil, netlink.FAMILY_ALL) if err != nil { return "", err } @@ -411,11 +412,11 @@ func cmdCheck(args *skel.CmdArgs) error { if n.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - _, err = netlink.LinkByName(n.Master) + _, err = netlinksafe.LinkByName(n.Master) return err }) } else { - _, err = netlink.LinkByName(n.Master) + _, err = netlinksafe.LinkByName(n.Master) } if err != nil { @@ -454,7 +455,7 @@ func validateCniContainerInterface(intf current.Interface, modeExpected string) if intf.Name == "" { return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("Container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/ipvlan/ipvlan_test.go b/plugins/main/ipvlan/ipvlan_test.go index 09b1dc64d..f20d50ba4 100644 --- a/plugins/main/ipvlan/ipvlan_test.go +++ b/plugins/main/ipvlan/ipvlan_test.go @@ -31,6 +31,7 @@ import ( types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -136,7 +137,7 @@ func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetN err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(args.IfName)) @@ -146,7 +147,7 @@ func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetN Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -198,7 +199,7 @@ func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetN err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -295,7 +296,7 @@ var _ = Describe("ipvlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(MASTER_NAME) + _, err = netlinksafe.LinkByName(MASTER_NAME) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -311,7 +312,7 @@ var _ = Describe("ipvlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(MASTER_NAME_INCONTAINER) + _, err = netlinksafe.LinkByName(MASTER_NAME_INCONTAINER) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -367,7 +368,7 @@ var _ = Describe("ipvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName("foobar0") + link, err := netlinksafe.LinkByName("foobar0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal("foobar0")) return nil @@ -475,7 +476,7 @@ var _ = Describe("ipvlan Operations", func() { err := currentNs.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(masterInterface) + link, err := netlinksafe.LinkByName(masterInterface) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) diff --git a/plugins/main/loopback/loopback.go b/plugins/main/loopback/loopback.go index 182e4e6b0..a2c428eb3 100644 --- a/plugins/main/loopback/loopback.go +++ b/plugins/main/loopback/loopback.go @@ -26,6 +26,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -58,7 +59,7 @@ func cmdAdd(args *skel.CmdArgs) error { args.IfName = "lo" // ignore config, this only works for loopback err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error { - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) if err != nil { return err // not tested } @@ -68,7 +69,7 @@ func cmdAdd(args *skel.CmdArgs) error { return err // not tested } - v4Addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + v4Addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) if err != nil { return err // not tested } @@ -82,7 +83,7 @@ func cmdAdd(args *skel.CmdArgs) error { } } - v6Addrs, err := netlink.AddrList(link, netlink.FAMILY_V6) + v6Addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V6) if err != nil { return err // not tested } @@ -145,7 +146,7 @@ func cmdDel(args *skel.CmdArgs) error { } args.IfName = "lo" // ignore config, this only works for loopback err := ns.WithNetNSPath(args.Netns, func(ns.NetNS) error { - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) if err != nil { return err // not tested } @@ -185,7 +186,7 @@ func cmdCheck(args *skel.CmdArgs) error { args.IfName = "lo" // ignore config, this only works for loopback return ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error { - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) if err != nil { return err } diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index f550be75c..a7d3c0d15 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -29,6 +29,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" "github.com/containernetworking/plugins/pkg/utils/sysctl" @@ -62,7 +63,7 @@ func init() { } func getDefaultRouteInterfaceName() (string, error) { - routeToDstIP, err := netlink.RouteList(nil, netlink.FAMILY_ALL) + routeToDstIP, err := netlinksafe.RouteList(nil, netlink.FAMILY_ALL) if err != nil { return "", err } @@ -156,11 +157,11 @@ func getMTUByName(ifName string, namespace string, inContainer bool) (int, error defer netns.Close() err = netns.Do(func(_ ns.NetNS) error { - link, err = netlink.LinkByName(ifName) + link, err = netlinksafe.LinkByName(ifName) return err }) } else { - link, err = netlink.LinkByName(ifName) + link, err = netlinksafe.LinkByName(ifName) } if err != nil { return 0, err @@ -209,11 +210,11 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter var m netlink.Link if conf.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) return err }) } else { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) } if err != nil { return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) @@ -269,7 +270,7 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter macvlan.Name = ifName // Re-fetch macvlan to get all properties/attributes - contMacvlan, err := netlink.LinkByName(ifName) + contMacvlan, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to refetch macvlan %q: %v", ifName, err) } @@ -363,7 +364,7 @@ func cmdAdd(args *skel.CmdArgs) error { } else { // For L2 just change interface status to up err = netns.Do(func(_ ns.NetNS) error { - macvlanInterfaceLink, err := netlink.LinkByName(args.IfName) + macvlanInterfaceLink, err := netlinksafe.LinkByName(args.IfName) if err != nil { return fmt.Errorf("failed to find interface name %q: %v", macvlanInterface.Name, err) } @@ -491,11 +492,11 @@ func cmdCheck(args *skel.CmdArgs) error { if n.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - _, err = netlink.LinkByName(n.Master) + _, err = netlinksafe.LinkByName(n.Master) return err }) } else { - _, err = netlink.LinkByName(n.Master) + _, err = netlinksafe.LinkByName(n.Master) } if err != nil { return fmt.Errorf("failed to lookup master %q: %v", n.Master, err) @@ -533,7 +534,7 @@ func validateCniContainerInterface(intf current.Interface, modeExpected string) if intf.Name == "" { return fmt.Errorf("container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/macvlan/macvlan_test.go b/plugins/main/macvlan/macvlan_test.go index 3341acf73..cd1461e3c 100644 --- a/plugins/main/macvlan/macvlan_test.go +++ b/plugins/main/macvlan/macvlan_test.go @@ -31,6 +31,7 @@ import ( types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -215,7 +216,7 @@ var _ = Describe("macvlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(MASTER_NAME) + _, err = netlinksafe.LinkByName(MASTER_NAME) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -231,7 +232,7 @@ var _ = Describe("macvlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(MASTER_NAME_INCONTAINER) + _, err = netlinksafe.LinkByName(MASTER_NAME_INCONTAINER) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -287,7 +288,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName("foobar0") + link, err := netlinksafe.LinkByName("foobar0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal("foobar0")) return nil @@ -343,7 +344,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -353,7 +354,7 @@ var _ = Describe("macvlan Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -375,7 +376,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -462,7 +463,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -472,7 +473,7 @@ var _ = Describe("macvlan Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(BeEmpty()) return nil @@ -494,7 +495,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -555,7 +556,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -565,7 +566,7 @@ var _ = Describe("macvlan Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -616,7 +617,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -654,7 +655,7 @@ var _ = Describe("macvlan Operations", func() { err := currentNs.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(masterInterface) + link, err := netlinksafe.LinkByName(masterInterface) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) @@ -702,7 +703,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -712,7 +713,7 @@ var _ = Describe("macvlan Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -734,7 +735,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -786,7 +787,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -794,7 +795,7 @@ var _ = Describe("macvlan Operations", func() { Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(BeEmpty()) return nil @@ -816,7 +817,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -871,7 +872,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -879,7 +880,7 @@ var _ = Describe("macvlan Operations", func() { Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(BeEmpty()) return nil @@ -901,7 +902,7 @@ var _ = Describe("macvlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 129146f21..9c88d9010 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -30,6 +30,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -147,7 +148,7 @@ func setupContainerVeth(netns ns.NetNS, ifName string, mtu int, pr *current.Resu func setupHostVeth(vethName string, result *current.Result) error { // hostVeth moved namespaces and may have a new ifindex - veth, err := netlink.LinkByName(vethName) + veth, err := netlinksafe.LinkByName(vethName) if err != nil { return fmt.Errorf("failed to lookup %q: %v", vethName, err) } @@ -390,7 +391,7 @@ func validateCniContainerInterface(intf current.Interface) error { if intf.Name == "" { return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("ptp: Container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/ptp/ptp_test.go b/plugins/main/ptp/ptp_test.go index 5caf83f6b..7cc20f107 100644 --- a/plugins/main/ptp/ptp_test.go +++ b/plugins/main/ptp/ptp_test.go @@ -22,13 +22,13 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -275,7 +275,7 @@ var _ = Describe("ptp Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) if mac != "" { Expect(mac).To(Equal(link.Attrs().HardwareAddr.String())) @@ -337,7 +337,7 @@ var _ = Describe("ptp Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil diff --git a/plugins/main/tap/tap.go b/plugins/main/tap/tap.go index f789952e0..b16bfdcdb 100644 --- a/plugins/main/tap/tap.go +++ b/plugins/main/tap/tap.go @@ -34,6 +34,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" "github.com/containernetworking/plugins/pkg/utils/sysctl" @@ -202,7 +203,7 @@ func createTap(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface } if err = ip.RenameLink(tmpName, ifName); err != nil { - link, err := netlink.LinkByName(tmpName) + link, err := netlinksafe.LinkByName(tmpName) if err != nil { netlink.LinkDel(link) return fmt.Errorf("failed to rename tap to %q: %v", ifName, err) @@ -211,13 +212,13 @@ func createTap(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface tap.Name = ifName // Re-fetch link to get all properties/attributes - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to refetch tap %q: %v", ifName, err) } if conf.Bridge != "" { - bridge, err := netlink.LinkByName(conf.Bridge) + bridge, err := netlinksafe.LinkByName(conf.Bridge) if err != nil { return fmt.Errorf("failed to get bridge %s: %v", conf.Bridge, err) } @@ -322,7 +323,7 @@ func cmdAdd(args *skel.CmdArgs) error { } else { // For L2 just change interface status to up err = netns.Do(func(_ ns.NetNS) error { - tapInterfaceLink, err := netlink.LinkByName(args.IfName) + tapInterfaceLink, err := netlinksafe.LinkByName(args.IfName) if err != nil { return fmt.Errorf("failed to find interface name %q: %v", tapInterface.Name, err) } diff --git a/plugins/main/tap/tap_test.go b/plugins/main/tap/tap_test.go index df1ba7656..a97265718 100644 --- a/plugins/main/tap/tap_test.go +++ b/plugins/main/tap/tap_test.go @@ -31,6 +31,7 @@ import ( types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -243,7 +244,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link.Type()).To(Equal(TYPETAP)) @@ -253,7 +254,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -302,7 +303,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -360,7 +361,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { }); err != nil { return err } - bridge, err = netlink.LinkByName(bridgeName) + bridge, err = netlinksafe.LinkByName(bridgeName) if err != nil { return err } @@ -391,7 +392,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) Expect(link.Type()).To(Equal(TYPETAP)) @@ -402,7 +403,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -425,7 +426,7 @@ var _ = Describe("Add, check, remove tap plugin", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil diff --git a/plugins/main/vlan/vlan.go b/plugins/main/vlan/vlan.go index f0e045779..75efa8fdc 100644 --- a/plugins/main/vlan/vlan.go +++ b/plugins/main/vlan/vlan.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -82,11 +83,11 @@ func getMTUByName(ifName string, namespace string, inContainer bool) (int, error defer netns.Close() err = netns.Do(func(_ ns.NetNS) error { - link, err = netlink.LinkByName(ifName) + link, err = netlinksafe.LinkByName(ifName) return err }) } else { - link, err = netlink.LinkByName(ifName) + link, err = netlinksafe.LinkByName(ifName) } if err != nil { return 0, err @@ -101,11 +102,11 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac var err error if conf.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) return err }) } else { - m, err = netlink.LinkByName(conf.Master) + m, err = netlinksafe.LinkByName(conf.Master) } if err != nil { @@ -149,7 +150,7 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac vlan.Name = ifName // Re-fetch interface to get all properties/attributes - contVlan, err := netlink.LinkByName(vlan.Name) + contVlan, err := netlinksafe.LinkByName(vlan.Name) if err != nil { return fmt.Errorf("failed to refetch vlan %q: %v", vlan.Name, err) } @@ -317,11 +318,11 @@ func cmdCheck(args *skel.CmdArgs) error { if conf.LinkContNs { err = netns.Do(func(_ ns.NetNS) error { - _, err = netlink.LinkByName(conf.Master) + _, err = netlinksafe.LinkByName(conf.Master) return err }) } else { - _, err = netlink.LinkByName(conf.Master) + _, err = netlinksafe.LinkByName(conf.Master) } if err != nil { @@ -361,7 +362,7 @@ func validateCniContainerInterface(intf current.Interface, vlanID int, mtu int) if intf.Name == "" { return fmt.Errorf("Container interface name missing in prevResult: %v", intf.Name) } - link, err = netlink.LinkByName(intf.Name) + link, err = netlinksafe.LinkByName(intf.Name) if err != nil { return fmt.Errorf("vlan: Container Interface name in prevResult: %s not found", intf.Name) } diff --git a/plugins/main/vlan/vlan_test.go b/plugins/main/vlan/vlan_test.go index 10533cf6e..956155578 100644 --- a/plugins/main/vlan/vlan_test.go +++ b/plugins/main/vlan/vlan_test.go @@ -31,6 +31,7 @@ import ( types020 "github.com/containernetworking/cni/pkg/types/020" types040 "github.com/containernetworking/cni/pkg/types/040" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator" @@ -194,7 +195,7 @@ var _ = Describe("vlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - m, err := netlink.LinkByName(MASTER_NAME) + m, err := netlinksafe.LinkByName(MASTER_NAME) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(m) Expect(err).NotTo(HaveOccurred()) @@ -212,7 +213,7 @@ var _ = Describe("vlan Operations", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - m, err := netlink.LinkByName(MASTER_NAME_INCONTAINER) + m, err := netlinksafe.LinkByName(MASTER_NAME_INCONTAINER) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(m) Expect(err).NotTo(HaveOccurred()) @@ -268,7 +269,7 @@ var _ = Describe("vlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName("foobar0") + link, err := netlinksafe.LinkByName("foobar0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal("foobar0")) Expect(link.Attrs().MTU).To(Equal(1500)) @@ -298,7 +299,7 @@ var _ = Describe("vlan Operations", func() { err := otherNs.Do(func(ns.NetNS) error { defer GinkgoRecover() - m, err := netlink.LinkByName(masterInterface) + m, err := netlinksafe.LinkByName(masterInterface) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetMTU(m, 1200) Expect(err).NotTo(HaveOccurred()) @@ -313,7 +314,7 @@ var _ = Describe("vlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName("foobar0") + link, err := netlinksafe.LinkByName("foobar0") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal("foobar0")) Expect(link.Attrs().MTU).To(Equal(1200)) @@ -375,7 +376,7 @@ var _ = Describe("vlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Name).To(Equal(IFNAME)) @@ -385,7 +386,7 @@ var _ = Describe("vlan Operations", func() { Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr)) } - addrs, err := netlink.AddrList(link, syscall.AF_INET) + addrs, err := netlinksafe.AddrList(link, syscall.AF_INET) Expect(err).NotTo(HaveOccurred()) Expect(addrs).To(HaveLen(1)) return nil @@ -440,7 +441,7 @@ var _ = Describe("vlan Operations", func() { err = targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).To(HaveOccurred()) Expect(link).To(BeNil()) return nil @@ -487,7 +488,7 @@ var _ = Describe("vlan Operations", func() { defer GinkgoRecover() // set master link's MTU to 1500 - link, err := netlink.LinkByName(masterInterface) + link, err := netlinksafe.LinkByName(masterInterface) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetMTU(link, 1500) Expect(err).NotTo(HaveOccurred()) diff --git a/plugins/meta/bandwidth/bandwidth_linux_test.go b/plugins/meta/bandwidth/bandwidth_linux_test.go index 9d2aa9cbc..0ea41d98c 100644 --- a/plugins/meta/bandwidth/bandwidth_linux_test.go +++ b/plugins/meta/bandwidth/bandwidth_linux_test.go @@ -31,6 +31,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -176,11 +177,11 @@ var _ = Describe("bandwidth test", func() { Expect(result.Interfaces[2].Name).To(Equal(ifbDeviceName)) Expect(result.Interfaces[2].Sandbox).To(Equal("")) - ifbLink, err := netlink.LinkByName(ifbDeviceName) + ifbLink, err := netlinksafe.LinkByName(ifbDeviceName) Expect(err).NotTo(HaveOccurred()) Expect(ifbLink.Attrs().MTU).To(Equal(hostIfaceMTU)) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(1)) @@ -190,10 +191,10 @@ var _ = Describe("bandwidth test", func() { Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2))) Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1))) - hostVethLink, err := netlink.LinkByName(hostIfname) + hostVethLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscFilters, err := netlink.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) + qdiscFilters, err := netlinksafe.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) Expect(err).NotTo(HaveOccurred()) Expect(qdiscFilters).To(HaveLen(1)) @@ -205,10 +206,10 @@ var _ = Describe("bandwidth test", func() { Expect(hostNs.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - ifbLink, err := netlink.LinkByName(hostIfname) + ifbLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(2)) @@ -266,7 +267,7 @@ var _ = Describe("bandwidth test", func() { _, out, err := testutils.CmdAdd(containerNs.Path(), args.ContainerID, ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) Expect(err).NotTo(HaveOccurred(), string(out)) - _, err = netlink.LinkByName(ifbDeviceName) + _, err = netlinksafe.LinkByName(ifbDeviceName) Expect(err).NotTo(HaveOccurred()) return nil })).To(Succeed()) @@ -274,10 +275,10 @@ var _ = Describe("bandwidth test", func() { Expect(hostNs.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - containerIfLink, err := netlink.LinkByName(hostIfname) + containerIfLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscs, err := netlink.QdiscList(containerIfLink) + qdiscs, err := netlinksafe.QdiscList(containerIfLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(2)) @@ -333,7 +334,7 @@ var _ = Describe("bandwidth test", func() { _, out, err := testutils.CmdAdd(containerNs.Path(), args.ContainerID, ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) Expect(err).NotTo(HaveOccurred(), string(out)) - _, err = netlink.LinkByName(ifbDeviceName) + _, err = netlinksafe.LinkByName(ifbDeviceName) Expect(err).To(HaveOccurred()) return nil })).To(Succeed()) @@ -341,10 +342,10 @@ var _ = Describe("bandwidth test", func() { Expect(hostNs.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - containerIfLink, err := netlink.LinkByName(hostIfname) + containerIfLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscs, err := netlink.QdiscList(containerIfLink) + qdiscs, err := netlinksafe.QdiscList(containerIfLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(1)) @@ -459,11 +460,11 @@ var _ = Describe("bandwidth test", func() { Expect(result.Interfaces[2].Name).To(Equal(ifbDeviceName)) Expect(result.Interfaces[2].Sandbox).To(Equal("")) - ifbLink, err := netlink.LinkByName(ifbDeviceName) + ifbLink, err := netlinksafe.LinkByName(ifbDeviceName) Expect(err).NotTo(HaveOccurred()) Expect(ifbLink.Attrs().MTU).To(Equal(hostIfaceMTU)) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(1)) @@ -473,10 +474,10 @@ var _ = Describe("bandwidth test", func() { Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2))) Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1))) - hostVethLink, err := netlink.LinkByName(hostIfname) + hostVethLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscFilters, err := netlink.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) + qdiscFilters, err := netlinksafe.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) Expect(err).NotTo(HaveOccurred()) Expect(qdiscFilters).To(HaveLen(1)) @@ -488,10 +489,10 @@ var _ = Describe("bandwidth test", func() { Expect(hostNs.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - ifbLink, err := netlink.LinkByName(hostIfname) + ifbLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(2)) @@ -609,7 +610,7 @@ var _ = Describe("bandwidth test", func() { err = testutils.CmdDel(containerNs.Path(), args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred(), string(out)) - _, err = netlink.LinkByName(ifbDeviceName) + _, err = netlinksafe.LinkByName(ifbDeviceName) Expect(err).To(HaveOccurred()) return nil @@ -680,11 +681,11 @@ var _ = Describe("bandwidth test", func() { Expect(result.Interfaces[4].Name).To(Equal(ifbDeviceName)) Expect(result.Interfaces[4].Sandbox).To(Equal("")) - ifbLink, err := netlink.LinkByName(ifbDeviceName) + ifbLink, err := netlinksafe.LinkByName(ifbDeviceName) Expect(err).NotTo(HaveOccurred()) Expect(ifbLink.Attrs().MTU).To(Equal(hostIfaceMTU)) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(1)) @@ -694,10 +695,10 @@ var _ = Describe("bandwidth test", func() { Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2))) Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1))) - hostVethLink, err := netlink.LinkByName(hostIfname) + hostVethLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscFilters, err := netlink.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) + qdiscFilters, err := netlinksafe.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) Expect(err).NotTo(HaveOccurred()) Expect(qdiscFilters).To(HaveLen(1)) @@ -709,10 +710,10 @@ var _ = Describe("bandwidth test", func() { Expect(hostNs.Do(func(_ ns.NetNS) error { defer GinkgoRecover() - ifbLink, err := netlink.LinkByName(hostIfname) + ifbLink, err := netlinksafe.LinkByName(hostIfname) Expect(err).NotTo(HaveOccurred()) - qdiscs, err := netlink.QdiscList(ifbLink) + qdiscs, err := netlinksafe.QdiscList(ifbLink) Expect(err).NotTo(HaveOccurred()) Expect(qdiscs).To(HaveLen(2)) diff --git a/plugins/meta/bandwidth/bandwidth_suite_test.go b/plugins/meta/bandwidth/bandwidth_suite_test.go index 0dc7ea7c9..cba203ece 100644 --- a/plugins/meta/bandwidth/bandwidth_suite_test.go +++ b/plugins/meta/bandwidth/bandwidth_suite_test.go @@ -30,6 +30,7 @@ import ( "github.com/onsi/gomega/gexec" "github.com/vishvananda/netlink" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" ) @@ -120,7 +121,7 @@ func createVeth(hostNs ns.NetNS, hostVethIfName string, containerNs ns.NetNS, co return fmt.Errorf("creating veth pair: %s", err) } - containerVeth, err := netlink.LinkByName(containerVethIfName) + containerVeth, err := netlinksafe.LinkByName(containerVethIfName) if err != nil { return fmt.Errorf("failed to find newly-created veth device %q: %v", containerVethIfName, err) } @@ -146,7 +147,7 @@ func createVeth(hostNs ns.NetNS, hostVethIfName string, containerNs ns.NetNS, co addr.Peer = peerAddr addr.Scope = int(netlink.SCOPE_LINK) - hostVeth, err := netlink.LinkByName(hostVethIfName) + hostVeth, err := netlinksafe.LinkByName(hostVethIfName) if err != nil { return fmt.Errorf("failed to find newly-created veth device %q: %v", containerVethIfName, err) } @@ -177,7 +178,7 @@ func createVeth(hostNs ns.NetNS, hostVethIfName string, containerNs ns.NetNS, co addr.Peer = peerAddr addr.Scope = int(netlink.SCOPE_LINK) - containerVeth, err := netlink.LinkByName(containerVethIfName) + containerVeth, err := netlinksafe.LinkByName(containerVethIfName) if err != nil { return fmt.Errorf("failed to find newly-created veth device %q: %v", containerVethIfName, err) } @@ -206,7 +207,7 @@ func createVethInOneNs(netNS ns.NetNS, vethName, peerName string) { return fmt.Errorf("failed to create veth pair: %v", err) } - _, err := netlink.LinkByName(peerName) + _, err := netlinksafe.LinkByName(peerName) if err != nil { return fmt.Errorf("failed to find newly-created veth device %q: %v", peerName, err) } @@ -217,7 +218,7 @@ func createVethInOneNs(netNS ns.NetNS, vethName, peerName string) { func createMacvlan(netNS ns.NetNS, master, macvlanName string) { err := netNS.Do(func(_ ns.NetNS) error { - m, err := netlink.LinkByName(master) + m, err := netlinksafe.LinkByName(master) if err != nil { return fmt.Errorf("failed to lookup master %q: %v", master, err) } @@ -235,7 +236,7 @@ func createMacvlan(netNS ns.NetNS, master, macvlanName string) { return fmt.Errorf("failed to create macvlan device: %s", err) } - _, err = netlink.LinkByName(macvlanName) + _, err = netlinksafe.LinkByName(macvlanName) if err != nil { return fmt.Errorf("failed to find newly-created macvlan device %q: %v", macvlanName, err) } diff --git a/plugins/meta/bandwidth/ifb_creator.go b/plugins/meta/bandwidth/ifb_creator.go index 604b42db2..aed88c3d7 100644 --- a/plugins/meta/bandwidth/ifb_creator.go +++ b/plugins/meta/bandwidth/ifb_creator.go @@ -22,6 +22,7 @@ import ( "github.com/vishvananda/netlink" "github.com/containernetworking/plugins/pkg/ip" + "github.com/containernetworking/plugins/pkg/netlinksafe" ) const latencyInMillis = 25 @@ -53,7 +54,7 @@ func TeardownIfb(deviceName string) error { } func CreateIngressQdisc(rateInBits, burstInBits uint64, hostDeviceName string) error { - hostDevice, err := netlink.LinkByName(hostDeviceName) + hostDevice, err := netlinksafe.LinkByName(hostDeviceName) if err != nil { return fmt.Errorf("get host device: %s", err) } @@ -61,11 +62,11 @@ func CreateIngressQdisc(rateInBits, burstInBits uint64, hostDeviceName string) e } func CreateEgressQdisc(rateInBits, burstInBits uint64, hostDeviceName string, ifbDeviceName string) error { - ifbDevice, err := netlink.LinkByName(ifbDeviceName) + ifbDevice, err := netlinksafe.LinkByName(ifbDeviceName) if err != nil { return fmt.Errorf("get ifb device: %s", err) } - hostDevice, err := netlink.LinkByName(hostDeviceName) + hostDevice, err := netlinksafe.LinkByName(hostDeviceName) if err != nil { return fmt.Errorf("get host device: %s", err) } diff --git a/plugins/meta/bandwidth/main.go b/plugins/meta/bandwidth/main.go index 27de7c86d..1df1ceb55 100644 --- a/plugins/meta/bandwidth/main.go +++ b/plugins/meta/bandwidth/main.go @@ -26,6 +26,7 @@ import ( current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/utils" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" @@ -120,7 +121,7 @@ func getIfbDeviceName(networkName string, containerID string) string { } func getMTU(deviceName string) (int, error) { - link, err := netlink.LinkByName(deviceName) + link, err := netlinksafe.LinkByName(deviceName) if err != nil { return -1, err } @@ -210,7 +211,7 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - ifbDevice, err := netlink.LinkByName(ifbDeviceName) + ifbDevice, err := netlinksafe.LinkByName(ifbDeviceName) if err != nil { return err } @@ -250,7 +251,7 @@ func main() { } func SafeQdiscList(link netlink.Link) ([]netlink.Qdisc, error) { - qdiscs, err := netlink.QdiscList(link) + qdiscs, err := netlinksafe.QdiscList(link) if err != nil { return nil, err } @@ -291,7 +292,7 @@ func cmdCheck(args *skel.CmdArgs) error { if err != nil { return err } - link, err := netlink.LinkByName(hostInterface.Name) + link, err := netlinksafe.LinkByName(hostInterface.Name) if err != nil { return err } @@ -339,7 +340,7 @@ func cmdCheck(args *skel.CmdArgs) error { ifbDeviceName := getIfbDeviceName(bwConf.Name, args.ContainerID) - ifbDevice, err := netlink.LinkByName(ifbDeviceName) + ifbDevice, err := netlinksafe.LinkByName(ifbDeviceName) if err != nil { return fmt.Errorf("get ifb device: %s", err) } diff --git a/plugins/meta/firewall/firewall_iptables_test.go b/plugins/meta/firewall/firewall_iptables_test.go index 6f4c76248..8849b552c 100644 --- a/plugins/meta/firewall/firewall_iptables_test.go +++ b/plugins/meta/firewall/firewall_iptables_test.go @@ -29,6 +29,7 @@ import ( types040 "github.com/containernetworking/cni/pkg/types/040" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -211,7 +212,7 @@ var _ = Describe("firewall plugin iptables backend", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(IFNAME) + _, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) return nil }) diff --git a/plugins/meta/portmap/portmap_integ_test.go b/plugins/meta/portmap/portmap_integ_test.go index 25b27deb3..dc519d969 100644 --- a/plugins/meta/portmap/portmap_integ_test.go +++ b/plugins/meta/portmap/portmap_integ_test.go @@ -31,7 +31,8 @@ import ( "github.com/vishvananda/netlink" "github.com/containernetworking/cni/libcni" - "github.com/containernetworking/cni/pkg/types/100" + types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -452,7 +453,7 @@ func testEchoServer(address, protocol string, port int, netns string) bool { } func getLocalIP() string { - addrs, err := netlink.AddrList(nil, netlink.FAMILY_V4) + addrs, err := netlinksafe.AddrList(nil, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) for _, addr := range addrs { diff --git a/plugins/meta/sbr/main.go b/plugins/meta/sbr/main.go index acfa24640..7379a01ea 100644 --- a/plugins/meta/sbr/main.go +++ b/plugins/meta/sbr/main.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -208,12 +209,12 @@ func getNextTableID(rules []netlink.Rule, routes []netlink.Route, candidateID in // doRoutes does all the work to set up routes and rules during an add. func doRoutes(ipCfgs []*current.IPConfig, iface string) error { // Get a list of rules and routes ready. - rules, err := netlink.RuleList(netlink.FAMILY_ALL) + rules, err := netlinksafe.RuleList(netlink.FAMILY_ALL) if err != nil { return fmt.Errorf("Failed to list all rules: %v", err) } - routes, err := netlink.RouteList(nil, netlink.FAMILY_ALL) + routes, err := netlinksafe.RouteList(nil, netlink.FAMILY_ALL) if err != nil { return fmt.Errorf("Failed to list all routes: %v", err) } @@ -224,7 +225,7 @@ func doRoutes(ipCfgs []*current.IPConfig, iface string) error { table := getNextTableID(rules, routes, firstTableID) log.Printf("First unreferenced table: %d", table) - link, err := netlink.LinkByName(iface) + link, err := netlinksafe.LinkByName(iface) if err != nil { return fmt.Errorf("Cannot find network interface %s: %v", iface, err) } @@ -232,7 +233,7 @@ func doRoutes(ipCfgs []*current.IPConfig, iface string) error { linkIndex := link.Attrs().Index // Get all routes for the interface in the default routing table - routes, err = netlink.RouteList(link, netlink.FAMILY_ALL) + routes, err = netlinksafe.RouteList(link, netlink.FAMILY_ALL) if err != nil { return fmt.Errorf("Unable to list routes: %v", err) } @@ -384,7 +385,7 @@ func tidyRules(iface string, table *int) error { var rules []netlink.Rule if table != nil { - rules, err = netlink.RuleListFiltered( + rules, err = netlinksafe.RuleListFiltered( netlink.FAMILY_ALL, &netlink.Rule{ Table: *table, @@ -396,14 +397,14 @@ func tidyRules(iface string, table *int) error { return fmt.Errorf("failed to list rules of table %d to tidy: %v", *table, err) } } else { - rules, err = netlink.RuleList(netlink.FAMILY_ALL) + rules, err = netlinksafe.RuleList(netlink.FAMILY_ALL) if err != nil { log.Printf("Failed to list all rules to tidy: %v", err) return fmt.Errorf("Failed to list all rules to tidy: %v", err) } } - link, err := netlink.LinkByName(iface) + link, err := netlinksafe.LinkByName(iface) if err != nil { // If interface is not found by any reason it's safe to ignore an error. Also, we don't need to raise an error // during cmdDel call according to CNI spec: @@ -416,7 +417,7 @@ func tidyRules(iface string, table *int) error { return fmt.Errorf("Failed to get link %s: %v", iface, err) } - addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL) + addrs, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) if err != nil { log.Printf("Failed to list all addrs: %v", err) return fmt.Errorf("Failed to list all addrs: %v", err) diff --git a/plugins/meta/sbr/sbr_linux_test.go b/plugins/meta/sbr/sbr_linux_test.go index 731f71d81..d0f872672 100644 --- a/plugins/meta/sbr/sbr_linux_test.go +++ b/plugins/meta/sbr/sbr_linux_test.go @@ -25,6 +25,7 @@ import ( "golang.org/x/sys/unix" "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -101,7 +102,7 @@ func readback(targetNs ns.NetNS, devNames []string) (netStatus, error) { log.Printf("Checking device %s", name) retVal.Devices[i].Name = name - link, err := netlink.LinkByName(name) + link, err := netlinksafe.LinkByName(name) if err != nil { return err } @@ -112,7 +113,7 @@ func readback(targetNs ns.NetNS, devNames []string) (netStatus, error) { Table: unix.RT_TABLE_UNSPEC, } - routes, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, + routes, err := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, routeFilter, netlink.RT_FILTER_OIF|netlink.RT_FILTER_TABLE) if err != nil { @@ -131,7 +132,7 @@ func readback(targetNs ns.NetNS, devNames []string) (netStatus, error) { retVal.Devices[i].Routes = routesNoLinkLocal } - rules, err := netlink.RuleList(netlink.FAMILY_ALL) + rules, err := netlinksafe.RuleList(netlink.FAMILY_ALL) if err != nil { return err } @@ -609,7 +610,7 @@ var _ = Describe("sbr test", func() { var rules []netlink.Rule err = targetNs.Do(func(_ ns.NetNS) error { var err error - rules, err = netlink.RuleListFiltered( + rules, err = netlinksafe.RuleListFiltered( netlink.FAMILY_ALL, &netlink.Rule{ Table: tableID, }, diff --git a/plugins/meta/tuning/tuning.go b/plugins/meta/tuning/tuning.go index 84e8d97bb..20b61ca60 100644 --- a/plugins/meta/tuning/tuning.go +++ b/plugins/meta/tuning/tuning.go @@ -35,6 +35,7 @@ import ( "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/cni/pkg/version" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" ) @@ -154,7 +155,7 @@ func changeMacAddr(ifName string, newMacAddr string) error { return fmt.Errorf("invalid args %v for MAC addr: %v", newMacAddr, err) } - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -180,7 +181,7 @@ func updateResultsMacAddr(config *TuningConf, ifName string, newMacAddr string) } func changePromisc(ifName string, val bool) error { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -192,7 +193,7 @@ func changePromisc(ifName string, val bool) error { } func changeMtu(ifName string, mtu int) error { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -200,7 +201,7 @@ func changeMtu(ifName string, mtu int) error { } func changeAllmulti(ifName string, val bool) error { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -212,7 +213,7 @@ func changeAllmulti(ifName string, val bool) error { } func changeTxQLen(ifName string, txQLen int) error { - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -221,7 +222,7 @@ func changeTxQLen(ifName string, txQLen int) error { func createBackup(ifName, containerID, backupPath string, tuningConf *TuningConf) error { config := configToRestore{} - link, err := netlink.LinkByName(ifName) + link, err := netlinksafe.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to get %q: %v", ifName, err) } @@ -281,7 +282,7 @@ func restoreBackup(ifName, containerID, backupPath string) error { var errStr []string - _, err = netlink.LinkByName(ifName) + _, err = netlinksafe.LinkByName(ifName) if err != nil { return nil } @@ -483,7 +484,7 @@ func cmdCheck(args *skel.CmdArgs) error { } } - link, err := netlink.LinkByName(args.IfName) + link, err := netlinksafe.LinkByName(args.IfName) if err != nil { return fmt.Errorf("Cannot find container link %v", args.IfName) } diff --git a/plugins/meta/tuning/tuning_test.go b/plugins/meta/tuning/tuning_test.go index 09a9a8349..ca6434568 100644 --- a/plugins/meta/tuning/tuning_test.go +++ b/plugins/meta/tuning/tuning_test.go @@ -29,6 +29,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -116,7 +117,7 @@ var _ = Describe("tuning plugin", func() { LinkAttrs: linkAttrs, }) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) beforeConf.Mac = link.Attrs().HardwareAddr.String() @@ -249,7 +250,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Promisc).To(Equal(1)) @@ -273,7 +274,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Promisc != 0).To(Equal(*beforeConf.Promisc)) @@ -330,7 +331,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Promisc).To(Equal(1)) @@ -338,7 +339,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Promisc != 0).To(Equal(*beforeConf.Promisc)) @@ -391,7 +392,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().MTU).To(Equal(1454)) @@ -415,7 +416,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().MTU).To(Equal(beforeConf.Mtu)) @@ -472,7 +473,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().MTU).To(Equal(1454)) @@ -480,7 +481,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().MTU).To(Equal(beforeConf.Mtu)) @@ -525,7 +526,7 @@ var _ = Describe("tuning plugin", func() { }) Expect(err).NotTo(HaveOccurred()) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().TxQLen).To(Equal(20000)) @@ -547,7 +548,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().TxQLen).To(Equal(*beforeConf.TxQLen)) @@ -604,7 +605,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().TxQLen).To(Equal(20000)) @@ -612,7 +613,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().TxQLen).To(Equal(*beforeConf.TxQLen)) @@ -667,7 +668,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) Expect(result.Interfaces[0].Mac).To(Equal(mac)) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) hw, err := net.ParseMAC(mac) Expect(err).NotTo(HaveOccurred()) @@ -693,7 +694,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac)) @@ -750,7 +751,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) hw, err := net.ParseMAC("c2:11:22:33:44:55") Expect(err).NotTo(HaveOccurred()) @@ -760,7 +761,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac)) @@ -813,7 +814,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) hw, err := net.ParseMAC("c2:11:22:33:44:66") Expect(err).NotTo(HaveOccurred()) @@ -839,7 +840,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac)) @@ -895,7 +896,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) hw, err := net.ParseMAC("c2:11:22:33:44:55") Expect(err).NotTo(HaveOccurred()) @@ -905,7 +906,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac)) @@ -962,7 +963,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) hw, err := net.ParseMAC("c2:11:22:33:44:77") Expect(err).NotTo(HaveOccurred()) @@ -993,7 +994,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac)) Expect(link.Attrs().MTU).To(Equal(beforeConf.Mtu)) @@ -1049,7 +1050,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().RawFlags & unix.IFF_ALLMULTI).NotTo(BeZero()) @@ -1073,7 +1074,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().RawFlags&unix.IFF_ALLMULTI != 0).To(Equal(*beforeConf.Allmulti)) @@ -1130,7 +1131,7 @@ var _ = Describe("tuning plugin", func() { Expect(result.IPs).To(HaveLen(1)) Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24")) - link, err := netlink.LinkByName(IFNAME) + link, err := netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().RawFlags & unix.IFF_ALLMULTI).NotTo(BeZero()) @@ -1138,7 +1139,7 @@ var _ = Describe("tuning plugin", func() { args.ContainerID, "", func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) - link, err = netlink.LinkByName(IFNAME) + link, err = netlinksafe.LinkByName(IFNAME) Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().RawFlags&unix.IFF_ALLMULTI != 0).To(Equal(*beforeConf.Allmulti)) diff --git a/plugins/meta/vrf/vrf.go b/plugins/meta/vrf/vrf.go index bc7a732ee..fb1ff92ad 100644 --- a/plugins/meta/vrf/vrf.go +++ b/plugins/meta/vrf/vrf.go @@ -21,11 +21,13 @@ import ( "time" "github.com/vishvananda/netlink" + + "github.com/containernetworking/plugins/pkg/netlinksafe" ) // findVRF finds a VRF link with the provided name. func findVRF(name string) (*netlink.Vrf, error) { - link, err := netlink.LinkByName(name) + link, err := netlinksafe.LinkByName(name) if err != nil { return nil, err } @@ -38,7 +40,7 @@ func findVRF(name string) (*netlink.Vrf, error) { // createVRF creates a new VRF and sets it up. func createVRF(name string, tableID uint32) (*netlink.Vrf, error) { - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() if err != nil { return nil, fmt.Errorf("createVRF: Failed to find links %v", err) } @@ -71,7 +73,7 @@ func createVRF(name string, tableID uint32) (*netlink.Vrf, error) { // assignedInterfaces returns the list of interfaces associated to the given vrf. func assignedInterfaces(vrf *netlink.Vrf) ([]netlink.Link, error) { - links, err := netlink.LinkList() + links, err := netlinksafe.LinkList() if err != nil { return nil, fmt.Errorf("getAssignedInterfaces: Failed to find links %v", err) } @@ -86,7 +88,7 @@ func assignedInterfaces(vrf *netlink.Vrf) ([]netlink.Link, error) { // addInterface adds the given interface to the VRF func addInterface(vrf *netlink.Vrf, intf string) error { - i, err := netlink.LinkByName(intf) + i, err := netlinksafe.LinkByName(intf) if err != nil { return fmt.Errorf("could not get link by name %s", intf) } @@ -114,7 +116,7 @@ func addInterface(vrf *netlink.Vrf, intf string) error { Scope: netlink.SCOPE_UNIVERSE, // Exclude local and connected routes } filterMask := netlink.RT_FILTER_OIF | netlink.RT_FILTER_SCOPE // Filter based on link index and scope - r, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, filter, filterMask) + r, err := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, filter, filterMask) if err != nil { return fmt.Errorf("failed getting all routes for %s", intf) } @@ -156,7 +158,7 @@ CONTINUE: // Waits for global IPV6 addresses to be added by the kernel. maxRetry := 10 for { - routesVRFTable, err := netlink.RouteListFiltered( + routesVRFTable, err := netlinksafe.RouteListFiltered( netlink.FAMILY_ALL, &netlink.Route{ Dst: &net.IPNet{ @@ -217,7 +219,7 @@ func findFreeRoutingTableID(links []netlink.Link) (uint32, error) { } func resetMaster(interfaceName string) error { - intf, err := netlink.LinkByName(interfaceName) + intf, err := netlinksafe.LinkByName(interfaceName) if err != nil { return fmt.Errorf("resetMaster: could not get link by name %s", interfaceName) } @@ -230,7 +232,7 @@ func resetMaster(interfaceName string) error { // getGlobalAddresses returns the global addresses of the given interface func getGlobalAddresses(link netlink.Link, family int) ([]netlink.Addr, error) { - addresses, err := netlink.AddrList(link, family) + addresses, err := netlinksafe.AddrList(link, family) if err != nil { return nil, fmt.Errorf("failed getting list of IP addresses for %s: %w", link.Attrs().Name, err) } diff --git a/plugins/meta/vrf/vrf_test.go b/plugins/meta/vrf/vrf_test.go index a38a6a05b..ff0d1be7d 100644 --- a/plugins/meta/vrf/vrf_test.go +++ b/plugins/meta/vrf/vrf_test.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/plugins/pkg/netlinksafe" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" ) @@ -101,7 +102,7 @@ var _ = Describe("vrf plugin", func() { LinkAttrs: la0, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(IF0Name) + _, err = netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) la1 := netlink.NewLinkAttrs() @@ -110,7 +111,7 @@ var _ = Describe("vrf plugin", func() { LinkAttrs: la1, }) Expect(err).NotTo(HaveOccurred()) - _, err = netlink.LinkByName(IF1Name) + _, err = netlinksafe.LinkByName(IF1Name) Expect(err).NotTo(HaveOccurred()) return nil }) @@ -202,7 +203,7 @@ var _ = Describe("vrf plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(routev6).NotTo(BeNil()) - link, err := netlink.LinkByName(IF0Name) + link, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) // Add IP addresses for network reachability @@ -214,14 +215,14 @@ var _ = Describe("vrf plugin", func() { IP: ipv6.IP, Mask: net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, } - routes, _ := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ + routes, _ := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ Dst: ipv6RouteDst, Table: 0, }, netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE) return err == nil && len(routes) >= 1 }, time.Second, 500*time.Millisecond).Should(BeTrue()) - ipAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + ipAddrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) // Check if address was assigned properly Expect(ipAddrs[0].IP.String()).To(Equal("10.0.0.2")) @@ -311,7 +312,7 @@ var _ = Describe("vrf plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(routev6).NotTo(BeNil()) - link, err := netlink.LinkByName(IF0Name) + link, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) // Add IP addresses for network reachability @@ -323,14 +324,14 @@ var _ = Describe("vrf plugin", func() { IP: ipv6.IP, Mask: net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, } - routes, _ := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ + routes, _ := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ Dst: ipv6RouteDst, Table: 0, }, netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE) return err == nil && len(routes) >= 1 }, time.Second, 500*time.Millisecond).Should(BeTrue()) - ipAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + ipAddrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) // Check if address was assigned properly Expect(ipAddrs[0].IP.String()).To(Equal("10.0.0.2")) @@ -381,7 +382,7 @@ var _ = Describe("vrf plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(routev6).NotTo(BeNil()) - link, err := netlink.LinkByName(IF1Name) + link, err := netlinksafe.LinkByName(IF1Name) Expect(err).NotTo(HaveOccurred()) // Add IP addresses for network reachability @@ -393,14 +394,14 @@ var _ = Describe("vrf plugin", func() { IP: ipv6.IP, Mask: net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, } - routes, _ := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ + routes, _ := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{ Dst: ipv6RouteDst, Table: 0, }, netlink.RT_FILTER_DST|netlink.RT_FILTER_TABLE) return err == nil && len(routes) >= 1 }, time.Second, 500*time.Millisecond).Should(BeTrue()) - ipAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + ipAddrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) // Check if address was assigned properly Expect(ipAddrs[0].IP.String()).To(Equal("10.0.0.3")) @@ -473,7 +474,7 @@ var _ = Describe("vrf plugin", func() { By("Setting the interface's master", func() { err := targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - l, err := netlink.LinkByName(IF0Name) + l, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) linkAttrs := netlink.NewLinkAttrs() linkAttrs.Name = "testrbridge" @@ -520,7 +521,7 @@ var _ = Describe("vrf plugin", func() { By("Setting the first interface's ip", func() { err := targetNS.Do(func(ns.NetNS) error { - l, err := netlink.LinkByName(IF0Name) + l, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) err = netlink.AddrAdd(l, addr0) @@ -551,7 +552,7 @@ var _ = Describe("vrf plugin", func() { By("Setting the second interface's ip", func() { err := targetNS.Do(func(ns.NetNS) error { - l, err := netlink.LinkByName(IF1Name) + l, err := netlinksafe.LinkByName(IF1Name) Expect(err).NotTo(HaveOccurred()) err = netlink.AddrAdd(l, addr1) @@ -584,9 +585,9 @@ var _ = Describe("vrf plugin", func() { defer GinkgoRecover() checkInterfaceOnVRF(vrf0, IF0Name) - link, err := netlink.LinkByName(IF0Name) + link, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) - addresses, err := netlink.AddrList(link, netlink.FAMILY_ALL) + addresses, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) Expect(err).NotTo(HaveOccurred()) Expect(addresses).To(HaveLen(1)) Expect(addresses[0].IP.Equal(addr0.IP)).To(BeTrue()) @@ -601,10 +602,10 @@ var _ = Describe("vrf plugin", func() { defer GinkgoRecover() checkInterfaceOnVRF(vrf0, IF0Name) - link, err := netlink.LinkByName(IF1Name) + link, err := netlinksafe.LinkByName(IF1Name) Expect(err).NotTo(HaveOccurred()) - addresses, err := netlink.AddrList(link, netlink.FAMILY_ALL) + addresses, err := netlinksafe.AddrList(link, netlink.FAMILY_ALL) Expect(err).NotTo(HaveOccurred()) Expect(addresses).To(HaveLen(1)) Expect(addresses[0].IP.Equal(addr1.IP)).To(BeTrue()) @@ -620,10 +621,10 @@ var _ = Describe("vrf plugin", func() { } err := targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - l0, err := netlink.LinkByName(vrf0) + l0, err := netlinksafe.LinkByName(vrf0) Expect(err).NotTo(HaveOccurred()) Expect(l0).To(BeAssignableToTypeOf(&netlink.Vrf{})) - l1, err := netlink.LinkByName(vrf1) + l1, err := netlinksafe.LinkByName(vrf1) Expect(err).NotTo(HaveOccurred()) Expect(l1).To(BeAssignableToTypeOf(&netlink.Vrf{})) @@ -670,7 +671,7 @@ var _ = Describe("vrf plugin", func() { err := targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - l, err := netlink.LinkByName(vrf0) + l, err := netlinksafe.LinkByName(vrf0) Expect(err).NotTo(HaveOccurred()) vrf := l.(*netlink.Vrf) Expect(vrf.Table).To(Equal(uint32(tableid0))) @@ -766,7 +767,7 @@ var _ = Describe("vrf plugin", func() { Expect(err).NotTo(HaveOccurred()) err = targetNS.Do(func(ns.NetNS) error { - link, err := netlink.LinkByName(IF0Name) + link, err := netlinksafe.LinkByName(IF0Name) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkDel(link) Expect(err).NotTo(HaveOccurred()) @@ -801,7 +802,7 @@ var _ = Describe("vrf plugin", func() { Expect(err).NotTo(HaveOccurred()) err = targetNS.Do(func(ns.NetNS) error { - link, err := netlink.LinkByName(IF1Name) + link, err := netlinksafe.LinkByName(IF1Name) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkDel(link) Expect(err).NotTo(HaveOccurred()) @@ -813,7 +814,7 @@ var _ = Describe("vrf plugin", func() { By("Checking that the VRF is removed", func() { targetNS.Do(func(ns.NetNS) error { defer GinkgoRecover() - _, err := netlink.LinkByName(VRF0Name) + _, err := netlinksafe.LinkByName(VRF0Name) Expect(err).To(HaveOccurred()) return nil }) @@ -1010,11 +1011,11 @@ func configWithRouteFor(name, intf, vrf, ip, route string) []byte { } func checkInterfaceOnVRF(vrfName, intfName string) { - vrf, err := netlink.LinkByName(vrfName) + vrf, err := netlinksafe.LinkByName(vrfName) Expect(err).NotTo(HaveOccurred()) Expect(vrf).To(BeAssignableToTypeOf(&netlink.Vrf{})) - link, err := netlink.LinkByName(intfName) + link, err := netlinksafe.LinkByName(intfName) Expect(err).NotTo(HaveOccurred()) masterIndx := link.Attrs().MasterIndex master, err := netlink.LinkByIndex(masterIndx) @@ -1023,20 +1024,20 @@ func checkInterfaceOnVRF(vrfName, intfName string) { } func checkRoutesOnVRF(vrfName, intfName string, addrStr string, routesToCheck ...string) { - l, err := netlink.LinkByName(vrfName) + l, err := netlinksafe.LinkByName(vrfName) Expect(err).NotTo(HaveOccurred()) Expect(l).To(BeAssignableToTypeOf(&netlink.Vrf{})) vrf, ok := l.(*netlink.Vrf) Expect(ok).To(BeTrue()) - link, err := netlink.LinkByName(intfName) + link, err := netlinksafe.LinkByName(intfName) Expect(err).NotTo(HaveOccurred()) err = netlink.LinkSetUp(link) Expect(err).NotTo(HaveOccurred()) - ipAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + ipAddrs, err := netlinksafe.AddrList(link, netlink.FAMILY_V4) Expect(err).NotTo(HaveOccurred()) Expect(ipAddrs).To(HaveLen(1)) Expect(ipAddrs[0].IP.String()).To(Equal(addrStr)) @@ -1045,7 +1046,7 @@ func checkRoutesOnVRF(vrfName, intfName string, addrStr string, routesToCheck .. Table: int(vrf.Table), } - routes, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, + routes, err := netlinksafe.RouteListFiltered(netlink.FAMILY_ALL, routeFilter, netlink.RT_FILTER_TABLE) Expect(err).NotTo(HaveOccurred()) diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 218ab2379..01c2306cb 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "strings" @@ -17,6 +18,7 @@ import ( // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func AddrAdd(link Link, addr *Addr) error { return pkgHandle.AddrAdd(link, addr) } @@ -27,6 +29,7 @@ func AddrAdd(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func (h *Handle) AddrAdd(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -38,6 +41,7 @@ func (h *Handle) AddrAdd(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func AddrReplace(link Link, addr *Addr) error { return pkgHandle.AddrReplace(link, addr) } @@ -48,6 +52,7 @@ func AddrReplace(link Link, addr *Addr) error { // // If `addr` is an IPv4 address and the broadcast address is not given, it // will be automatically computed based on the IP mask if /30 or larger. +// If `net.IPv4zero` is given as the broadcast address, broadcast is disabled. func (h *Handle) AddrReplace(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -56,18 +61,13 @@ func (h *Handle) AddrReplace(link Link, addr *Addr) error { // AddrDel will delete an IP address from a link device. // // Equivalent to: `ip addr del $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. func AddrDel(link Link, addr *Addr) error { return pkgHandle.AddrDel(link, addr) } // AddrDel will delete an IP address from a link device. -// Equivalent to: `ip addr del $addr dev $link` // -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. +// Equivalent to: `ip addr del $addr dev $link` func (h *Handle) AddrDel(link Link, addr *Addr) error { req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) return h.addrHandle(link, addr, req) @@ -141,6 +141,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error addr.Broadcast = calcBroadcast } + if net.IPv4zero.Equal(addr.Broadcast) { + addr.Broadcast = nil + } + if addr.Broadcast != nil { req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) } @@ -169,6 +173,9 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error // AddrList gets a list of IP addresses in the system. // Equivalent to: `ip addr show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func AddrList(link Link, family int) ([]Addr, error) { return pkgHandle.AddrList(link, family) } @@ -176,14 +183,17 @@ func AddrList(link Link, family int) ([]Addr, error) { // AddrList gets a list of IP addresses in the system. // Equivalent to: `ip addr show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) msg := nl.NewIfAddrmsg(family) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } indexFilter := 0 @@ -212,7 +222,7 @@ func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { res = append(res, addr) } - return res, nil + return res, executeErr } func parseAddr(m []byte) (addr Addr, family int, err error) { diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go index 6c340b0ce..fa5766b80 100644 --- a/vendor/github.com/vishvananda/netlink/bridge_linux.go +++ b/vendor/github.com/vishvananda/netlink/bridge_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "github.com/vishvananda/netlink/nl" @@ -9,21 +10,27 @@ import ( // BridgeVlanList gets a map of device id to bridge vlan infos. // Equivalent to: `bridge vlan show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { return pkgHandle.BridgeVlanList() } // BridgeVlanList gets a map of device id to bridge vlan infos. // Equivalent to: `bridge vlan show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, 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, 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 } ret := make(map[int32][]*nl.BridgeVlanInfo) for _, m := range msgs { @@ -51,7 +58,7 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { } } } - return ret, nil + return ret, executeErr } // BridgeVlanAdd adds a new vlan filter entry diff --git a/vendor/github.com/vishvananda/netlink/chain_linux.go b/vendor/github.com/vishvananda/netlink/chain_linux.go index d9f441613..5008e7101 100644 --- a/vendor/github.com/vishvananda/netlink/chain_linux.go +++ b/vendor/github.com/vishvananda/netlink/chain_linux.go @@ -1,6 +1,8 @@ package netlink import ( + "errors" + "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) @@ -56,6 +58,9 @@ func (h *Handle) chainModify(cmd, flags int, link Link, chain Chain) error { // ChainList gets a list of chains in the system. // Equivalent to: `tc chain list`. // The list can be filtered by link. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func ChainList(link Link, parent uint32) ([]Chain, error) { return pkgHandle.ChainList(link, parent) } @@ -63,6 +68,9 @@ func ChainList(link Link, parent uint32) ([]Chain, error) { // ChainList gets a list of chains in the system. // Equivalent to: `tc chain list`. // The list can be filtered by link. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) { req := h.newNetlinkRequest(unix.RTM_GETCHAIN, unix.NLM_F_DUMP) index := int32(0) @@ -78,9 +86,9 @@ func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) { } req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []Chain @@ -108,5 +116,5 @@ func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) { res = append(res, chain) } - return res, nil + return res, executeErr } diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go index a82eb09de..08fb16c2b 100644 --- a/vendor/github.com/vishvananda/netlink/class_linux.go +++ b/vendor/github.com/vishvananda/netlink/class_linux.go @@ -201,14 +201,20 @@ func classPayload(req *nl.NetlinkRequest, class Class) error { // ClassList gets a list of classes in the system. // Equivalent to: `tc class show`. +// // Generally returns nothing if link and parent are not specified. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func ClassList(link Link, parent uint32) ([]Class, error) { return pkgHandle.ClassList(link, parent) } // ClassList gets a list of classes in the system. // Equivalent to: `tc class show`. +// // Generally returns nothing if link and parent are not specified. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP) msg := &nl.TcMsg{ @@ -222,9 +228,9 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { } req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []Class @@ -295,7 +301,7 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { res = append(res, class) } - return res, nil + return res, executeErr } func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go index ba022453b..b3d354d75 100644 --- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go +++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "errors" "fmt" + "io/fs" "net" "time" @@ -44,6 +45,9 @@ type InetFamily uint8 // ConntrackTableList returns the flow list of a table of a specific family // conntrack -L [table] [options] List conntrack or expectation table +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { return pkgHandle.ConntrackTableList(table, family) } @@ -70,7 +74,7 @@ func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *Conntrac // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter // conntrack -D [table] parameters Delete conntrack or expectation // -// Deprecated: use [ConntrackDeleteFilter] instead. +// Deprecated: use [ConntrackDeleteFilters] instead. func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { return pkgHandle.ConntrackDeleteFilters(table, family, filter) } @@ -83,10 +87,13 @@ func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters // ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed // conntrack -L [table] [options] List conntrack or expectation table +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { - res, err := h.dumpConntrackTable(table, family) - if err != nil { - return nil, err + res, executeErr := h.dumpConntrackTable(table, family) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } // Deserialize all the flows @@ -95,7 +102,7 @@ func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) result = append(result, parseRawData(dataRaw)) } - return result, nil + return result, executeErr } // ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed @@ -152,11 +159,18 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami // ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed // conntrack -D [table] parameters Delete conntrack or expectation func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { + var finalErr error res, err := h.dumpConntrackTable(table, family) if err != nil { - return 0, err + if !errors.Is(err, ErrDumpInterrupted) { + return 0, err + } + // This allows us to at least do a best effort to try to clean the + // entries matching the filter. + finalErr = err } + var totalFilterErrors int var matched uint for _, dataRaw := range res { flow := parseRawData(dataRaw) @@ -165,15 +179,20 @@ func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFam req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already req2.AddRawData(dataRaw[4:]) - req2.Execute(unix.NETLINK_NETFILTER, 0) - matched++ - // flow is already deleted, no need to match on other filters and continue to the next flow. - break + if _, err = req2.Execute(unix.NETLINK_NETFILTER, 0); err == nil || errors.Is(err, fs.ErrNotExist) { + matched++ + // flow is already deleted, no need to match on other filters and continue to the next flow. + break + } else { + totalFilterErrors++ + } } } } - - return matched, nil + if totalFilterErrors > 0 { + finalErr = errors.Join(finalErr, fmt.Errorf("failed to delete %d conntrack flows with %d filters", totalFilterErrors, len(filters))) + } + return matched, finalErr } func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily, operation, flags int) *nl.NetlinkRequest { diff --git a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go index 0bfdf422d..0049048dc 100644 --- a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go @@ -33,7 +33,7 @@ func ConntrackTableFlush(table ConntrackTableType) error { // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter // conntrack -D [table] parameters Delete conntrack or expectation // -// Deprecated: use [ConntrackDeleteFilter] instead. +// Deprecated: use [ConntrackDeleteFilters] instead. func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { return 0, ErrNotImplemented } diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go index d98801dbb..45d8ee4b6 100644 --- a/vendor/github.com/vishvananda/netlink/devlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "strings" @@ -466,6 +467,8 @@ func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) { // DevLinkGetDeviceList provides a pointer to devlink devices and nil error, // otherwise returns an error code. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) { f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) if err != nil { @@ -478,9 +481,9 @@ func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) { req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } devices, err := parseDevLinkDeviceList(msgs) if err != nil { @@ -489,11 +492,14 @@ func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) { for _, d := range devices { h.getEswitchAttrs(f, d) } - return devices, nil + return devices, executeErr } // DevLinkGetDeviceList provides a pointer to devlink devices and nil error, // otherwise returns an error code. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func DevLinkGetDeviceList() ([]*DevlinkDevice, error) { return pkgHandle.DevLinkGetDeviceList() } @@ -646,6 +652,8 @@ func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) { // DevLinkGetPortList provides a pointer to devlink ports and nil error, // otherwise returns an error code. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) { f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) if err != nil { @@ -658,19 +666,21 @@ func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) { req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } ports, err := parseDevLinkAllPortList(msgs) if err != nil { return nil, err } - return ports, nil + return ports, executeErr } // DevLinkGetPortList provides a pointer to devlink ports and nil error, // otherwise returns an error code. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func DevLinkGetAllPortList() ([]*DevlinkPort, error) { return pkgHandle.DevLinkGetAllPortList() } @@ -738,15 +748,18 @@ func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkR // DevlinkGetDeviceParams returns parameters for devlink device // Equivalent to: `devlink dev param show /` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) { _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device) if err != nil { return nil, err } req.Flags |= unix.NLM_F_DUMP - respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err + respmsg, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var params []*DevlinkParam for _, m := range respmsg { @@ -761,11 +774,14 @@ func (h *Handle) DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkPa params = append(params, p) } - return params, nil + return params, executeErr } // DevlinkGetDeviceParams returns parameters for devlink device // Equivalent to: `devlink dev param show /` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) { return pkgHandle.DevlinkGetDeviceParams(bus, device) } diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go index 84e1ca7a4..a722e0a27 100644 --- a/vendor/github.com/vishvananda/netlink/filter.go +++ b/vendor/github.com/vishvananda/netlink/filter.go @@ -231,6 +231,35 @@ func NewCsumAction() *CsumAction { } } +type VlanAct int8 + +type VlanAction struct { + ActionAttrs + Action VlanAct + VlanID uint16 +} + +const ( + TCA_VLAN_ACT_POP VlanAct = 1 + TCA_VLAN_ACT_PUSH VlanAct = 2 +) + +func (action *VlanAction) Type() string { + return "vlan" +} + +func (action *VlanAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewVlanAction() *VlanAction { + return &VlanAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + type MirredAct uint8 func (a MirredAct) String() string { diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go index 87cd18f8e..404e50d52 100644 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ b/vendor/github.com/vishvananda/netlink/filter_linux.go @@ -65,6 +65,9 @@ type Flower struct { EncSrcIPMask net.IPMask EncDestPort uint16 EncKeyId uint32 + SrcMac net.HardwareAddr + DestMac net.HardwareAddr + VlanId uint16 SkipHw bool SkipSw bool IPProto *nl.IPProto @@ -135,6 +138,15 @@ func (filter *Flower) encode(parent *nl.RtAttr) error { if filter.EncKeyId != 0 { parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId)) } + if filter.SrcMac != nil { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac) + } + if filter.DestMac != nil { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac) + } + if filter.VlanId != 0 { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId)) + } if filter.IPProto != nil { ipproto := *filter.IPProto parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize()) @@ -201,6 +213,13 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error { filter.EncDestPort = ntohs(datum.Value) case nl.TCA_FLOWER_KEY_ENC_KEY_ID: filter.EncKeyId = ntohl(datum.Value) + case nl.TCA_FLOWER_KEY_ETH_SRC: + filter.SrcMac = datum.Value + case nl.TCA_FLOWER_KEY_ETH_DST: + filter.DestMac = datum.Value + case nl.TCA_FLOWER_KEY_VLAN_ID: + filter.VlanId = native.Uint16(datum.Value[0:2]) + filter.EthType = unix.ETH_P_8021Q case nl.TCA_FLOWER_KEY_IP_PROTO: val := new(nl.IPProto) *val = nl.IPProto(datum.Value[0]) @@ -405,14 +424,20 @@ func (h *Handle) filterModify(filter Filter, proto, flags int) error { // FilterList gets a list of filters in the system. // Equivalent to: `tc filter show`. +// // Generally returns nothing if link and parent are not specified. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func FilterList(link Link, parent uint32) ([]Filter, error) { return pkgHandle.FilterList(link, parent) } // FilterList gets a list of filters in the system. // Equivalent to: `tc filter show`. +// // Generally returns nothing if link and parent are not specified. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP) msg := &nl.TcMsg{ @@ -426,9 +451,9 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { } req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []Filter @@ -516,7 +541,7 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { } } - return res, nil + return res, executeErr } func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) { @@ -616,6 +641,22 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { } toTcGen(action.Attrs(), &mirred.TcGen) aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) + case *VlanAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + vlan := nl.TcVlan{ + Action: int32(action.Action), + } + toTcGen(action.Attrs(), &vlan.TcGen) + aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize()) + if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 { + return fmt.Errorf("vlan id is required for push action") + } + if action.VlanID != 0 { + aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID)) + } case *TunnelKeyAction: table := attr.AddRtAttr(tabIndex, nil) tabIndex++ @@ -786,6 +827,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action = &CsumAction{} case "gact": action = &GenericAction{} + case "vlan": + action = &VlanAction{} case "tunnel_key": action = &TunnelKeyAction{} case "skbedit": @@ -816,7 +859,17 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { tcTs := nl.DeserializeTcf(adatum.Value) actionTimestamp = toTimeStamp(tcTs) } - + case "vlan": + switch adatum.Attr.Type { + case nl.TCA_VLAN_PARMS: + vlan := *nl.DeserializeTcVlan(adatum.Value) + action.(*VlanAction).ActionAttrs = ActionAttrs{} + toAttrs(&vlan.TcGen, action.Attrs()) + action.(*VlanAction).Action = VlanAct(vlan.Action) + case nl.TCA_VLAN_PUSH_VLAN_ID: + vlanId := native.Uint16(adatum.Value[0:2]) + action.(*VlanAction).VlanID = vlanId + } case "tunnel_key": switch adatum.Attr.Type { case nl.TCA_TUNNEL_KEY_PARMS: @@ -920,9 +973,11 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { actionnStatistic = (*ActionStatistic)(s) } } - action.Attrs().Statistics = actionnStatistic - action.Attrs().Timestamp = actionTimestamp - actions = append(actions, action) + if action != nil { + action.Attrs().Statistics = actionnStatistic + action.Attrs().Timestamp = actionTimestamp + actions = append(actions, action) + } } return actions, nil } diff --git a/vendor/github.com/vishvananda/netlink/fou.go b/vendor/github.com/vishvananda/netlink/fou.go index 71e73c37a..ea9f6cf67 100644 --- a/vendor/github.com/vishvananda/netlink/fou.go +++ b/vendor/github.com/vishvananda/netlink/fou.go @@ -1,16 +1,7 @@ package netlink import ( - "errors" -) - -var ( - // ErrAttrHeaderTruncated is returned when a netlink attribute's header is - // truncated. - ErrAttrHeaderTruncated = errors.New("attribute header truncated") - // ErrAttrBodyTruncated is returned when a netlink attribute's body is - // truncated. - ErrAttrBodyTruncated = errors.New("attribute body truncated") + "net" ) type Fou struct { @@ -18,4 +9,8 @@ type Fou struct { Port int Protocol int EncapType int + Local net.IP + Peer net.IP + PeerPort int + IfIndex int } diff --git a/vendor/github.com/vishvananda/netlink/fou_linux.go b/vendor/github.com/vishvananda/netlink/fou_linux.go index ed55b2b79..7645a5a5c 100644 --- a/vendor/github.com/vishvananda/netlink/fou_linux.go +++ b/vendor/github.com/vishvananda/netlink/fou_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netlink @@ -5,6 +6,8 @@ package netlink import ( "encoding/binary" "errors" + "log" + "net" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" @@ -29,6 +32,12 @@ const ( FOU_ATTR_IPPROTO FOU_ATTR_TYPE FOU_ATTR_REMCSUM_NOPARTIAL + FOU_ATTR_LOCAL_V4 + FOU_ATTR_LOCAL_V6 + FOU_ATTR_PEER_V4 + FOU_ATTR_PEER_V6 + FOU_ATTR_PEER_PORT + FOU_ATTR_IFINDEX FOU_ATTR_MAX = FOU_ATTR_REMCSUM_NOPARTIAL ) @@ -128,10 +137,14 @@ func (h *Handle) FouDel(f Fou) error { return nil } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func FouList(fam int) ([]Fou, error) { return pkgHandle.FouList(fam) } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) FouList(fam int) ([]Fou, error) { fam_id, err := FouFamilyId() if err != nil { @@ -150,9 +163,9 @@ func (h *Handle) FouList(fam int) ([]Fou, error) { req.AddRawData(raw) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(err, ErrDumpInterrupted) { + return nil, executeErr } fous := make([]Fou, 0, len(msgs)) @@ -165,45 +178,32 @@ func (h *Handle) FouList(fam int) ([]Fou, error) { fous = append(fous, f) } - return fous, nil + return fous, executeErr } func deserializeFouMsg(msg []byte) (Fou, error) { - // we'll skip to byte 4 to first attribute - msg = msg[3:] - var shift int fou := Fou{} - for { - // attribute header is at least 16 bits - if len(msg) < 4 { - return fou, ErrAttrHeaderTruncated - } - - lgt := int(binary.BigEndian.Uint16(msg[0:2])) - if len(msg) < lgt+4 { - return fou, ErrAttrBodyTruncated - } - attr := binary.BigEndian.Uint16(msg[2:4]) - - shift = lgt + 3 - switch attr { + for attr := range nl.ParseAttributes(msg[4:]) { + switch attr.Type { case FOU_ATTR_AF: - fou.Family = int(msg[5]) + fou.Family = int(attr.Value[0]) case FOU_ATTR_PORT: - fou.Port = int(binary.BigEndian.Uint16(msg[5:7])) - // port is 2 bytes - shift = lgt + 2 + fou.Port = int(networkOrder.Uint16(attr.Value)) case FOU_ATTR_IPPROTO: - fou.Protocol = int(msg[5]) + fou.Protocol = int(attr.Value[0]) case FOU_ATTR_TYPE: - fou.EncapType = int(msg[5]) - } - - msg = msg[shift:] - - if len(msg) < 4 { - break + fou.EncapType = int(attr.Value[0]) + case FOU_ATTR_LOCAL_V4, FOU_ATTR_LOCAL_V6: + fou.Local = net.IP(attr.Value) + case FOU_ATTR_PEER_V4, FOU_ATTR_PEER_V6: + fou.Peer = net.IP(attr.Value) + case FOU_ATTR_PEER_PORT: + fou.PeerPort = int(networkOrder.Uint16(attr.Value)) + case FOU_ATTR_IFINDEX: + fou.IfIndex = int(native.Uint16(attr.Value)) + default: + log.Printf("unknown fou attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) } } diff --git a/vendor/github.com/vishvananda/netlink/fou_unspecified.go b/vendor/github.com/vishvananda/netlink/fou_unspecified.go index 3a8365bfe..7e550151a 100644 --- a/vendor/github.com/vishvananda/netlink/fou_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/fou_unspecified.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package netlink diff --git a/vendor/github.com/vishvananda/netlink/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/genetlink_linux.go index 772e5834a..7bdaad97b 100644 --- a/vendor/github.com/vishvananda/netlink/genetlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/genetlink_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "syscall" @@ -126,6 +127,8 @@ func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) { return families, nil } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) { msg := &nl.Genlmsg{ Command: nl.GENL_CTRL_CMD_GETFAMILY, @@ -133,13 +136,19 @@ func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) { } req := h.newNetlinkRequest(nl.GENL_ID_CTRL, unix.NLM_F_DUMP) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + msgs, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr + } + families, err := parseFamilies(msgs) if err != nil { return nil, err } - return parseFamilies(msgs) + return families, executeErr } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func GenlFamilyList() ([]*GenlFamily, error) { return pkgHandle.GenlFamilyList() } diff --git a/vendor/github.com/vishvananda/netlink/gtp_linux.go b/vendor/github.com/vishvananda/netlink/gtp_linux.go index f5e160ba5..377dcae5c 100644 --- a/vendor/github.com/vishvananda/netlink/gtp_linux.go +++ b/vendor/github.com/vishvananda/netlink/gtp_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "strings" @@ -74,6 +75,8 @@ func parsePDP(msgs [][]byte) ([]*PDP, error) { return pdps, nil } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) GTPPDPList() ([]*PDP, error) { f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME) if err != nil { @@ -85,13 +88,19 @@ func (h *Handle) GTPPDPList() ([]*PDP, error) { } req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_DUMP) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + msgs, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(err, ErrDumpInterrupted) { + return nil, executeErr + } + pdps, err := parsePDP(msgs) if err != nil { return nil, err } - return parsePDP(msgs) + return pdps, executeErr } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func GTPPDPList() ([]*PDP, error) { return pkgHandle.GTPPDPList() } diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go index f820cdb67..cccf5d792 100644 --- a/vendor/github.com/vishvananda/netlink/link.go +++ b/vendor/github.com/vishvananda/netlink/link.go @@ -56,6 +56,8 @@ type LinkAttrs struct { Vfs []VfInfo // virtual functions available on link Group uint32 PermHWAddr net.HardwareAddr + ParentDev string + ParentDevBus string Slave LinkSlave } @@ -377,6 +379,13 @@ const ( NETKIT_POLICY_BLACKHOLE NetkitPolicy = 2 ) +type NetkitScrub int + +const ( + NETKIT_SCRUB_NONE NetkitScrub = 0 + NETKIT_SCRUB_DEFAULT NetkitScrub = 1 +) + func (n *Netkit) IsPrimary() bool { return n.isPrimary } @@ -391,6 +400,9 @@ type Netkit struct { Mode NetkitMode Policy NetkitPolicy PeerPolicy NetkitPolicy + Scrub NetkitScrub + PeerScrub NetkitScrub + supportsScrub bool isPrimary bool peerLinkAttrs LinkAttrs } @@ -403,6 +415,10 @@ func (n *Netkit) Type() string { return "netkit" } +func (n *Netkit) SupportsScrub() bool { + return n.supportsScrub +} + // Veth devices must specify PeerName on create type Veth struct { LinkAttrs @@ -761,19 +777,19 @@ const ( ) var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{ - BOND_XMIT_HASH_POLICY_LAYER2: "layer2", - BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4", - BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3", - BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3", - BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4", + BOND_XMIT_HASH_POLICY_LAYER2: "layer2", + BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4", + BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3", + BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3", + BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4", BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac", } var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{ - "layer2": BOND_XMIT_HASH_POLICY_LAYER2, - "layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4, - "layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3, - "encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3, - "encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4, + "layer2": BOND_XMIT_HASH_POLICY_LAYER2, + "layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4, + "layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3, + "encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3, + "encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4, "vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC, } diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index d713612a9..889ce6436 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -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 } diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go index 2d93044a6..1c6f2958a 100644 --- a/vendor/github.com/vishvananda/netlink/neigh_linux.go +++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "syscall" @@ -206,6 +207,9 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { // NeighList returns a list of IP-MAC mappings in the system (ARP table). // Equivalent to: `ip neighbor show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func NeighList(linkIndex, family int) ([]Neigh, error) { return pkgHandle.NeighList(linkIndex, family) } @@ -213,6 +217,9 @@ func NeighList(linkIndex, family int) ([]Neigh, error) { // NeighProxyList returns a list of neighbor proxies in the system. // Equivalent to: `ip neighbor show proxy`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func NeighProxyList(linkIndex, family int) ([]Neigh, error) { return pkgHandle.NeighProxyList(linkIndex, family) } @@ -220,6 +227,9 @@ func NeighProxyList(linkIndex, family int) ([]Neigh, error) { // NeighList returns a list of IP-MAC mappings in the system (ARP table). // Equivalent to: `ip neighbor show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { return h.NeighListExecute(Ndmsg{ Family: uint8(family), @@ -230,6 +240,9 @@ func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { // NeighProxyList returns a list of neighbor proxies in the system. // Equivalent to: `ip neighbor show proxy`. // The list can be filtered by link, ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { return h.NeighListExecute(Ndmsg{ Family: uint8(family), @@ -239,18 +252,24 @@ func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { } // NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func NeighListExecute(msg Ndmsg) ([]Neigh, error) { return pkgHandle.NeighListExecute(msg) } // NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) { req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP) req.AddData(&msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []Neigh @@ -281,7 +300,7 @@ func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) { res = append(res, *neigh) } - return res, nil + return res, executeErr } func NeighDeserialize(m []byte) (*Neigh, error) { @@ -364,6 +383,10 @@ type NeighSubscribeOptions struct { // NeighSubscribeWithOptions work like NeighSubscribe 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 NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, options NeighSubscribeOptions) error { if options.Namespace == nil { none := netns.None() @@ -428,6 +451,9 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done < 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 { if listExisting { // This will be called after handling AF_UNSPEC diff --git a/vendor/github.com/vishvananda/netlink/netlink_linux.go b/vendor/github.com/vishvananda/netlink/netlink_linux.go index a20d293d8..7416e3051 100644 --- a/vendor/github.com/vishvananda/netlink/netlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/netlink_linux.go @@ -9,3 +9,6 @@ const ( FAMILY_V6 = nl.FAMILY_V6 FAMILY_MPLS = nl.FAMILY_MPLS ) + +// ErrDumpInterrupted is an alias for [nl.ErrDumpInterrupted]. +var ErrDumpInterrupted = nl.ErrDumpInterrupted diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go index 0b5be470c..6dfa16cc2 100644 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go @@ -38,6 +38,8 @@ const ( IFLA_NETKIT_POLICY IFLA_NETKIT_PEER_POLICY IFLA_NETKIT_MODE + IFLA_NETKIT_SCRUB + IFLA_NETKIT_PEER_SCRUB IFLA_NETKIT_MAX = IFLA_NETKIT_MODE ) diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go index 6cecc4517..4d2732a9e 100644 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go @@ -4,6 +4,7 @@ package nl import ( "bytes" "encoding/binary" + "errors" "fmt" "net" "os" @@ -11,6 +12,7 @@ import ( "sync" "sync/atomic" "syscall" + "time" "unsafe" "github.com/vishvananda/netns" @@ -43,6 +45,26 @@ var SocketTimeoutTv = unix.Timeval{Sec: 60, Usec: 0} // ErrorMessageReporting is the default error message reporting configuration for the new netlink sockets var EnableErrorMessageReporting bool = false +// ErrDumpInterrupted is an instance of errDumpInterrupted, used to report that +// a netlink function has set the NLM_F_DUMP_INTR flag in a response message, +// indicating that the results may be incomplete or inconsistent. +var ErrDumpInterrupted = errDumpInterrupted{} + +// errDumpInterrupted is an error type, used to report that NLM_F_DUMP_INTR was +// set in a netlink response. +type errDumpInterrupted struct{} + +func (errDumpInterrupted) Error() string { + return "results may be incomplete or inconsistent" +} + +// Before errDumpInterrupted was introduced, EINTR was returned when a netlink +// response had NLM_F_DUMP_INTR. Retain backward compatibility with code that +// may be checking for EINTR using Is. +func (e errDumpInterrupted) Is(target error) bool { + return target == unix.EINTR +} + // GetIPFamily returns the family type of a net.IP. func GetIPFamily(ip net.IP) int { if len(ip) <= net.IPv4len { @@ -492,22 +514,26 @@ func (req *NetlinkRequest) AddRawData(data []byte) { // Execute the request against the given sockType. // Returns a list of netlink messages in serialized format, optionally filtered // by resType. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { var res [][]byte err := req.ExecuteIter(sockType, resType, func(msg []byte) bool { res = append(res, msg) return true }) - if err != nil { + if err != nil && !errors.Is(err, ErrDumpInterrupted) { return nil, err } - return res, nil + return res, err } // ExecuteIter executes the request against the given sockType. // Calls the provided callback func once for each netlink message. // If the callback returns false, it is not called again, but // the remaining messages are consumed/discarded. +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. // // Thread safety: ExecuteIter holds a lock on the socket until // it finishes iteration so the callback must not call back into @@ -559,6 +585,8 @@ func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg return err } + dumpIntr := false + done: for { msgs, from, err := s.Receive() @@ -580,7 +608,7 @@ done: } if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 { - return syscall.Errno(unix.EINTR) + dumpIntr = true } if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR { @@ -634,6 +662,9 @@ done: } } } + if dumpIntr { + return ErrDumpInterrupted + } return nil } @@ -656,9 +687,11 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest { } type NetlinkSocket struct { - fd int32 - file *os.File - lsa unix.SockaddrNetlink + fd int32 + file *os.File + lsa unix.SockaddrNetlink + sendTimeout int64 // Access using atomic.Load/StoreInt64 + receiveTimeout int64 // Access using atomic.Load/StoreInt64 sync.Mutex } @@ -802,8 +835,44 @@ func (s *NetlinkSocket) GetFd() int { return int(s.fd) } +func (s *NetlinkSocket) GetTimeouts() (send, receive time.Duration) { + return time.Duration(atomic.LoadInt64(&s.sendTimeout)), + time.Duration(atomic.LoadInt64(&s.receiveTimeout)) +} + func (s *NetlinkSocket) Send(request *NetlinkRequest) error { - return unix.Sendto(int(s.fd), request.Serialize(), 0, &s.lsa) + rawConn, err := s.file.SyscallConn() + if err != nil { + return err + } + var ( + deadline time.Time + innerErr error + ) + sendTimeout := atomic.LoadInt64(&s.sendTimeout) + if sendTimeout != 0 { + deadline = time.Now().Add(time.Duration(sendTimeout)) + } + if err := s.file.SetWriteDeadline(deadline); err != nil { + return err + } + serializedReq := request.Serialize() + err = rawConn.Write(func(fd uintptr) (done bool) { + innerErr = unix.Sendto(int(s.fd), serializedReq, 0, &s.lsa) + return innerErr != unix.EWOULDBLOCK + }) + if innerErr != nil { + return innerErr + } + if err != nil { + // The timeout was previously implemented using SO_SNDTIMEO on a blocking + // socket. So, continue to return EAGAIN when the timeout is reached. + if errors.Is(err, os.ErrDeadlineExceeded) { + return unix.EAGAIN + } + return err + } + return nil } func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) { @@ -812,20 +881,33 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli return nil, nil, err } var ( + deadline time.Time fromAddr *unix.SockaddrNetlink rb [RECEIVE_BUFFER_SIZE]byte nr int from unix.Sockaddr innerErr error ) + receiveTimeout := atomic.LoadInt64(&s.receiveTimeout) + if receiveTimeout != 0 { + deadline = time.Now().Add(time.Duration(receiveTimeout)) + } + if err := s.file.SetReadDeadline(deadline); err != nil { + return nil, nil, err + } err = rawConn.Read(func(fd uintptr) (done bool) { nr, from, innerErr = unix.Recvfrom(int(fd), rb[:], 0) return innerErr != unix.EWOULDBLOCK }) if innerErr != nil { - err = innerErr + return nil, nil, innerErr } if err != nil { + // The timeout was previously implemented using SO_RCVTIMEO on a blocking + // socket. So, continue to return EAGAIN when the timeout is reached. + if errors.Is(err, os.ErrDeadlineExceeded) { + return nil, nil, unix.EAGAIN + } return nil, nil, err } fromAddr, ok := from.(*unix.SockaddrNetlink) @@ -847,16 +929,14 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli // SetSendTimeout allows to set a send timeout on the socket func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error { - // Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine - // remains stuck on a send on a closed fd - return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout) + atomic.StoreInt64(&s.sendTimeout, timeout.Nano()) + return nil } // SetReceiveTimeout allows to set a receive timeout on the socket func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error { - // Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine - // remains stuck on a recvmsg on a closed fd - return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout) + atomic.StoreInt64(&s.receiveTimeout, timeout.Nano()) + return nil } // SetReceiveBufferSize allows to set a receive buffer size on the socket diff --git a/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go index 7f49125cf..8ee0428db 100644 --- a/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go @@ -17,7 +17,7 @@ func ParseAttributes(data []byte) <-chan Attribute { go func() { i := 0 - for i+4 < len(data) { + for i+4 <= len(data) { length := int(native.Uint16(data[i : i+2])) attrType := native.Uint16(data[i+2 : i+4]) diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go index 0720729a9..b8f500792 100644 --- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go @@ -115,6 +115,7 @@ const ( SizeofTcConnmark = SizeofTcGen + 0x04 SizeofTcCsum = SizeofTcGen + 0x04 SizeofTcMirred = SizeofTcGen + 0x08 + SizeofTcVlan = SizeofTcGen + 0x04 SizeofTcTunnelKey = SizeofTcGen + 0x04 SizeofTcSkbEdit = SizeofTcGen SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 @@ -816,6 +817,41 @@ func (x *TcMirred) Serialize() []byte { return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] } +const ( + TCA_VLAN_UNSPEC = iota + TCA_VLAN_TM + TCA_VLAN_PARMS + TCA_VLAN_PUSH_VLAN_ID + TCA_VLAN_PUSH_VLAN_PROTOCOL + TCA_VLAN_PAD + TCA_VLAN_PUSH_VLAN_PRIORITY + TCA_VLAN_PUSH_ETH_DST + TCA_VLAN_PUSH_ETH_SRC + TCA_VLAN_MAX +) + +//struct tc_vlan { +// tc_gen; +// int v_action; +//}; + +type TcVlan struct { + TcGen + Action int32 +} + +func (msg *TcVlan) Len() int { + return SizeofTcVlan +} + +func DeserializeTcVlan(b []byte) *TcVlan { + return (*TcVlan)(unsafe.Pointer(&b[0:SizeofTcVlan][0])) +} + +func (x *TcVlan) Serialize() []byte { + return (*(*[SizeofTcVlan]byte)(unsafe.Pointer(x)))[:] +} + const ( TCA_TUNNEL_KEY_UNSPEC = iota TCA_TUNNEL_KEY_TM @@ -1239,8 +1275,8 @@ const ( ) // /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It -// * means no specific header type - offset is relative to the network layer -// */ +// - means no specific header type - offset is relative to the network layer +// */ type PeditHeaderType uint16 const ( diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go index 1ba25d3cd..aa51e3b47 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "syscall" @@ -8,10 +9,14 @@ import ( "golang.org/x/sys/unix" ) +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func LinkGetProtinfo(link Link) (Protinfo, error) { return pkgHandle.LinkGetProtinfo(link) } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { base := link.Attrs() h.ensureIndex(base) @@ -19,9 +24,9 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) msg := nl.NewIfInfomsg(unix.AF_BRIDGE) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) - if err != nil { - return pi, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return pi, executeErr } for _, m := range msgs { @@ -43,7 +48,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { } pi = parseProtinfo(infos) - return pi, nil + return pi, executeErr } } return pi, fmt.Errorf("Device with index %d not found", base.Index) diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go index e732ae3bd..22cf0e582 100644 --- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go +++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "io/ioutil" "strconv" @@ -338,6 +339,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { // QdiscList gets a list of qdiscs in the system. // Equivalent to: `tc qdisc show`. // The list can be filtered by link. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func QdiscList(link Link) ([]Qdisc, error) { return pkgHandle.QdiscList(link) } @@ -345,6 +349,9 @@ func QdiscList(link Link) ([]Qdisc, error) { // QdiscList gets a list of qdiscs in the system. // Equivalent to: `tc qdisc show`. // The list can be filtered by link. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP) index := int32(0) @@ -359,9 +366,9 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { } req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []Qdisc @@ -497,7 +504,7 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { res = append(res, qdisc) } - return res, nil + return res, executeErr } func parsePfifoFastData(qdisc Qdisc, value []byte) error { diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go index 036399db6..9bb750732 100644 --- a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go +++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go @@ -3,6 +3,7 @@ package netlink import ( "bytes" "encoding/binary" + "errors" "fmt" "net" @@ -85,19 +86,25 @@ func execRdmaSetLink(req *nl.NetlinkRequest) error { // RdmaLinkList gets a list of RDMA link devices. // Equivalent to: `rdma dev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func RdmaLinkList() ([]*RdmaLink, error) { return pkgHandle.RdmaLinkList() } // RdmaLinkList gets a list of RDMA link devices. // Equivalent to: `rdma dev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RdmaLinkList() ([]*RdmaLink, error) { proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_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 + msgs, executeErr := req.Execute(unix.NETLINK_RDMA, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []*RdmaLink @@ -109,17 +116,23 @@ func (h *Handle) RdmaLinkList() ([]*RdmaLink, error) { res = append(res, link) } - return res, nil + return res, executeErr } // RdmaLinkByName finds a link by name and returns a pointer to the object if // found and nil error, otherwise returns error code. +// +// If the returned error is [ErrDumpInterrupted], the result may be missing or +// outdated and the caller should retry. func RdmaLinkByName(name string) (*RdmaLink, error) { return pkgHandle.RdmaLinkByName(name) } // RdmaLinkByName finds a link by name and returns a pointer to the object if // found and nil error, otherwise returns error code. +// +// If the returned error is [ErrDumpInterrupted], the result may be missing or +// outdated and the caller should retry. func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) { links, err := h.RdmaLinkList() if err != nil { @@ -288,6 +301,8 @@ func RdmaLinkDel(name string) error { } // RdmaLinkDel deletes an rdma link. +// +// If the returned error is [ErrDumpInterrupted], the caller should retry. func (h *Handle) RdmaLinkDel(name string) error { link, err := h.RdmaLinkByName(name) if err != nil { @@ -307,6 +322,7 @@ func (h *Handle) RdmaLinkDel(name string) error { // RdmaLinkAdd adds an rdma link for the specified type to the network device. // Similar to: rdma link add NAME type TYPE netdev NETDEV +// // NAME - specifies the new name of the rdma link to add // TYPE - specifies which rdma type to use. Link types: // rxe - Soft RoCE driver diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go index 0cd4f8363..28a132a2f 100644 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/route_linux.go @@ -3,6 +3,7 @@ package netlink import ( "bytes" "encoding/binary" + "errors" "fmt" "net" "strconv" @@ -1163,6 +1164,9 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R // RouteList gets a list of routes in the system. // Equivalent to: `ip route show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func RouteList(link Link, family int) ([]Route, error) { return pkgHandle.RouteList(link, family) } @@ -1170,6 +1174,9 @@ func RouteList(link Link, family int) ([]Route, error) { // RouteList gets a list of routes in the system. // Equivalent to: `ip route show`. // The list can be filtered by link and ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RouteList(link Link, family int) ([]Route, error) { routeFilter := &Route{} if link != nil { @@ -1188,6 +1195,9 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e // RouteListFiltered gets a list of routes in the system filtered with specified rules. // All rules must be defined in RouteFilter struct +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { var res []Route err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) { @@ -1202,17 +1212,22 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) // RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues // until all routes are loaded or the func returns false. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error { return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f) } +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error { req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) rtmsg := &nl.RtMsg{} rtmsg.Family = uint8(family) var parseErr error - err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool { + executeErr := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool { msg := nl.DeserializeRtMsg(m) if family != FAMILY_ALL && msg.Family != uint8(family) { // Ignore routes not matching requested family @@ -1270,13 +1285,13 @@ func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uin } return f(route) }) - if err != nil { - return err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return executeErr } if parseErr != nil { return parseErr } - return nil + return executeErr } // deserializeRoute decodes a binary netlink message into a Route struct @@ -1684,6 +1699,10 @@ type RouteSubscribeOptions struct { // RouteSubscribeWithOptions work like RouteSubscribe 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 RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error { if options.Namespace == nil { none := netns.None() @@ -1743,6 +1762,9 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done < 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 } diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go index ddff99cfa..dba99147b 100644 --- a/vendor/github.com/vishvananda/netlink/rule_linux.go +++ b/vendor/github.com/vishvananda/netlink/rule_linux.go @@ -2,6 +2,7 @@ package netlink import ( "bytes" + "errors" "fmt" "net" @@ -183,12 +184,18 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { // RuleList lists rules in the system. // Equivalent to: ip rule list +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func RuleList(family int) ([]Rule, error) { return pkgHandle.RuleList(family) } // RuleList lists rules in the system. // Equivalent to: ip rule list +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RuleList(family int) ([]Rule, error) { return h.RuleListFiltered(family, nil, 0) } @@ -196,20 +203,26 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { // RuleListFiltered gets a list of rules in the system filtered by the // specified rule template `filter`. // Equivalent to: ip rule list +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { return pkgHandle.RuleListFiltered(family, filter, filterMask) } // RuleListFiltered lists rules in the system. // Equivalent to: ip rule list +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST) msg := nl.NewIfInfomsg(family) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res = make([]Rule, 0) @@ -306,7 +319,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ( res = append(res, *rule) } - return res, nil + return res, executeErr } func (pr *RulePortRange) toRtAttrData() []byte { diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go index 4eb4aeafb..ebda532a8 100644 --- a/vendor/github.com/vishvananda/netlink/socket_linux.go +++ b/vendor/github.com/vishvananda/netlink/socket_linux.go @@ -157,6 +157,9 @@ func (u *UnixSocket) deserialize(b []byte) error { } // SocketGet returns the Socket identified by its local and remote addresses. +// +// If the returned error is [ErrDumpInterrupted], the search for a result may +// be incomplete and the caller should retry. func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) { var protocol uint8 var localIP, remoteIP net.IP @@ -232,6 +235,9 @@ func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) { } // SocketGet returns the Socket identified by its local and remote addresses. +// +// If the returned error is [ErrDumpInterrupted], the search for a result may +// be incomplete and the caller should retry. func SocketGet(local, remote net.Addr) (*Socket, error) { return pkgHandle.SocketGet(local, remote) } @@ -283,6 +289,9 @@ func SocketDestroy(local, remote net.Addr) error { } // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { // Construct the request req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) @@ -295,9 +304,9 @@ func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) // Do the query and parse the result var result []*InetDiagTCPInfoResp - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &Socket{} + var err error if err = sockInfo.deserialize(msg); err != nil { return false } @@ -315,18 +324,24 @@ func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { return pkgHandle.SocketDiagTCPInfo(family) } // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) { // Construct the request req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) @@ -339,27 +354,32 @@ func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) { // Do the query and parse the result var result []*Socket - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &Socket{} - if err = sockInfo.deserialize(msg); err != nil { + if err := sockInfo.deserialize(msg); err != nil { return false } result = append(result, sockInfo) return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func SocketDiagTCP(family uint8) ([]*Socket, error) { return pkgHandle.SocketDiagTCP(family) } // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { // Construct the request var extensions uint8 @@ -377,14 +397,14 @@ func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) // Do the query and parse the result var result []*InetDiagUDPInfoResp - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &Socket{} - if err = sockInfo.deserialize(msg); err != nil { + if err := sockInfo.deserialize(msg); err != nil { return false } var attrs []syscall.NetlinkRouteAttr + var err error if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { return false } @@ -397,18 +417,24 @@ func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) result = append(result, res) return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { return pkgHandle.SocketDiagUDPInfo(family) } // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) { // Construct the request req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) @@ -421,27 +447,32 @@ func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) { // Do the query and parse the result var result []*Socket - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &Socket{} - if err = sockInfo.deserialize(msg); err != nil { + if err := sockInfo.deserialize(msg); err != nil { return false } result = append(result, sockInfo) return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func SocketDiagUDP(family uint8) ([]*Socket, error) { return pkgHandle.SocketDiagUDP(family) } // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { // Construct the request var extensions uint8 @@ -456,10 +487,9 @@ func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { }) var result []*UnixDiagInfoResp - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &UnixSocket{} - if err = sockInfo.deserialize(msg); err != nil { + if err := sockInfo.deserialize(msg); err != nil { return false } @@ -469,7 +499,8 @@ func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { } var attrs []syscall.NetlinkRouteAttr - if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { + var err error + if attrs, err = nl.ParseRouteAttr(msg[sizeofUnixSocket:]); err != nil { return false } @@ -480,18 +511,24 @@ func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { result = append(result, res) return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { return pkgHandle.UnixSocketDiagInfo() } // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) { // Construct the request req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) @@ -501,10 +538,9 @@ func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) { }) var result []*UnixSocket - var err error - err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + executeErr := req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { sockInfo := &UnixSocket{} - if err = sockInfo.deserialize(msg); err != nil { + if err := sockInfo.deserialize(msg); err != nil { return false } @@ -514,13 +550,16 @@ func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) { } return true }) - if err != nil { - return nil, err + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } - return result, nil + return result, executeErr } // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func UnixSocketDiag() ([]*UnixSocket, error) { return pkgHandle.UnixSocketDiag() } diff --git a/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go index 20c82f9c7..c1dd00a86 100644 --- a/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go +++ b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go @@ -52,8 +52,10 @@ func (s *XDPSocket) deserialize(b []byte) error { return nil } -// XDPSocketGet returns the XDP socket identified by its inode number and/or +// SocketXDPGetInfo returns the XDP socket identified by its inode number and/or // socket cookie. Specify the cookie as SOCK_ANY_COOKIE if +// +// If the returned error is [ErrDumpInterrupted], the caller should retry. func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) { // We have a problem here: dumping AF_XDP sockets currently does not support // filtering. We thus need to dump all XSKs and then only filter afterwards @@ -85,6 +87,9 @@ func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) { } // SocketDiagXDP requests XDP_DIAG_INFO for XDP family sockets. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func SocketDiagXDP() ([]*XDPDiagInfoResp, error) { var result []*XDPDiagInfoResp err := socketDiagXDPExecutor(func(m syscall.NetlinkMessage) error { @@ -105,10 +110,10 @@ func SocketDiagXDP() ([]*XDPDiagInfoResp, error) { result = append(result, res) return nil }) - if err != nil { + if err != nil && !errors.Is(err, ErrDumpInterrupted) { return nil, err } - return result, nil + return result, err } // socketDiagXDPExecutor requests XDP_DIAG_INFO for XDP family sockets. @@ -128,6 +133,7 @@ func socketDiagXDPExecutor(receiver func(syscall.NetlinkMessage) error) error { return err } + dumpIntr := false loop: for { msgs, from, err := s.Receive() @@ -142,6 +148,9 @@ loop: } for _, m := range msgs { + if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 { + dumpIntr = true + } switch m.Header.Type { case unix.NLMSG_DONE: break loop @@ -154,6 +163,9 @@ loop: } } } + if dumpIntr { + return ErrDumpInterrupted + } return nil } diff --git a/vendor/github.com/vishvananda/netlink/vdpa_linux.go b/vendor/github.com/vishvananda/netlink/vdpa_linux.go index 7c15986d0..c14877a29 100644 --- a/vendor/github.com/vishvananda/netlink/vdpa_linux.go +++ b/vendor/github.com/vishvananda/netlink/vdpa_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "syscall" @@ -118,6 +119,9 @@ func VDPADelDev(name string) error { // VDPAGetDevList returns list of VDPA devices // Equivalent to: `vdpa dev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func VDPAGetDevList() ([]*VDPADev, error) { return pkgHandle.VDPAGetDevList() } @@ -130,6 +134,9 @@ func VDPAGetDevByName(name string) (*VDPADev, error) { // VDPAGetDevConfigList returns list of VDPA devices configurations // Equivalent to: `vdpa dev config show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func VDPAGetDevConfigList() ([]*VDPADevConfig, error) { return pkgHandle.VDPAGetDevConfigList() } @@ -148,6 +155,9 @@ func VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) { // VDPAGetMGMTDevList returns list of mgmt devices // Equivalent to: `vdpa mgmtdev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) { return pkgHandle.VDPAGetMGMTDevList() } @@ -261,9 +271,9 @@ func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) req.AddData(a) } - resp, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err + resp, executeErr := req.Execute(unix.NETLINK_GENERIC, 0) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } messages := make([]vdpaNetlinkMessage, 0, len(resp)) for _, m := range resp { @@ -273,10 +283,13 @@ func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) } messages = append(messages, attrs) } - return messages, nil + return messages, executeErr } // dump all devices if dev is nil +// +// If dev is nil and the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) { var extraFlags int var attrs []*nl.RtAttr @@ -285,9 +298,9 @@ func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) { } else { extraFlags = extraFlags | unix.NLM_F_DUMP } - messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs) - if err != nil { - return nil, err + messages, executeErr := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } devs := make([]*VDPADev, 0, len(messages)) for _, m := range messages { @@ -295,10 +308,13 @@ func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) { d.parseAttributes(m) devs = append(devs, d) } - return devs, nil + return devs, executeErr } // dump all devices if dev is nil +// +// If dev is nil, and the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) { var extraFlags int var attrs []*nl.RtAttr @@ -307,9 +323,9 @@ func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) { } else { extraFlags = extraFlags | unix.NLM_F_DUMP } - messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs) - if err != nil { - return nil, err + messages, executeErr := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } cfgs := make([]*VDPADevConfig, 0, len(messages)) for _, m := range messages { @@ -317,10 +333,13 @@ func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) { cfg.parseAttributes(m) cfgs = append(cfgs, cfg) } - return cfgs, nil + return cfgs, executeErr } // dump all devices if dev is nil +// +// If dev is nil and the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) { var extraFlags int var attrs []*nl.RtAttr @@ -336,9 +355,9 @@ func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) { } else { extraFlags = extraFlags | unix.NLM_F_DUMP } - messages, err := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs) - if err != nil { - return nil, err + messages, executeErr := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } cfgs := make([]*VDPAMGMTDev, 0, len(messages)) for _, m := range messages { @@ -346,7 +365,7 @@ func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) { cfg.parseAttributes(m) cfgs = append(cfgs, cfg) } - return cfgs, nil + return cfgs, executeErr } // VDPANewDev adds new VDPA device @@ -385,6 +404,9 @@ func (h *Handle) VDPADelDev(name string) error { // VDPAGetDevList returns list of VDPA devices // Equivalent to: `vdpa dev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) VDPAGetDevList() ([]*VDPADev, error) { return h.vdpaDevGet(nil) } @@ -404,6 +426,9 @@ func (h *Handle) VDPAGetDevByName(name string) (*VDPADev, error) { // VDPAGetDevConfigList returns list of VDPA devices configurations // Equivalent to: `vdpa dev config show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) VDPAGetDevConfigList() ([]*VDPADevConfig, error) { return h.vdpaDevConfigGet(nil) } @@ -441,6 +466,9 @@ func (h *Handle) VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStat // VDPAGetMGMTDevList returns list of mgmt devices // Equivalent to: `vdpa mgmtdev show` +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) { return h.vdpaMGMTDevGet(nil, nil) } diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go index d526739ce..bf143a1b1 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" @@ -215,6 +216,9 @@ func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error { // XfrmPolicyList gets a list of xfrm policies in the system. // Equivalent to: `ip xfrm policy show`. // The list can be filtered by ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func XfrmPolicyList(family int) ([]XfrmPolicy, error) { return pkgHandle.XfrmPolicyList(family) } @@ -222,15 +226,18 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) { // XfrmPolicyList gets a list of xfrm policies in the system. // Equivalent to: `ip xfrm policy show`. // The list can be filtered by ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) { req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP) msg := nl.NewIfInfomsg(family) req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []XfrmPolicy @@ -243,7 +250,7 @@ func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) { return nil, err } } - return res, nil + return res, executeErr } // XfrmPolicyGet gets a the policy described by the index or selector, if found. diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go index 554f2498c..2f4614651 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "errors" "fmt" "net" "time" @@ -382,6 +383,9 @@ func (h *Handle) XfrmStateDel(state *XfrmState) error { // XfrmStateList gets a list of xfrm states in the system. // Equivalent to: `ip [-4|-6] xfrm state show`. // The list can be filtered by ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func XfrmStateList(family int) ([]XfrmState, error) { return pkgHandle.XfrmStateList(family) } @@ -389,12 +393,15 @@ func XfrmStateList(family int) ([]XfrmState, error) { // XfrmStateList gets a list of xfrm states in the system. // Equivalent to: `ip xfrm state show`. // The list can be filtered by ip family. +// +// If the returned error is [ErrDumpInterrupted], results may be inconsistent +// or incomplete. func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP) - msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) - if err != nil { - return nil, err + msgs, executeErr := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) + if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { + return nil, executeErr } var res []XfrmState @@ -407,7 +414,7 @@ func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { return nil, err } } - return res, nil + return res, executeErr } // XfrmStateGet gets the xfrm state described by the ID, if found. diff --git a/vendor/modules.txt b/vendor/modules.txt index f6251a2b1..06e5e615f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -189,7 +189,7 @@ github.com/sirupsen/logrus ## explicit; go 1.21 github.com/u-root/uio/rand github.com/u-root/uio/uio -# github.com/vishvananda/netlink v1.3.0 +# github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 ## explicit; go 1.12 github.com/vishvananda/netlink github.com/vishvananda/netlink/nl