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 <rgirada@vmware.com>
This commit is contained in:
rgirada 2020-09-05 08:15:51 -07:00
parent 53e44d0594
commit 960417cf06
3 changed files with 318 additions and 66 deletions

View File

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

View File

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

View File

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