From 7f562ed5761f0c6dc9590050654042ae7d5183f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20Soul=C3=A9?= Date: Thu, 30 Nov 2023 13:36:33 +0100 Subject: [PATCH] RouteUpdate gains NlFlags field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It allows to distinguish between a new created route or a replaced one. Signed-off-by: Maxime Soulé --- route.go | 9 ++++++++- route_linux.go | 6 +++++- route_test.go | 23 ++++++++++++----------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/route.go b/route.go index 79cc218..1b4555d 100644 --- a/route.go +++ b/route.go @@ -154,8 +154,15 @@ type flagString struct { } // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE + +// NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set: +// - unix.NLM_F_REPLACE - Replace existing matching config object with this request +// - unix.NLM_F_EXCL - Don't replace the config object if it already exists +// - unix.NLM_F_CREATE - Create config object if it doesn't already exist +// - unix.NLM_F_APPEND - Add to the end of the object list type RouteUpdate struct { - Type uint16 + Type uint16 + NlFlags uint16 Route } diff --git a/route_linux.go b/route_linux.go index 30a1d69..cfe8407 100644 --- a/route_linux.go +++ b/route_linux.go @@ -1687,7 +1687,11 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done < } continue } - ch <- RouteUpdate{Type: m.Header.Type, Route: route} + ch <- RouteUpdate{ + Type: m.Header.Type, + NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND), + Route: route, + } } } }() diff --git a/route_test.go b/route_test.go index 67497e2..166c357 100644 --- a/route_test.go +++ b/route_test.go @@ -543,13 +543,14 @@ func TestRouteAddIncomplete(t *testing.T) { } } -// expectNeighUpdate returns whether the expected updated is received within one minute. -func expectRouteUpdate(ch <-chan RouteUpdate, t uint16, dst net.IP) bool { +// expectRouteUpdate returns whether the expected updated is received within one minute. +func expectRouteUpdate(ch <-chan RouteUpdate, t, f uint16, dst net.IP) bool { for { timeout := time.After(time.Minute) select { case update := <-ch: if update.Type == t && + update.NlFlags == f && update.Route.Dst != nil && update.Route.Dst.IP.Equal(dst) { return true @@ -594,13 +595,13 @@ func TestRouteSubscribe(t *testing.T) { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) { t.Fatal("Add update not received as expected") } if err := RouteDel(&route); err != nil { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) { t.Fatal("Del update not received as expected") } } @@ -649,7 +650,7 @@ func TestRouteSubscribeWithOptions(t *testing.T) { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) { t.Fatal("Add update not received as expected") } } @@ -701,13 +702,13 @@ func TestRouteSubscribeAt(t *testing.T) { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) { t.Fatal("Add update not received as expected") } if err := nh.RouteDel(&route); err != nil { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) { t.Fatal("Del update not received as expected") } } @@ -762,7 +763,7 @@ func TestRouteSubscribeListExisting(t *testing.T) { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst10.IP) { + if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, 0, dst10.IP) { t.Fatal("Existing add update not received as expected") } @@ -777,19 +778,19 @@ func TestRouteSubscribeListExisting(t *testing.T) { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) { t.Fatal("Add update not received as expected") } if err := nh.RouteDel(&route); err != nil { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) { + if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) { t.Fatal("Del update not received as expected") } if err := nh.RouteDel(&route10); err != nil { t.Fatal(err) } - if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst10.IP) { + if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst10.IP) { t.Fatal("Del update not received as expected") } }