From b16633bbe92e12d1417963fd989ee8f73b5b6813 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 25 Jan 2018 10:18:19 -0600 Subject: [PATCH] pkg/ip: add GetVethPeerIfindex() --- pkg/ip/link_linux.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/pkg/ip/link_linux.go b/pkg/ip/link_linux.go index 843ce8aa..94ef4127 100644 --- a/pkg/ip/link_linux.go +++ b/pkg/ip/link_linux.go @@ -23,6 +23,7 @@ import ( "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/utils/hwaddr" + "github.com/safchain/ethtool" "github.com/vishvananda/netlink" ) @@ -226,3 +227,43 @@ func SetHWAddrByIP(ifName string, ip4 net.IP, ip6 net.IP) error { return nil } + +// GetVethPeerIfindex returns the veth link object, the peer ifindex of the +// 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) + if err != nil { + return nil, -1, fmt.Errorf("could not look up %q: %v", ifName, err) + } + if _, ok := link.(*netlink.Veth); !ok { + return nil, -1, fmt.Errorf("interface %q was not a veth interface", ifName) + } + + // veth supports IFLA_LINK (what vishvananda/netlink calls ParentIndex) + // on 4.1 and higher kernels + peerIndex := link.Attrs().ParentIndex + if peerIndex <= 0 { + // Fall back to ethtool for 4.0 and earlier kernels + e, err := ethtool.NewEthtool() + if err != nil { + return nil, -1, fmt.Errorf("failed to initialize ethtool: %v", err) + } + defer e.Close() + + stats, err := e.Stats(link.Attrs().Name) + if err != nil { + return nil, -1, fmt.Errorf("failed to request ethtool stats: %v", err) + } + n, ok := stats["peer_ifindex"] + if !ok { + return nil, -1, fmt.Errorf("failed to find 'peer_ifindex' in ethtool stats") + } + if n > 32767 || n == 0 { + return nil, -1, fmt.Errorf("invalid 'peer_ifindex' %d", n) + } + peerIndex = int(n) + } + + return link, peerIndex, nil +}