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>
This commit is contained in:
rgirada 2020-08-15 02:55:40 -07:00
parent ad7222b76c
commit 63f0e9415c
6 changed files with 736 additions and 26 deletions

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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 *);

View File

@ -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);