mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 13:27:53 +00:00
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:
parent
53e44d0594
commit
960417cf06
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user