From 960417cf06ea99482b594e96ba7deb9d17afad76 Mon Sep 17 00:00:00 2001 From: rgirada Date: Sat, 5 Sep 2020 08:15:51 -0700 Subject: [PATCH] ospfd: OSPF external summarisation scenarios Description: Aggergation handled in the following scenarios. 1. Route update from Zebra. 2. Refresh external LSA. 3. Processing routemap update. 4. Self originated lsa processing. Signed-off-by: Rajesh Girada --- ospfd/ospf_flood.c | 48 ++++++++- ospfd/ospf_lsa.c | 93 +++++++++++++++-- ospfd/ospf_zebra.c | 243 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 318 insertions(+), 66 deletions(-) diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 72939bfcca..cb2b7c2365 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -154,6 +154,9 @@ static void ospf_process_self_originated_lsa(struct ospf *ospf, struct ospf_interface *oi; struct external_info *ei; struct listnode *node; + struct as_external_lsa *al; + struct prefix_ipv4 p; + struct ospf_external_aggr_rt *aggr; if (IS_DEBUG_OSPF_EVENT) zlog_debug( @@ -222,12 +225,51 @@ static void ospf_process_self_originated_lsa(struct ospf *ospf, ospf_translated_nssa_refresh(ospf, NULL, new); return; } + + al = (struct as_external_lsa *)new->data; + p.family = AF_INET; + p.prefixlen = ip_masklen(al->mask); + p.prefix = new->data->id; + ei = ospf_external_info_check(ospf, new); - if (ei) + if (ei) { + if (ospf_external_aggr_match(ospf, &ei->p)) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s, Matching external aggregate route found for %pI4, so don't refresh it.", + __func__, + &ei->p.prefix); + + /* Aggregated external route shouldn't + * be in LSDB. + */ + if (!IS_LSA_MAXAGE(new)) + ospf_lsa_flush_as(ospf, new); + + return; + } + ospf_external_lsa_refresh(ospf, new, ei, LSA_REFRESH_FORCE, false); - else - ospf_lsa_flush_as(ospf, new); + } else { + aggr = (struct ospf_external_aggr_rt *) + ospf_extrenal_aggregator_lookup(ospf, &p); + if (aggr) { + struct external_info ei_aggr; + + memset(&ei_aggr, 0, + sizeof(struct external_info)); + ei_aggr.p = aggr->p; + ei_aggr.tag = aggr->tag; + ei_aggr.instance = ospf->instance; + ei_aggr.route_map_set.metric = -1; + ei_aggr.route_map_set.metric_type = -1; + + ospf_external_lsa_refresh(ospf, new, &ei_aggr, + LSA_REFRESH_FORCE, true); + } else + ospf_lsa_flush_as(ospf, new); + } break; case OSPF_OPAQUE_AREA_LSA: ospf_opaque_lsa_refresh(new); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index b77e894c14..42fc3288cd 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -1977,10 +1977,6 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, return NULL; } - /* Check the AS-external-LSA should be originated. */ - if (!ospf_redistribute_check(ospf, ei, NULL)) - return NULL; - /* Create new AS-external-LSA instance. */ if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) { if (IS_DEBUG_OSPF_EVENT) @@ -2056,6 +2052,7 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf) void ospf_external_lsa_rid_change(struct ospf *ospf) { struct external_info *ei; + struct ospf_external_aggr_rt *aggr; int type; for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { @@ -2087,9 +2084,21 @@ void ospf_external_lsa_rid_change(struct ospf *ospf) (struct prefix_ipv4 *)&ei->p)) continue; - if (!ospf_external_lsa_originate(ospf, ei)) + if (!ospf_redistribute_check(ospf, ei, NULL)) + continue; + + aggr = ospf_external_aggr_match(ospf, &ei->p); + if (aggr) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "Originate Summary LSA after reset/router-ID change"); + /* Here the LSA is originated as new */ + ospf_originate_summary_lsa(ospf, aggr, + ei); + } else if (!ospf_external_lsa_originate(ospf, + ei)) flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, - "LSA: AS-external-LSA was not originated."); + "LSA: AS-external-LSA was not originated."); } } } @@ -2226,16 +2235,51 @@ void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, if (ei) { if (!is_prefix_default(&ei->p)) { struct ospf_lsa *lsa; + struct ospf_external_aggr_rt *aggr; + aggr = ospf_external_aggr_match(ospf, + &ei->p); lsa = ospf_external_info_find_lsa( - ospf, &ei->p); - if (lsa) + ospf, &ei->p); + if (aggr) { + /* Check the AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check( + ospf, ei, NULL)) { + + ospf_unlink_ei_from_aggr( + ospf, aggr, ei); + continue; + } + + if (IS_DEBUG_OSPF( + lsa, + EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Send Aggreate LSA (%pFX/%d)", + __func__, + &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_originate_summary_lsa( + ospf, aggr, ei); + + } else if (lsa) { + + if (IS_LSA_MAXAGE(lsa)) + force = LSA_REFRESH_FORCE; + ospf_external_lsa_refresh( ospf, lsa, ei, force, false); - else + } else { + if (!ospf_redistribute_check( + ospf, ei, NULL)) + continue; ospf_external_lsa_originate( ospf, ei); + } } } } @@ -3453,7 +3497,11 @@ void ospf_schedule_lsa_flush_area(struct ospf_area *area, struct ospf_lsa *lsa) struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) { struct external_info *ei; + struct ospf_external_aggr_rt *aggr; struct ospf_lsa *new = NULL; + struct as_external_lsa *al; + struct prefix_ipv4 p; + assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF)); assert(IS_LSA_SELF(lsa)); assert(lsa->lock > 0); @@ -3476,14 +3524,37 @@ struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) /* Translated from NSSA Type-5s are refreshed when * from refresh of Type-7 - do not refresh these directly. */ + + al = (struct as_external_lsa *)lsa->data; + p.family = AF_INET; + p.prefixlen = ip_masklen(al->mask); + p.prefix = lsa->data->id; + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) break; ei = ospf_external_info_check(ospf, lsa); if (ei) new = ospf_external_lsa_refresh( ospf, lsa, ei, LSA_REFRESH_FORCE, false); - else - ospf_lsa_flush_as(ospf, lsa); + else { + aggr = (struct ospf_external_aggr_rt *) + ospf_extrenal_aggregator_lookup(ospf, &p); + if (aggr) { + struct external_info ei_aggr; + + memset(&ei_aggr, 0, + sizeof(struct external_info)); + ei_aggr.p = aggr->p; + ei_aggr.tag = aggr->tag; + ei_aggr.instance = ospf->instance; + ei_aggr.route_map_set.metric = -1; + ei_aggr.route_map_set.metric_type = -1; + + ospf_external_lsa_refresh(ospf, lsa, &ei_aggr, + LSA_REFRESH_FORCE, true); + } else + ospf_lsa_flush_as(ospf, lsa); + } break; case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 0f5da54828..fd965e8f21 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1181,24 +1181,100 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) if (is_prefix_default(&p)) ospf_external_lsa_refresh_default(ospf); else { - struct ospf_lsa *current; + struct ospf_external_aggr_rt *aggr; + struct as_external_lsa *al; + struct ospf_lsa *lsa = NULL; + struct in_addr mask; + + aggr = ospf_external_aggr_match(ospf, + &ei->p); + + if (aggr) { + /* Check the AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check( + ospf, ei, NULL)) + return 0; - current = ospf_external_info_find_lsa( - ospf, &ei->p); - if (!current) - ospf_external_lsa_originate( - ospf, ei); - else { if (IS_DEBUG_OSPF( - zebra, - ZEBRA_REDISTRIBUTE)) + lsa, + EXTNL_LSA_AGGR)) zlog_debug( - "ospf_zebra_read_route() : %pI4 refreshing LSA", - &p.prefix); - ospf_external_lsa_refresh( - ospf, current, ei, - LSA_REFRESH_FORCE, - false); + "%s: Send Aggreate LSA (%pI4/%d)", + __func__, + &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_originate_summary_lsa( + ospf, aggr, ei); + + /* Handling the case where the + * external route prefix + * and aggegate prefix is same + * If same dont flush the + * originated + * external LSA. + */ + if (prefix_same( + (struct prefix + *)&aggr->p, + (struct prefix *)&ei + ->p)) + return 0; + + lsa = ospf_external_info_find_lsa( + ospf, &ei->p); + + if (lsa) { + al = (struct + as_external_lsa *) + lsa->data; + masklen2ip( + ei->p.prefixlen, + &mask); + + if (mask.s_addr + != al->mask.s_addr) + return 0; + + ospf_external_lsa_flush( + ospf, ei->type, + &ei->p, 0); + } + } else { + struct ospf_lsa *current; + + current = + ospf_external_info_find_lsa( + ospf, &ei->p); + if (!current) { + /* Check the + * AS-external-LSA + * should be + * originated. + */ + if (!ospf_redistribute_check( + ospf, ei, + NULL)) + return 0; + + ospf_external_lsa_originate( + ospf, ei); + } else { + if (IS_DEBUG_OSPF( + zebra, + ZEBRA_REDISTRIBUTE)) + zlog_debug( + "%s: %pI4 refreshing LSA", + __func__, + &p.prefix); + ospf_external_lsa_refresh( + ospf, current, + ei, + LSA_REFRESH_FORCE, + false); + } } } } @@ -1212,21 +1288,36 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { - /* - * Check if default-information originate is - * with some routemap prefix/access list match. - * Apply before ei is deleted. - */ + struct ospf_external_aggr_rt *aggr; + ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p); - if (ei) + if (ei == NULL) + return 0; + else + /* + * Check if default-information originate i + * with some routemap prefix/access list match. + * Apply before ei is deleted. + */ ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); - ospf_external_info_delete(ospf, rt_type, api.instance, p); - if (is_prefix_default(&p)) - ospf_external_lsa_refresh_default(ospf); - else - ospf_external_lsa_flush(ospf, rt_type, &p, - ifindex /*, nexthop */); + aggr = ospf_external_aggr_match(ospf, &ei->p); + + if (aggr && (ei->aggr_route == aggr)) { + ospf_unlink_ei_from_aggr(ospf, aggr, ei); + + ospf_external_info_delete(ospf, rt_type, api.instance, + p); + } else { + ospf_external_info_delete(ospf, rt_type, api.instance, + p); + + if (is_prefix_default(&p)) + ospf_external_lsa_refresh_default(ospf); + else + ospf_external_lsa_flush(ospf, rt_type, &p, + ifindex /*, nexthop */); + } } @@ -1318,32 +1409,80 @@ static int ospf_distribute_list_update_timer(struct thread *thread) if ((ei = rn->info) != NULL) { if (is_prefix_default(&ei->p)) default_refresh = 1; - else if ( - (lsa = ospf_external_info_find_lsa( - ospf, &ei->p))) { - int force = - LSA_REFRESH_IF_CHANGED; - /* If this is a MaxAge LSA, we - * need to force refresh it - * because distribute settings - * might have changed and now, - * this LSA needs to be - * originated, not be removed. - * If we don't force refresh it, - * it will remain a MaxAge LSA - * because it will look like it - * hasn't changed. Neighbors - * will not receive updates for - * this LSA. - */ - if (IS_LSA_MAXAGE(lsa)) - force = LSA_REFRESH_FORCE; + else { + struct ospf_external_aggr_rt + *aggr; + aggr = ospf_external_aggr_match( + ospf, &ei->p); + if (aggr) { + /* Check the + * AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check( + ospf, ei, + NULL)) { - ospf_external_lsa_refresh( - ospf, lsa, ei, force, false); - } else - ospf_external_lsa_originate( - ospf, ei); + ospf_unlink_ei_from_aggr( + ospf, + aggr, + ei); + continue; + } + + if (IS_DEBUG_OSPF( + lsa, + EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Send Aggregate LSA (%pI4/%d)", + __func__, + &aggr->p.prefix, + aggr->p.prefixlen); + + /* Originate Aggregate + * LSA + */ + ospf_originate_summary_lsa( + ospf, aggr, ei); + } else if ( + (lsa = ospf_external_info_find_lsa( + ospf, + &ei->p))) { + int force = + LSA_REFRESH_IF_CHANGED; + /* If this is a MaxAge + * LSA, we need to + * force refresh it + * because distribute + * settings might have + * changed and now, + * this LSA needs to be + * originated, not be + * removed. + * If we don't force + * refresh it, it will + * remain a MaxAge LSA + * because it will look + * like it hasn't + * changed. Neighbors + * will not receive + * updates for this LSA. + */ + if (IS_LSA_MAXAGE(lsa)) + force = LSA_REFRESH_FORCE; + + ospf_external_lsa_refresh( + ospf, lsa, ei, + force, false); + } else { + if (!ospf_redistribute_check( + ospf, ei, + NULL)) + continue; + ospf_external_lsa_originate( + ospf, ei); + } + } } } }