/* 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);
{
afi_t afi;
safi_t safi;
+ bool add = false;
bool root_found = false;
uint32_t instId = 0;
uint32_t numEntries = 0;
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;
afi = family2afi(table->root.family);
safi = table->safi;
instId = table->instId;
+ add = table->add;
numEntries = table->num_entries;
prefix_copy(&root, &table->root);
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__,
* 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;
safi_t safi;
+ /* Add or delete routes */
+ bool add;
+
/* IGP metric from Active Root. */
struct prefix root;
uint32_t num_entries;
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;
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)) {
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,
}
}
+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)
}
/* 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.
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)
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,
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;
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 */
/* 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);
/*
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() */
}