diff --git a/bgpd/bgp_orr.c b/bgpd/bgp_orr.c index 894eae687f4b..81e6da244911 100644 --- a/bgpd/bgp_orr.c +++ b/bgpd/bgp_orr.c @@ -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; diff --git a/lib/orr_msg.h b/lib/orr_msg.h index ec13df61bb00..b0c4c48df872 100644 --- a/lib/orr_msg.h +++ b/lib/orr_msg.h @@ -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; diff --git a/ospfd/ospf_orr.c b/ospfd/ospf_orr.c index 41e2c8e2df0a..09dd5970ee57 100644 --- a/ospfd/ospf_orr.c +++ b/ospfd/ospf_orr.c @@ -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) diff --git a/ospfd/ospf_orr.h b/ospfd/ospf_orr.h index 24b610c61c4b..d0a6f6e790ce 100644 --- a/ospfd/ospf_orr.h +++ b/ospfd/ospf_orr.h @@ -34,12 +34,15 @@ 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, diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 6360d8ec601d..26f593f08971 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -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; diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index fa9478fcedb2..e7e2b651c56a 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -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 */ diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 467ec7609042..74213d7de283 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -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() */ }