diff options
author | rgirada <rgirada@vmware.com> | 2020-08-15 11:55:40 +0200 |
---|---|---|
committer | rgirada <rgirada@vmware.com> | 2020-11-02 06:17:26 +0100 |
commit | 63f0e9415c42fd60fdcf583ab20c3cc096fc8483 (patch) | |
tree | 06c8a3b161fc9c0987197c833f050b0eddf1671a /ospfd | |
parent | ospfd: Summarisation init/de-init. (diff) | |
download | frr-63f0e9415c42fd60fdcf583ab20c3cc096fc8483.tar.xz frr-63f0e9415c42fd60fdcf583ab20c3cc096fc8483.zip |
ospfd: ospf summarisation core handlers
Description:
Apis for creating/deleting aggregate routes.
Origination of summary route on behalf of matched external routes.
Signed-off-by: Rajesh Girada <rgirada@vmware.com>
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/ospf_asbr.c | 690 | ||||
-rw-r--r-- | ospfd/ospf_asbr.h | 19 | ||||
-rw-r--r-- | ospfd/ospf_flood.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 38 | ||||
-rw-r--r-- | ospfd/ospf_lsa.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 10 |
6 files changed, 736 insertions, 26 deletions
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 8d262bd73..c5586f7d9 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -42,7 +42,7 @@ #include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" - +#include "ospfd/ospf_errors.h" /* Remove external route. */ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p) @@ -80,6 +80,7 @@ struct external_info *ospf_external_info_new(uint8_t type, new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info)); new->type = type; new->instance = instance; + new->to_be_processed = 0; ospf_reset_route_map_set_values(&new->route_map_set); return new; @@ -147,6 +148,7 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance, new->nexthop = nexthop; new->tag = tag; new->orig_tag = tag; + new->aggr_route = NULL; /* we don't unlock rn from the get() because we're attaching the info */ if (rn) @@ -378,6 +380,41 @@ ospf_external_aggregator_new(struct prefix_ipv4 *p) return aggr; } +static void ospf_aggr_handle_external_info(void *data) +{ + struct external_info *ei = (struct external_info *)data; + struct ospf_external_aggr_rt *aggr = NULL; + struct ospf *ospf = NULL; + struct ospf_lsa *lsa = NULL; + + ei->aggr_route = NULL; + + ei->to_be_processed = true; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Handle extrenal route(%pI4/%d)", __func__, + &ei->p.prefix, ei->p.prefixlen); + + ospf = ospf_lookup_instance(ei->instance); + + assert(ospf); + + if (!ospf_redistribute_check(ospf, ei, NULL)) + return; + + aggr = ospf_external_aggr_match(ospf, &ei->p); + if (aggr) { + lsa = ospf_originate_summary_lsa(ospf, aggr, ei); + return; + } + + lsa = ospf_external_info_find_lsa(ospf, &ei->p); + if (lsa) + ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, 1); + else + lsa = ospf_external_lsa_originate(ospf, ei); +} + static void ospf_aggr_unlink_external_info(void *data) { struct external_info *ei = (struct external_info *)data; @@ -394,11 +431,656 @@ void ospf_external_aggregator_free(struct ospf_external_aggr_rt *aggr) (void *)ospf_aggr_unlink_external_info); if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) - zlog_debug("%s: Release the aggregator Address(%s/%d)", - __func__, inet_ntoa(aggr->p.prefix), - aggr->p.prefixlen); + zlog_debug("%s: Release the aggregator Address(%pI4/%d)", + __func__, &aggr->p.prefix, aggr->p.prefixlen); hash_free(aggr->match_extnl_hash); aggr->match_extnl_hash = NULL; XFREE(MTYPE_OSPF_EXTERNAL_RT_AGGR, aggr); } + +static void ospf_external_aggr_add(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr) +{ + struct route_node *rn; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Adding Aggregate route to Aggr table (%pI4/%d)", + __func__, &aggr->p.prefix, aggr->p.prefixlen); + rn = route_node_get(ospf->rt_aggr_tbl, (struct prefix *)&aggr->p); + if (rn->info) + route_unlock_node(rn); + else + rn->info = aggr; +} + +static void ospf_external_aggr_delete(struct ospf *ospf, struct route_node *rn) +{ + struct ospf_external_aggr_rt *aggr = rn->info; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Deleting Aggregate route (%pI4/%d)", __func__, + &aggr->p.prefix, aggr->p.prefixlen); + + /* Sent a Max age LSA if it is already originated. */ + if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Flushing Aggregate route (%pI4/%d)", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + ospf_external_lsa_flush(ospf, 0, &aggr->p, 0); + } + + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); +} + +struct ospf_external_aggr_rt * +ospf_extrenal_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p) +{ + struct route_node *rn; + struct ospf_external_aggr_rt *summary_rt = NULL; + + rn = route_node_lookup(ospf->rt_aggr_tbl, (struct prefix *)p); + if (rn) { + summary_rt = rn->info; + route_unlock_node(rn); + return summary_rt; + } + return NULL; +} + +struct ospf_external_aggr_rt *ospf_external_aggr_match(struct ospf *ospf, + struct prefix_ipv4 *p) +{ + struct route_node *node; + struct ospf_external_aggr_rt *summary_rt = NULL; + + node = route_node_match(ospf->rt_aggr_tbl, (struct prefix *)p); + if (node) { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + if (node->info) { + struct ospf_external_aggr_rt *ag = node->info; + + zlog_debug( + "%s: Matching aggregator found.prefix:%pI4/%d Aggregator %pI4/%d\n", + __func__, &p->prefix, p->prefixlen, + &ag->p.prefix, ag->p.prefixlen); + } + + summary_rt = node->info; + route_unlock_node(node); + return summary_rt; + } + return NULL; +} + +void ospf_unlink_ei_from_aggr(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei) +{ + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Unlinking extrenal route(%pI4/%d) from aggregator(%pI4/%d), external route count:%ld", + __func__, &ei->p.prefix, ei->p.prefixlen, + &aggr->p.prefix, aggr->p.prefixlen, + OSPF_EXTERNAL_RT_COUNT(aggr)); + hash_release(aggr->match_extnl_hash, ei); + ei->aggr_route = NULL; + + /* Flush the aggreagte route if matching + * external route count becomes zero. + */ + if (!OSPF_EXTERNAL_RT_COUNT(aggr) + && CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Flushing the aggreagte route (%pI4/%d)", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + + /* Flush the aggregate LSA */ + ospf_external_lsa_flush(ospf, 0, &aggr->p, 0); + + /* Unset the Origination flag */ + UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + } +} + +static void ospf_link_ei_to_aggr(struct ospf_external_aggr_rt *aggr, + struct external_info *ei) +{ + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Linking extrenal route(%pI4/%d) to aggregator(%pI4/%d)", + __func__, &ei->p.prefix, ei->p.prefixlen, + &aggr->p.prefix, aggr->p.prefixlen); + hash_get(aggr->match_extnl_hash, ei, hash_alloc_intern); + ei->aggr_route = aggr; +} + +struct ospf_lsa *ospf_originate_summary_lsa(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei) +{ + struct ospf_lsa *lsa; + struct external_info ei_aggr; + struct as_external_lsa *asel; + struct ospf_external_aggr_rt *old_aggr; + route_tag_t tag = 0; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Prepare to originate Summary route(%pI4/%d)", + __func__, &aggr->p.prefix, aggr->p.prefixlen); + + /* This case to handle when the overlapping aggregator address + * is availbe.Best match will be considered.So need to delink + * from old aggregator and link to the new aggr. + */ + if (ei->aggr_route) { + if (ei->aggr_route != aggr) { + old_aggr = ei->aggr_route; + ospf_unlink_ei_from_aggr(ospf, old_aggr, ei); + } + } + + /* Add the external route to hash table */ + ospf_link_ei_to_aggr(aggr, ei); + + lsa = ospf_external_info_find_lsa(ospf, &aggr->p); + /* Dont originate external LSA, + * If it is configured not to advertise. + */ + if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) { + /* If it is already originated as external LSA, + * But, it is configured not to advertise then + * flush the originated external lsa. + */ + if (lsa) + ospf_external_lsa_flush(ospf, 0, &aggr->p, 0); + UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Don't originate the summary address,It is configured to not-advertise.", + __func__); + return NULL; + } + + /* Prepare the extrenal_info for aggregator */ + memset(&ei_aggr, 0, sizeof(struct external_info)); + ei_aggr.p = aggr->p; + ei_aggr.tag = aggr->tag; + ei_aggr.type = 0; + ei_aggr.instance = ospf->instance; + ei_aggr.route_map_set.metric = -1; + ei_aggr.route_map_set.metric_type = -1; + + /* Summary route already originated, + * So, Do nothing. + */ + if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + if (!lsa) { + flog_warn(EC_OSPF_LSA_MISSING, + "%s: Could not refresh/originate %pI4/%d", + __func__, &aggr->p.prefix, aggr->p.prefixlen); + return NULL; + } + + asel = (struct as_external_lsa *)lsa->data; + tag = (unsigned long)ntohl(asel->e[0].route_tag); + + /* If tag modified , then re-originate the route + * with modified tag details. + */ + if (tag != ei_aggr.tag) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Route tag changed(old:%d new:%d,So refresh the summary route.(%pI4/%d)", + __func__, tag, ei_aggr.tag, + &aggr->p.prefix, aggr->p.prefixlen); + + ospf_external_lsa_refresh(ospf, lsa, &ei_aggr, + LSA_REFRESH_FORCE, 1); + } + return lsa; + } + + if (lsa && IS_LSA_MAXAGE(lsa)) { + /* This is special case. + * If a summary route need to be originated but where + * summary route already exist in lsdb with maxage, then + * it need to be refreshed. + */ + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: LSA is in MAX-AGE so refreshing LSA(%pI4/%d)", + __PRETTY_FUNCTION__, &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_external_lsa_refresh(ospf, lsa, &ei_aggr, + LSA_REFRESH_FORCE, 1); + SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + return lsa; + } + + /* If the external route prefix same as aggregate route + * and if external route is already originated as TYPE-5 + * then it need to be refreshed and originate bit should + * be set. + */ + if (lsa && prefix_same((struct prefix *)&ei_aggr.p, + (struct prefix *)&ei->p)) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: External route prefix is same as aggr so refreshing LSA(%pI4/%d)", + __PRETTY_FUNCTION__, &aggr->p.prefix, + aggr->p.prefixlen); + ospf_external_lsa_refresh(ospf, lsa, &ei_aggr, + LSA_REFRESH_FORCE, 1); + SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + return lsa; + } + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Originate Summary route(%pI4/%d)", __func__, + &aggr->p.prefix, aggr->p.prefixlen); + + /* Originate summary LSA */ + lsa = ospf_external_lsa_originate(ospf, &ei_aggr); + if (lsa) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Set the origination bit for aggregator", + __func__); + SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + } + + return lsa; +} +void ospf_unset_all_aggr_flag(struct ospf *ospf) +{ + struct route_node *rn = NULL; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("Unset the origination bit for all aggregator"); + + for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + struct ospf_external_aggr_rt *aggr = rn->info; + + UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + } +} + +static void ospf_delete_all_marked_aggregators(struct ospf *ospf) +{ + struct route_node *rn = NULL; + + /* Loop through all the aggregators, Delete all aggregators + * which are marked as DELETE. Set action to NONE for remaining + * aggregators + */ + for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + struct ospf_external_aggr_rt *aggr = rn->info; + + if (aggr->action != OSPF_ROUTE_AGGR_DEL) { + aggr->action = OSPF_ROUTE_AGGR_NONE; + continue; + } + ospf_external_aggr_delete(ospf, rn); + ospf_external_aggregator_free(aggr); + } +} + +static void ospf_handle_aggregated_exnl_rt(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei) +{ + struct ospf_lsa *lsa; + struct as_external_lsa *al; + struct in_addr mask; + + /* Handling the case where the external route prefix + * and aggregate prefix is same + * If same dont flush the originated external LSA. + */ + if (prefix_same((struct prefix *)&aggr->p, (struct prefix *)&ei->p)) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: External Route prefix same as Aggregator(%pI4/%d), so dont flush.", + __func__, &ei->p.prefix, ei->p.prefixlen); + return; + } + + 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; + + ospf_external_lsa_flush(ospf, ei->type, &ei->p, 0); + } +} + +static void ospf_handle_exnl_rt_after_aggr_del(struct ospf *ospf, + struct external_info *ei) +{ + struct ospf_lsa *lsa; + + /* Process only marked external routes. + * These routes were part of a deleted + * aggregator.So, originate now. + */ + if (!ei->to_be_processed) + return; + + ei->to_be_processed = false; + + lsa = ospf_external_info_find_lsa(ospf, &ei->p); + + if (lsa) + ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, 0); + else { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Originate external route(%pI4/%d)", + __func__, &ei->p.prefix, ei->p.prefixlen); + + ospf_external_lsa_originate(ospf, ei); + } +} + +static void ospf_handle_external_aggr_add(struct ospf *ospf) +{ + struct external_info *ei; + struct route_node *rn = NULL; + struct route_table *rt = NULL; + int type = 0; + + /* Delete all the aggregators which are marked as + * OSPF_ROUTE_AGGR_DEL. + */ + ospf_delete_all_marked_aggregators(ospf); + + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + struct ospf_external_aggr_rt *aggr; + + ext_list = ospf->external[type]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + rt = ext->external_info; + if (!rt) + continue; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + ei = rn->info; + if (is_prefix_default(&ei->p)) + continue; + + /* Check the AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check(ospf, ei, NULL)) + continue; + + aggr = ospf_external_aggr_match(ospf, &ei->p); + + /* If matching aggregator found, Add + * the external route reference to the + * aggregator and originate the aggr + * route if it is advertisable. + * flush the external LSA if it is + * already originated for this external + * prefix. + */ + if (aggr) { + ospf_originate_summary_lsa(ospf, aggr, + ei); + + /* All aggregated external rts + * are handled here. + */ + ospf_handle_aggregated_exnl_rt( + ospf, aggr, ei); + continue; + } + + /* External routes which are only out + * of aggregation will be handled here. + */ + ospf_handle_exnl_rt_after_aggr_del(ospf, ei); + } + } + } +} + +static void +ospf_aggr_handle_advertise_change(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei_aggr) +{ + struct ospf_lsa *lsa; + + /* Check if advertise option modified. */ + if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Don't originate the summary address,It is configured to not-advertise.", + __func__); + + if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: No-advertise,So Flush the Aggregate route(%pI4/%d)", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_external_lsa_flush(ospf, 0, &aggr->p, 0); + + UNSET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + } + return; + } + + if (!CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Now it is advatisable", __func__); + + lsa = ospf_external_info_find_lsa(ospf, &ei_aggr->p); + if (lsa && IS_LSA_MAXAGE(lsa)) { + /* This is special case. + * If a summary route need to be originated but where + * summary route already exist in lsdb with maxage, then + * it need to be refreshed. + */ + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: It is already with Maxage, So refresh it (%pI4/%d)", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_external_lsa_refresh(ospf, lsa, ei_aggr, + LSA_REFRESH_FORCE, 1); + + SET_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_ORIGINATED); + + } else { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Originate Aggregate LSA (%pI4/%d)", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + + /* Originate summary LSA */ + lsa = ospf_external_lsa_originate(ospf, ei_aggr); + if (lsa) + SET_FLAG(aggr->flags, + OSPF_EXTERNAL_AGGRT_ORIGINATED); + } + } +} + +static void ospf_handle_external_aggr_update(struct ospf *ospf) +{ + struct route_node *rn = NULL; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Process modified aggregators.\n", __func__); + + for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) { + struct ospf_external_aggr_rt *aggr; + struct ospf_lsa *lsa = NULL; + struct as_external_lsa *asel = NULL; + struct external_info ei_aggr; + route_tag_t tag = 0; + + if (!rn->info) + continue; + + aggr = rn->info; + + if (aggr->action == OSPF_ROUTE_AGGR_DEL) { + aggr->action = OSPF_ROUTE_AGGR_NONE; + ospf_external_aggr_delete(ospf, rn); + + if (OSPF_EXTERNAL_RT_COUNT(aggr)) + hash_clean( + aggr->match_extnl_hash, + (void *)ospf_aggr_handle_external_info); + + hash_free(aggr->match_extnl_hash); + XFREE(MTYPE_OSPF_EXTERNAL_RT_AGGR, aggr); + + } else if (aggr->action == OSPF_ROUTE_AGGR_MODIFY) { + + aggr->action = OSPF_ROUTE_AGGR_NONE; + + /* Prepare the extrenal_info for aggregator */ + memset(&ei_aggr, 0, sizeof(struct external_info)); + ei_aggr.p = aggr->p; + ei_aggr.tag = aggr->tag; + ei_aggr.type = 0; + ei_aggr.instance = ospf->instance; + ei_aggr.route_map_set.metric = -1; + ei_aggr.route_map_set.metric_type = -1; + + /* Check if tag modified */ + if (CHECK_FLAG(aggr->flags, + OSPF_EXTERNAL_AGGRT_ORIGINATED)) { + lsa = ospf_external_info_find_lsa(ospf, + &ei_aggr.p); + if (!lsa) { + flog_warn(EC_OSPF_LSA_MISSING, + "%s: Could not refresh/originate %pI4/%d", + __func__, &aggr->p.prefix, + aggr->p.prefixlen); + continue; + } + + asel = (struct as_external_lsa *)lsa->data; + tag = (unsigned long)ntohl( + asel->e[0].route_tag); + + /* If tag modified , then re-originate the + * route with modified tag details. + */ + if (tag != ei_aggr.tag) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Route tag changed(old:%d new:%d,So refresh the summary route.(%pI4/%d)", + __func__, tag, + ei_aggr.tag, + &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_external_lsa_refresh( + ospf, lsa, &ei_aggr, + LSA_REFRESH_FORCE, 1); + } + } + + /* Advertise option modified ? + * If so, handled it here. + */ + ospf_aggr_handle_advertise_change(ospf, aggr, &ei_aggr); + } + } +} + +static int ospf_asbr_external_aggr_process(struct thread *thread) +{ + struct ospf *ospf = THREAD_ARG(thread); + int operation = 0; + + ospf->t_external_aggr = NULL; + operation = ospf->aggr_action; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: operation:%d\n", __func__, operation); + + switch (operation) { + case OSPF_ROUTE_AGGR_ADD: + ospf_handle_external_aggr_add(ospf); + break; + case OSPF_ROUTE_AGGR_DEL: + case OSPF_ROUTE_AGGR_MODIFY: + ospf_handle_external_aggr_update(ospf); + break; + default: + break; + } + + return OSPF_SUCCESS; +} +static void ospf_external_aggr_timer(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + enum ospf_aggr_action_t operation) +{ + aggr->action = operation; + + if (ospf->t_external_aggr) { + if (ospf->aggr_action == OSPF_ROUTE_AGGR_ADD) { + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Not required to retsart timer,set is already added.", + __func__); + return; + } + + if (operation == OSPF_ROUTE_AGGR_ADD) { + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s, Restarting Aggregator delay timer.", + __func__); + THREAD_OFF(ospf->t_external_aggr); + } + } + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug("%s: Start Aggregator delay timer %d(in seconds).", + __func__, ospf->aggr_delay_interval); + + ospf->aggr_action = operation; + thread_add_timer(master, ospf_asbr_external_aggr_process, ospf, + ospf->aggr_delay_interval, &ospf->t_external_aggr); +} diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 090579363..ea5860f9a 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -134,4 +134,23 @@ extern struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *, extern void ospf_asbr_external_aggregator_init(struct ospf *instance); extern void ospf_external_aggregator_free(struct ospf_external_aggr_rt *aggr); +extern struct ospf_external_aggr_rt * +ospf_external_aggr_match(struct ospf *ospf, struct prefix_ipv4 *p); + +extern void ospf_unlink_ei_from_aggr(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei); + +extern struct ospf_lsa * +ospf_originate_summary_lsa(struct ospf *ospf, + struct ospf_external_aggr_rt *aggr, + struct external_info *ei); +extern int ospf_external_aggregator_timer_set(struct ospf *ospf, + unsigned int interval); +extern void ospf_external_aggrigator_free(struct ospf_external_aggr_rt *aggr); + +extern struct ospf_external_aggr_rt * +ospf_extrenal_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p); + +void ospf_unset_all_aggr_flag(struct ospf *ospf); #endif /* _ZEBRA_OSPF_ASBR_H */ diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 0f43553c0..72939bfcc 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -225,7 +225,7 @@ static void ospf_process_self_originated_lsa(struct ospf *ospf, ei = ospf_external_info_check(ospf, new); if (ei) ospf_external_lsa_refresh(ospf, new, ei, - LSA_REFRESH_FORCE); + LSA_REFRESH_FORCE, false); else ospf_lsa_flush_as(ospf, new); break; diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 9ad7f2c4d..b77e894c1 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2191,8 +2191,9 @@ void ospf_external_lsa_refresh_default(struct ospf *ospf) if (ei && lsa) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", - (void *)lsa); - ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE); + (void *)lsa); + ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, + false); } else if (ei && !lsa) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( @@ -2230,7 +2231,8 @@ void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, ospf, &ei->p); if (lsa) ospf_external_lsa_refresh( - ospf, lsa, ei, force); + ospf, lsa, ei, force, + false); else ospf_external_lsa_originate( ospf, ei); @@ -2243,21 +2245,25 @@ void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, /* Refresh AS-external-LSA. */ struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa, - struct external_info *ei, int force) + struct external_info *ei, int force, + bool is_aggr) { struct ospf_lsa *new; - int changed; + int changed = 0; /* Check the AS-external-LSA should be originated. */ - if (!ospf_redistribute_check(ospf, ei, &changed)) { - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type%d:%pI4]: Could not be refreshed, redist check fail", - lsa->data->type, &lsa->data->id); - ospf_external_lsa_flush(ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - return NULL; - } + if (!is_aggr) + if (!ospf_redistribute_check(ospf, ei, &changed)) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s] Could not be refreshed, redist check fail", + lsa->data->type, + inet_ntoa(lsa->data->id)); + + ospf_external_lsa_flush(ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + return NULL; + } if (!changed && !force) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) @@ -3474,8 +3480,8 @@ struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) break; ei = ospf_external_info_check(ospf, lsa); if (ei) - new = ospf_external_lsa_refresh(ospf, lsa, ei, - LSA_REFRESH_FORCE); + new = ospf_external_lsa_refresh( + ospf, lsa, ei, LSA_REFRESH_FORCE, false); else ospf_lsa_flush_as(ospf, lsa); break; diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index e63af4b34..c5de28794 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -313,7 +313,8 @@ extern void ospf_external_lsa_refresh_type(struct ospf *, uint8_t, unsigned short, int); extern struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *, struct ospf_lsa *, - struct external_info *, int); + struct external_info *, int, + bool aggr); extern struct in_addr ospf_lsa_unique_id(struct ospf *, struct ospf_lsdb *, uint8_t, struct prefix_ipv4 *); extern void ospf_schedule_lsa_flood_area(struct ospf_area *, struct ospf_lsa *); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 477405e2a..0f5da5482 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -463,7 +463,7 @@ static int ospf_external_lsa_default_routemap_timer(struct thread *thread) if (ret && !lsa) ospf_external_lsa_originate(ospf, default_ei); else if (ret && lsa && IS_LSA_MAXAGE(lsa)) - ospf_external_lsa_refresh(ospf, lsa, default_ei, true); + ospf_external_lsa_refresh(ospf, lsa, default_ei, true, false); else if (!ret && lsa) ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0); @@ -973,7 +973,8 @@ static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf, if (lsa && IS_LSA_MAXAGE(lsa)) /* Refresh lsa.*/ - ospf_external_lsa_refresh(ospf, lsa, default_ei, true); + ospf_external_lsa_refresh(ospf, lsa, default_ei, true, + false); else /* If permit and default not advertised then advertise. */ @@ -1196,7 +1197,8 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) &p.prefix); ospf_external_lsa_refresh( ospf, current, ei, - LSA_REFRESH_FORCE); + LSA_REFRESH_FORCE, + false); } } } @@ -1338,7 +1340,7 @@ static int ospf_distribute_list_update_timer(struct thread *thread) force = LSA_REFRESH_FORCE; ospf_external_lsa_refresh( - ospf, lsa, ei, force); + ospf, lsa, ei, force, false); } else ospf_external_lsa_originate( ospf, ei); |