From e8f9049ee2c072fa413e72cf969c39b90929a538 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 Flags 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 79cc218e..a5de2b5c 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 + +// Flags 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 + Flags uint16 Route } diff --git a/route_linux.go b/route_linux.go index 82982c39..4498ae2e 100644 --- a/route_linux.go +++ b/route_linux.go @@ -1561,7 +1561,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, + Flags: 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 f18852db..7e171df1 100644 --- a/route_test.go +++ b/route_test.go @@ -477,13 +477,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.Flags == f && update.Route.Dst != nil && update.Route.Dst.IP.Equal(dst) { return true @@ -528,13 +529,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") } } @@ -583,7 +584,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") } } @@ -635,13 +636,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") } } @@ -696,7 +697,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") } @@ -711,19 +712,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") } }