mirror of https://github.com/vishvananda/netlink
Add IifIndex option to RouteGetOptions
This commit is contained in:
parent
ec7bcb248e
commit
42d9a053ea
|
@ -1424,6 +1424,7 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||
// RouteGetWithOptions
|
||||
type RouteGetOptions struct {
|
||||
Iif string
|
||||
IifIndex int
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
|
@ -1485,14 +1486,21 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
|||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
|
||||
iifIndex := 0
|
||||
if len(options.Iif) > 0 {
|
||||
link, err := LinkByName(options.Iif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iifIndex = link.Attrs().Index
|
||||
} else if options.IifIndex > 0 {
|
||||
iifIndex = options.IifIndex
|
||||
}
|
||||
|
||||
if iifIndex > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(link.Attrs().Index))
|
||||
native.PutUint32(b, uint32(iifIndex))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
||||
}
|
||||
|
|
141
route_test.go
141
route_test.go
|
@ -6,6 +6,7 @@ package netlink
|
|||
import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -931,6 +932,146 @@ func TestRouteMultiPath(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRouteIifOption(t *testing.T) {
|
||||
skipUnlessRoot(t)
|
||||
|
||||
runtime.LockOSThread()
|
||||
t.Cleanup(runtime.UnlockOSThread)
|
||||
|
||||
rootNs, err := netns.GetFromPid(1)
|
||||
if err != nil {
|
||||
t.Fatalf("could not get root ns: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { rootNs.Close() })
|
||||
|
||||
rootHdl, err := NewHandleAt(rootNs)
|
||||
if err != nil {
|
||||
t.Fatalf("could not create handle for root ns: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { rootHdl.Close() })
|
||||
|
||||
// setup a veth pair across two namespaces
|
||||
// veth1 (2.2.2.3/24) <-> veth2 (2.2.2.4/24)
|
||||
|
||||
// peer ns for veth pair
|
||||
ns, err := netns.New()
|
||||
if err != nil {
|
||||
t.Fatalf("could not create new ns: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { ns.Close() })
|
||||
|
||||
l := &Veth{
|
||||
LinkAttrs: LinkAttrs{Name: "veth1"},
|
||||
PeerName: "veth2",
|
||||
PeerNamespace: NsFd(ns),
|
||||
}
|
||||
if err = rootHdl.LinkAdd(l); err != nil {
|
||||
t.Fatalf("could not add veth interface: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { rootHdl.LinkDel(l) })
|
||||
|
||||
ve1, err := rootHdl.LinkByName("veth1")
|
||||
if err != nil {
|
||||
t.Fatalf("could not get link veth1: %s", err)
|
||||
}
|
||||
|
||||
err = rootHdl.AddrAdd(ve1, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.3"), Mask: net.CIDRMask(24, 32)}})
|
||||
if err != nil {
|
||||
t.Fatalf("could not set address for veth1: %s", err)
|
||||
}
|
||||
|
||||
nh, err := NewHandleAt(ns)
|
||||
if err != nil {
|
||||
t.Fatalf("could not get handle for ns %+v: %s", ns, err)
|
||||
}
|
||||
t.Cleanup(func() { nh.Close() })
|
||||
|
||||
ve2, err := nh.LinkByName("veth2")
|
||||
if err != nil {
|
||||
t.Fatalf("could not get link veth2: %s", err)
|
||||
}
|
||||
|
||||
err = nh.AddrAdd(ve2, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.4"), Mask: net.CIDRMask(24, 32)}})
|
||||
if err != nil {
|
||||
t.Fatalf("could set address for veth2: %s", err)
|
||||
}
|
||||
|
||||
if err = rootHdl.LinkSetUp(ve1); err != nil {
|
||||
t.Fatalf("could not set veth1 up: %s", err)
|
||||
}
|
||||
|
||||
if err = nh.LinkSetUp(ve2); err != nil {
|
||||
t.Fatalf("could not set veth2 up: %s", err)
|
||||
}
|
||||
|
||||
err = nh.RouteAdd(&Route{
|
||||
Dst: &net.IPNet{
|
||||
IP: net.IPv4zero,
|
||||
Mask: net.CIDRMask(0, 32),
|
||||
},
|
||||
Gw: net.ParseIP("2.2.2.3"),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("could not add default route to ns: %s", err)
|
||||
}
|
||||
|
||||
// setup finished, now do the actual test
|
||||
|
||||
_, err = rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), &RouteGetOptions{
|
||||
SrcAddr: net.ParseIP("2.2.2.4"),
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("route get should have resulted in error but did not")
|
||||
}
|
||||
|
||||
testWithOptions := func(opts *RouteGetOptions) {
|
||||
routes, err := rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("could not get route: %s", err)
|
||||
}
|
||||
if len(routes) != 1 {
|
||||
t.Fatalf("did not get exactly one route, routes: %+v", routes)
|
||||
}
|
||||
|
||||
// should be the default route
|
||||
r, err := rootHdl.RouteGet(net.ParseIP("8.8.8.8"))
|
||||
if err != nil {
|
||||
t.Fatalf("could not get default route for 8.8.8.8: %s", err)
|
||||
}
|
||||
if len(r) != 1 {
|
||||
t.Fatalf("did not get exactly one route, routes: %+v", routes)
|
||||
}
|
||||
if !routes[0].Gw.Equal(r[0].Gw) {
|
||||
t.Fatalf("wrong gateway in route: expected: %s, got: %s", r[0].Gw, routes[0].Gw)
|
||||
}
|
||||
if routes[0].LinkIndex != r[0].LinkIndex {
|
||||
t.Fatalf("wrong link in route: expected: %d, got: %d", r[0].LinkIndex, routes[0].LinkIndex)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("with iif", func(t *testing.T) {
|
||||
testWithOptions(&RouteGetOptions{
|
||||
SrcAddr: net.ParseIP("2.2.2.4"),
|
||||
Iif: "veth1",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("with iifIndex", func(t *testing.T) {
|
||||
testWithOptions(&RouteGetOptions{
|
||||
SrcAddr: net.ParseIP("2.2.2.4"),
|
||||
IifIndex: ve1.Attrs().Index,
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("with iif and iifIndex", func(t *testing.T) {
|
||||
testWithOptions(&RouteGetOptions{
|
||||
SrcAddr: net.ParseIP("2.2.2.4"),
|
||||
Iif: "veth1",
|
||||
IifIndex: ve2.Attrs().Index, // Iif will supersede here
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouteOifOption(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
|
Loading…
Reference in New Issue