]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Get zebra graceful restart working when restarting on *BSD
authorDonald Sharp <sharpd@nvidia.com>
Sun, 27 Feb 2022 19:11:13 +0000 (14:11 -0500)
committerDonald Sharp <sharpd@nvidia.com>
Mon, 28 Feb 2022 14:50:35 +0000 (09:50 -0500)
Upon restart zebra reads in the kernel state.  Under linux
there is a mechanism to read the route and convert the protocol
to the correct internal FRR protocol to allow the zebra graceful
restart efforts to work properly.

Under *BSD I do not see a mechanism to convey the original FRR
protocol into the kernel and thus back out of it.  Thus when
zebra crashes ( or restarts ) the routes read back in are kernel
routes and are effectively lost to the system and FRR cannot
remove them properly.  Why?  Because FRR see's kernel routes
as routes that it should not own and in general the admin
distance for those routes will be a better one than the
admin distance from a routing protocol.  This is even
worse because when the graceful restart timer pops and rib_sweep
is run, FRR becomes out of sync with the state of the kernel forwarding
on *BSD.

On restart, notice that the route is a self route that there
is no way to know it's originating protocol.  In this case
let's set the protocol to ZEBRA_ROUTE_STATIC and set the admin
distance to 255.

This way when an upper level protocol reinstalls it's route
the general zebra graceful restart code still works.  The
high admin distance allows the code to just work in a way
that is graceful( HA! )

The drawback here is that the route shows up as a static
route for the time the system is doing it's work.  FRR
could introduce *another* route type but this seems like
a bad idea and the STATIC route type is loosely analagous
to the type of route it has become.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
zebra/kernel_socket.c

index 53b7a21d32d648cbf5b4efffe6f6e91365e0af66..321800d9af472374b7d536f7a29ed8fa68608bdd 100644 (file)
@@ -1011,6 +1011,8 @@ void rtm_read(struct rt_msghdr *rtm)
        ifindex_t ifindex = 0;
        afi_t afi;
        char fbuf[64];
+       int32_t proto = ZEBRA_ROUTE_KERNEL;
+       uint8_t distance = 0;
 
        zebra_flags = 0;
 
@@ -1042,8 +1044,11 @@ void rtm_read(struct rt_msghdr *rtm)
        if (!(flags & RTF_GATEWAY))
                return;
 
-       if (flags & RTF_PROTO1)
+       if (flags & RTF_PROTO1) {
                SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
+               proto = ZEBRA_ROUTE_STATIC;
+               distance = 255;
+       }
 
        memset(&nh, 0, sizeof(nh));
 
@@ -1111,13 +1116,13 @@ void rtm_read(struct rt_msghdr *rtm)
                           0, true);
        if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
            || rtm->rtm_type == RTM_CHANGE)
-               rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
-                       zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN,
-                       0, 0, 0, 0, false);
+               rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
+                       &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, 0, distance, 0,
+                       false);
        else
-               rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
-                          0, zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
-                          0, true);
+               rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0,
+                          zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
+                          distance, true);
 }
 
 /* Interface function for the kernel routing table updates.  Support