]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd, ospfd: update BGP when routes are removed from OSPF routing table
authorMadhuri Kuruganti <maduri111@gmail.com>
Sun, 18 Sep 2022 22:23:20 +0000 (03:53 +0530)
committerMadhuri Kuruganti <maduri111@gmail.com>
Wed, 12 Oct 2022 08:13:55 +0000 (13:43 +0530)
Signed-off-by: Madhuri Kuruganti <maduri111@gmail.com>
bgpd/bgp_orr.c
lib/orr_msg.h
ospfd/ospf_orr.c
ospfd/ospf_orr.h
ospfd/ospf_route.c
ospfd/ospf_route.h
ospfd/ospf_spf.c

index 894eae687f4b731e3d7eb5396cd3512e9d70e84b..81e6da2449111626419675b95914c816e04fc42d 100644 (file)
@@ -159,7 +159,6 @@ static void bgp_orr_group_free(struct bgp_orr_group *orr_group)
 
        /* Unset ORR Group parameters */
        XFREE(MTYPE_BGP_ORR_GROUP_NAME, orr_group->name);
-       memset(orr_group, 0, sizeof(struct bgp_orr_group));
 
        listnode_delete(bgp->orr_group[afi][safi], orr_group);
        XFREE(MTYPE_BGP_ORR_GROUP, orr_group);
@@ -933,6 +932,7 @@ static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
 {
        afi_t afi;
        safi_t safi;
+       bool add = false;
        bool root_found = false;
        uint32_t instId = 0;
        uint32_t numEntries = 0;
@@ -943,7 +943,7 @@ static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
 
        struct list *orr_group_list = NULL;
        struct bgp_orr_group *group = NULL;
-       struct listnode *node;
+       struct listnode *node, *nnode;
 
        struct bgp_orr_igp_metric *igp_metric = NULL;
        struct list *bgp_orr_igp_metric = NULL;
@@ -955,6 +955,7 @@ static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
        afi = family2afi(table->root.family);
        safi = table->safi;
        instId = table->instId;
+       add = table->add;
        numEntries = table->num_entries;
        prefix_copy(&root, &table->root);
 
@@ -985,8 +986,8 @@ static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
                zlog_debug("[BGP-ORR] %s: Address family %s", __func__,
                           get_afi_safi_str(afi, safi, false));
                zlog_debug("[BGP-ORR] %s: Root %pFX", __func__, &root);
-               zlog_debug("[BGP-ORR] %s: Number of entries %d", __func__,
-                          numEntries);
+               zlog_debug("[BGP-ORR] %s: Number of entries to be %s %d",
+                          __func__, add ? "added" : "deleted", numEntries);
                zlog_debug("[BGP-ORR] %s: Prefix (Cost) :", __func__);
                for (entry = 0; entry < numEntries; entry++)
                        zlog_debug("[BGP-ORR] %s: %pFX (%d)", __func__,
@@ -1007,27 +1008,52 @@ static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
                 * group
                 */
                if (prefix_cmp(&pfx, &root) == 0) {
-                       if (!group->igp_metric_info)
-                               group->igp_metric_info = list_new();
-
-                       bgp_orr_igp_metric = group->igp_metric_info;
-                       if (!bgp_orr_igp_metric)
-                               bgp_orr_igp_metric_register(group, false);
-                       assert(bgp_orr_igp_metric);
-
-                       for (entry = 0; entry < numEntries; entry++) {
-                               igp_metric = XCALLOC(
-                                       MTYPE_ORR_IGP_INFO,
-                                       sizeof(struct bgp_orr_igp_metric));
-                               if (!igp_metric)
+                       if (add) {
+                               /* Add new routes */
+                               if (!group->igp_metric_info)
+                                       group->igp_metric_info = list_new();
+
+                               bgp_orr_igp_metric = group->igp_metric_info;
+                               if (!bgp_orr_igp_metric)
                                        bgp_orr_igp_metric_register(group,
                                                                    false);
-
-                               prefix_copy(&igp_metric->prefix,
-                                           &table->nexthop[entry].prefix);
-                               igp_metric->igp_metric =
-                                       table->nexthop[entry].metric;
-                               listnode_add(bgp_orr_igp_metric, igp_metric);
+                               assert(bgp_orr_igp_metric);
+
+                               for (entry = 0; entry < numEntries; entry++) {
+                                       igp_metric = XCALLOC(
+                                               MTYPE_ORR_IGP_INFO,
+                                               sizeof(struct
+                                                      bgp_orr_igp_metric));
+                                       if (!igp_metric)
+                                               bgp_orr_igp_metric_register(
+                                                       group, false);
+
+                                       prefix_copy(
+                                               &igp_metric->prefix,
+                                               &table->nexthop[entry].prefix);
+                                       igp_metric->igp_metric =
+                                               table->nexthop[entry].metric;
+                                       listnode_add(bgp_orr_igp_metric,
+                                                    igp_metric);
+                               }
+                       } else {
+                               /* Delete old routes */
+                               for (entry = 0; entry < numEntries; entry++) {
+                                       for (ALL_LIST_ELEMENTS(
+                                                    group->igp_metric_info,
+                                                    node, nnode, igp_metric)) {
+                                               if (prefix_cmp(
+                                                           &igp_metric->prefix,
+                                                           &table->nexthop[entry]
+                                                                    .prefix))
+                                                       continue;
+                                               listnode_delete(
+                                                       group->igp_metric_info,
+                                                       igp_metric);
+                                               XFREE(MTYPE_ORR_IGP_INFO,
+                                                     igp_metric);
+                                       }
+                               }
                        }
                        root_found = true;
                        break;
index ec13df61bb0070de973eb6e3be58fcb371330d54..b0c4c48df87235422dc1847d9eaebc48cf092a76 100644 (file)
@@ -51,6 +51,9 @@ struct orr_igp_metric_info {
 
        safi_t safi;
 
+       /* Add or delete routes */
+       bool add;
+
        /* IGP metric from Active Root. */
        struct prefix root;
        uint32_t num_entries;
index 41e2c8e2df0aa70ef2a8bce0a2c9619cab135b86..09dd5970ee573af7e3502f081bfa55ce68aded6e 100644 (file)
@@ -258,8 +258,8 @@ int ospf_orr_igp_metric_register(struct orr_igp_metric_reg msg)
        return 0;
 }
 
-void ospf_orr_igp_metric_send_update(struct orr_root *root,
-                                    unsigned short instance)
+void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
+                                        unsigned short instance)
 {
        int ret;
        uint8_t count = 0;
@@ -271,8 +271,8 @@ void ospf_orr_igp_metric_send_update(struct orr_root *root,
        msg.proto = ZEBRA_ROUTE_OSPF;
        msg.safi = root->safi;
        msg.instId = instance;
+       msg.add = true;
        prefix_copy(&msg.root, &root->prefix);
-       msg.num_entries = root->new_table->count;
 
        /* Update prefix table from ORR Route table */
        for (rn = route_top(root->new_table); rn; rn = route_next(rn)) {
@@ -280,7 +280,8 @@ void ospf_orr_igp_metric_send_update(struct orr_root *root,
                if (!or)
                        continue;
 
-               if (or->type != OSPF_DESTINATION_NETWORK)
+               if (or->type != OSPF_DESTINATION_NETWORK &&
+                   or->type != OSPF_DESTINATION_DISCARD)
                        continue;
 
                if (ospf_route_match_same(root->old_table,
@@ -318,6 +319,74 @@ void ospf_orr_igp_metric_send_update(struct orr_root *root,
        }
 }
 
+void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
+                                           unsigned short instance)
+{
+       int ret;
+       uint8_t count = 0;
+       struct route_node *rn;
+       struct ospf_route *or ;
+       struct orr_igp_metric_info msg;
+
+       if (!root->old_table)
+               return;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.proto = ZEBRA_ROUTE_OSPF;
+       msg.instId = instance;
+       msg.safi = root->safi;
+       msg.add = false;
+       prefix_copy(&msg.root, &root->prefix);
+
+       /* Update prefix table from ORR Route table */
+       for (rn = route_top(root->old_table); rn; rn = route_next(rn)) {
+               or = rn->info;
+               if (!or)
+                       continue;
+
+               if (or->path_type != OSPF_PATH_INTRA_AREA &&
+                   or->path_type != OSPF_PATH_INTER_AREA)
+                       continue;
+
+               if (or->type != OSPF_DESTINATION_NETWORK &&
+                   or->type != OSPF_DESTINATION_DISCARD)
+                       continue;
+
+               if (ospf_route_exist_new_table(root->new_table,
+                                              (struct prefix_ipv4 *)&rn->p))
+                       continue;
+
+               if (count < ORR_MAX_PREFIX) {
+                       prefix_copy(&msg.nexthop[count].prefix,
+                                   (struct prefix_ipv4 *)&rn->p);
+                       msg.nexthop[count].metric = or->cost;
+                       count++;
+               } else {
+                       msg.num_entries = count;
+                       ret = zclient_send_opaque(zclient,
+                                                 ORR_IGP_METRIC_UPDATE,
+                                                 (uint8_t *)&msg, sizeof(msg));
+                       if (ret != ZCLIENT_SEND_SUCCESS)
+                               ospf_orr_debug(
+                                       "%s: Failed to send message to BGP.",
+                                       __func__);
+                       count = 0;
+                       prefix_copy(&msg.nexthop[count].prefix,
+                                   (struct prefix_ipv4 *)&rn->p);
+                       msg.nexthop[count].metric = or->cost;
+                       count++;
+               }
+       }
+       if (count > 0 && count <= ORR_MAX_PREFIX) {
+               msg.num_entries = count;
+               ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
+                                         (uint8_t *)&msg, sizeof(msg));
+               if (ret != ZCLIENT_SEND_SUCCESS)
+                       ospf_orr_debug("%s: Failed to send message to BGP.",
+                                      __func__);
+       }
+}
+
 static void ospf_show_orr_root(struct orr_root *root)
 {
        if (!root)
@@ -438,7 +507,8 @@ void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa)
 }
 
 /* Do not Install routes to root table. Just update table ponters */
-void ospf_orr_route_install(struct orr_root *root, struct route_table *rt)
+void ospf_orr_route_install(struct orr_root *root, struct route_table *rt,
+                           unsigned short instance)
 {
        /*
         * rt contains new routing table, new_table contains an old one.
@@ -449,6 +519,14 @@ void ospf_orr_route_install(struct orr_root *root, struct route_table *rt)
 
        root->old_table = root->new_table;
        root->new_table = rt;
+
+       /* Send update to BGP to delete old routes. */
+       ospf_orr_igp_metric_send_update_delete(root, instance);
+
+       /* REVISIT: Skipping external route table for now */
+
+       /* Send update to BGP to add new routes. */
+       ospf_orr_igp_metric_send_update_add(root, instance);
 }
 
 void ospf_orr_spf_calculate_schedule(struct ospf *ospf)
index 24b610c61c4b8ce218b4a06451aa6d1a44584e00..d0a6f6e790ce4ef01f9db56d76a9a09d295e2102 100644 (file)
 extern struct zclient *zclient;
 
 extern int ospf_orr_igp_metric_register(struct orr_igp_metric_reg orr_reg);
-extern void ospf_orr_igp_metric_send_update(struct orr_root *root,
-                                           unsigned short instance);
+extern void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
+                                               unsigned short instance);
+extern void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
+                                                  unsigned short instance);
 extern void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add);
 extern void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa);
 extern void ospf_orr_route_install(struct orr_root *root,
-                                  struct route_table *rt);
+                                  struct route_table *rt,
+                                  unsigned short instance);
 extern void ospf_orr_spf_calculate_schedule(struct ospf *ospf);
 extern void ospf_orr_spf_calculate_area(struct ospf *ospf,
                                        struct ospf_area *area,
index 6360d8ec601d8fc033cb93464b0c8449ece4bf9e..26f593f08971bd007564365fbf73e019ba2a217b 100644 (file)
@@ -151,8 +151,8 @@ void ospf_route_table_free(struct route_table *rt)
    otherwise return 0. Since the ZEBRA-RIB does an implicit
    withdraw, it is not necessary to send a delete, an add later
    will act like an implicit delete. */
-static int ospf_route_exist_new_table(struct route_table *rt,
-                                     struct prefix_ipv4 *prefix)
+int ospf_route_exist_new_table(struct route_table *rt,
+                              struct prefix_ipv4 *prefix)
 {
        struct route_node *rn;
 
index fa9478fcedb2bd4136c7f06d244ffca31b7e6e08..e7e2b651c56a61022e684c5fee0eea15510ab51c 100644 (file)
@@ -172,5 +172,6 @@ extern void ospf_delete_discard_route(struct ospf *, struct route_table *,
                                      struct prefix_ipv4 *);
 extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *,
                                 struct ospf_route *);
-
+extern int ospf_route_exist_new_table(struct route_table *rt,
+                                     struct prefix_ipv4 *prefix);
 #endif /* _ZEBRA_OSPF_ROUTE_H */
index 467ec760904278d7a6a4d531e4eaf3b17b9fbaa5..74213d7de283debfb6139f35a63d05f2097263e5 100644 (file)
@@ -2060,7 +2060,7 @@ void ospf_orr_spf_calculate_schedule_worker(struct thread *thread)
 
                        /* Update routing table. */
                        monotime(&start_time);
-                       ospf_orr_route_install(root, new_table);
+                       ospf_orr_route_install(root, new_table, ospf->instance);
                        rt_time = monotime_since(&start_time, NULL);
 
                        /*
@@ -2111,13 +2111,6 @@ void ospf_orr_spf_calculate_schedule_worker(struct thread *thread)
                                                abr_time, ospf->areas->count);
                                zlog_info("Reason(s) for SPF: %s", rbuf);
                        }
-
-                       root->new_table = new_table;
-                       root->new_rtrs = new_rtrs;
-
-                       /* Send IGP Metric update to BGP */
-                       ospf_orr_igp_metric_send_update(root, ospf->instance);
-
                } /* ALL_LIST_ELEMENTS_RO() */
        } /* FOREACH_AFI_SAFI() */
 }