From bd5868794c6dd936127424873eb1fc1521b2b7c2 Mon Sep 17 00:00:00 2001 From: Yutaro Hayakawa Date: Wed, 5 Jul 2023 12:56:08 +0900 Subject: [PATCH] Support fibmatch flag for RouteGetWithOptions Support `ip route get fibmatch` equivalent with RouteGetWithOptions by adding FIBMatch flag to RouteGetOptions. Signed-off-by: Yutaro Hayakawa --- route_linux.go | 16 +++++++++----- route_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/route_linux.go b/route_linux.go index b1ef181..aacc44c 100644 --- a/route_linux.go +++ b/route_linux.go @@ -1320,12 +1320,13 @@ func deserializeRoute(m []byte) (Route, error) { // RouteGetOptions contains a set of options to use with // RouteGetWithOptions type RouteGetOptions struct { - Iif string - Oif string - VrfName string - SrcAddr net.IP - UID *uint32 - Mark int + Iif string + Oif string + VrfName string + SrcAddr net.IP + UID *uint32 + Mark int + FIBMatch bool } // RouteGetWithOptions gets a route to a specific destination from the host system. @@ -1361,6 +1362,9 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption msg.Src_len = bitlen } msg.Flags = unix.RTM_F_LOOKUP_TABLE + if options != nil && options.FIBMatch { + msg.Flags |= unix.RTM_F_FIB_MATCH + } req.AddData(msg) rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData) diff --git a/route_test.go b/route_test.go index 2eb6891..d4d584f 100644 --- a/route_test.go +++ b/route_test.go @@ -2019,3 +2019,62 @@ func TestRouteFWMarkOption(t *testing.T) { t.Fatal(routes) } } + +func TestRouteGetFIBMatchOption(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}}) + if err != nil { + t.Fatal(err) + } + link, err := LinkByName("eth0") + if err != nil { + t.Fatal(err) + } + if err = LinkSetUp(link); err != nil { + t.Fatal(err) + } + addr := &Addr{ + IPNet: &net.IPNet{ + IP: net.IPv4(192, 168, 0, 2), + Mask: net.CIDRMask(24, 32), + }, + } + if err = AddrAdd(link, addr); err != nil { + t.Fatal(err) + } + + route := &Route{ + LinkIndex: link.Attrs().Index, + Gw: net.IPv4(192, 168, 1, 1), + Dst: &net.IPNet{ + IP: net.IPv4(192, 168, 2, 0), + Mask: net.CIDRMask(24, 32), + }, + Flags: int(FLAG_ONLINK), + } + + err = RouteAdd(route) + if err != nil { + t.Fatal(err) + } + + routes, err := RouteGetWithOptions(net.IPv4(192, 168, 2, 1), &RouteGetOptions{FIBMatch: true}) + if err != nil { + t.Fatal(err) + } + + if len(routes) != 1 { + t.Fatalf("More than one route matched %v", routes) + } + + if len(routes[0].ListFlags()) != 1 { + t.Fatalf("More than one route flag returned %v", routes[0].ListFlags()) + } + + flag := routes[0].ListFlags()[0] + if flag != "onlink" { + t.Fatalf("Unexpected flag %s returned", flag) + } +}