]> git.proxmox.com Git - mirror_frr.git/commitdiff
ospfd: Fix quick interface down up event handling in ospf
authorDonald Sharp <sharpd@nvidia.com>
Mon, 24 May 2021 17:45:29 +0000 (13:45 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Tue, 25 May 2021 18:43:40 +0000 (14:43 -0400)
When we get this sequence of events:

- zebra receives interface up, sends to ospf
- ospf receives intf up, processes( including neighbor formation and spf )
  and sends route to zebra for installation.
- zebra receives route for processing, schedules it too happen in the future
- zebra receives interface down event, sends to ospf
- zebra processes route X and marks it inactive because nexthop
  interface is down
- zebra receives interface up event, sends to ospf
- ospf receives both events and processes the change and decides
  that nothing has changed so it does not send any route change for X to zebra.

At this point zebra has a route from ospf that is marked as inactive, while
ospf believes that the route should be installed properly.

Modify the code such that on an interface down event, ospf marks the routes
as changed if the ifindex is being used for a nexthop, so that when ospf
is deciding if routes have changed post spf that it can just automatically
send that route down again if it still exists.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
ospfd/ospf_interface.c
ospfd/ospf_route.c
ospfd/ospf_route.h

index 334ed33ee0ed587916d82e127840b901c2998072..b4e318d1d1d1bef3efcf30a158d0243a3f65e310 100644 (file)
@@ -49,6 +49,7 @@
 #include "ospfd/ospf_network.h"
 #include "ospfd/ospf_dump.h"
 #include "ospfd/ospf_ldp_sync.h"
+#include "ospfd/ospf_route.h"
 
 DEFINE_QOBJ_TYPE(ospf_interface);
 DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
@@ -804,6 +805,10 @@ int ospf_if_up(struct ospf_interface *oi)
 int ospf_if_down(struct ospf_interface *oi)
 {
        struct ospf *ospf;
+       struct route_node *rn;
+       struct ospf_route *or;
+       struct listnode *nh;
+       struct ospf_path *op;
 
        if (oi == NULL)
                return 0;
@@ -840,6 +845,22 @@ int ospf_if_down(struct ospf_interface *oi)
        /* Shutdown packet reception and sending */
        ospf_if_stream_unset(oi);
 
+       for (rn = route_top(ospf->new_table); rn; rn = route_next(rn)) {
+               or = rn->info;
+
+               if (!or)
+                       continue;
+
+               for (nh = listhead(or->paths); nh;
+                    nh = listnextnode_unchecked(nh)) {
+                       op = listgetdata(nh);
+                       if (op->ifindex == oi->ifp->ifindex) {
+                               or->changed = true;
+                               break;
+                       }
+               }
+       }
+
        return 1;
 }
 
index 7cfcaf14be610b6cd5aba63c7e1f43f44f99cdac..502a4a08c160cf83f04c706689a78302c192fd57 100644 (file)
@@ -208,6 +208,9 @@ int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix,
 
        or = rn->info;
        if (or->type == newor->type && or->cost == newor->cost) {
+               if (or->changed)
+                       return 0;
+
                if (or->type == OSPF_DESTINATION_NETWORK) {
                        if (or->paths->count != newor->paths->count)
                                return 0;
index 811581c0d30415aa3213c5225acddb0957012d13..c2ce0569dbc48d1420941f4d88aa5078c236c3f5 100644 (file)
@@ -124,6 +124,8 @@ struct ospf_route {
                struct route_standard std;
                struct route_external ext;
        } u;
+
+       bool changed;
 };
 
 extern struct ospf_path *ospf_path_new(void);