OSPF NSSA support, part one.

This commit is contained in:
Ondrej Zajicek 2011-07-20 23:40:20 +02:00
parent 9008579b97
commit 41b612c31b
9 changed files with 147 additions and 73 deletions

View file

@ -56,8 +56,8 @@ ospf_iface_finish(void)
static void
ospf_area_finish(void)
{
if ((this_area->areaid == 0) && (this_area->stub != 0))
cf_error( "Backbone area cannot be stub");
if ((this_area->areaid == 0) && (this_area->type != OPT_E))
cf_error( "Backbone area cannot be stub/NSSA");
}
static void
@ -89,7 +89,7 @@ ospf_proto_finish(void)
}
if (!cf->abr && !EMPTY_LIST(cf->vlink_list))
cf_error( "No configured areas in OSPF");
cf_error( "Vlinks cannot be used on single area router");
}
CF_DECLS
@ -101,7 +101,7 @@ CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA)
%type <t> opttext
@ -137,7 +137,9 @@ ospf_area_start: AREA idval {
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
this_area->stub = 0;
this_area->stub_cost = DEFAULT_STUB_COST;
this_area->type = OPT_E;
init_list(&this_area->patt_list);
init_list(&this_area->net_list);
init_list(&this_area->stubnet_list);
@ -153,8 +155,10 @@ ospf_area_opts:
;
ospf_area_item:
STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); }
| STUB bool {if($2) { if(!this_area->stub) this_area->stub=DEFAULT_STUB_COST;}else{ this_area->stub=0;}}
STUB COST expr { this_area->stub_cost = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); }
| STUB bool { this_area->type = $2 ? 0 : OPT_E; /* We should remove the option */ }
| NSSA { this_area->type = OPT_N; }
| SUMMARY bool { this_area->summary = $2; }
| NETWORKS '{' pref_list '}'
| STUBNET ospf_stubnet
| INTERFACE ospf_iface

View file

@ -94,10 +94,10 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
return;
}
tmp = !(ps->options & OPT_E);
if (tmp != !!ifa->oa->stub)
/* Check whether bits E, N match */
if ((ps->options ^ ifa->oa->options) & (OPT_E | OPT_N))
{
log(L_ERR "%s%I - stub area flag mismatch (%d)", beg, faddr, tmp);
log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, ps->options);
return;
}

View file

@ -490,6 +490,7 @@ lsa_validate(struct ospf_lsa_header *lsa, void *body)
case LSA_T_SUM_RT:
return lsa_validate_sum_rt(lsa, body);
case LSA_T_EXT:
case LSA_T_NSSA:
return lsa_validate_ext(lsa, body);
#ifdef OSPFv3
case LSA_T_LINK:

View file

@ -77,7 +77,7 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
{
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (ifa->oa->stub)
if (!oa_is_ext(ifa->oa))
return 0;
return 1;
}
@ -97,6 +97,7 @@ unknown_lsa_type(struct ospf_lsa_header *lsa)
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
case LSA_T_NSSA:
case LSA_T_LINK:
case LSA_T_PREFIX:
return 0;
@ -486,21 +487,21 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
#ifdef OSPFv2
/* pg 143 (2) */
if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
{
log(L_WARN "Unknown LSA type from %I", n->ip);
continue;
}
/* pg 143 (3) */
if ((lsa->type == LSA_T_EXT) && ifa->oa->stub)
if ((lsa->type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received External LSA in stub area from %I", n->ip);
continue;
}
#else /* OSPFv3 */
/* 4.5.1 (2) */
if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && ifa->oa->stub)
if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
continue;

View file

@ -147,7 +147,6 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
po->areano++;
oa->ac = ac;
oa->stub = ac->stub;
oa->areaid = ac->areaid;
oa->rt = NULL;
oa->po = po;
@ -158,9 +157,9 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
po->backbone = oa;
#ifdef OSPFv2
oa->options = (oa->stub ? 0 : OPT_E);
oa->options = ac->type;
#else /* OSPFv3 */
oa->options = OPT_R | (oa->stub ? 0 : OPT_E) | OPT_V6;
oa->options = OPT_R | ac->type | OPT_V6;
#endif
if (reconf)
@ -480,11 +479,15 @@ int
ospf_import_control(struct proto *p, rte ** new, ea_list ** attrs,
struct linpool *pool)
{
struct ospf_area *oa = ospf_main_area((struct proto_ospf *) p);
rte *e = *new;
if (p == e->attrs->proto)
return -1; /* Reject our own routes */
if (oa_is_stub(oa))
return -1; /* Do not export routes to stub areas */
eattr *ea = ea_find(e->attrs->eattrs, EA_GEN_IGP_METRIC);
u32 m1 = (ea && (ea->u.data < LSINFINITY)) ? ea->u.data : LSINFINITY;
@ -543,6 +546,7 @@ static void
ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs)
{
struct proto_ospf *po = (struct proto_ospf *) p;
struct ospf_area *oa = ospf_main_area(po);
/* Temporarily down write anything
OSPF_TRACE(D_EVENTS, "Got route %I/%d %s", p->name, n->n.prefix,
@ -550,9 +554,9 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
*/
if (new) /* Got some new route */
originate_ext_lsa(n, new, po, attrs);
originate_ext_lsa(oa, n, new, attrs);
else
flush_ext_lsa(n, po);
flush_ext_lsa(oa, n);
}
static void
@ -605,7 +609,7 @@ ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
if (rte->attrs->source == RTS_OSPF_EXT2)
buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
buf += bsprintf(buf, ")");
if ((rte->attrs->source == RTS_OSPF_EXT2 || rte->attrs->source == RTS_OSPF_EXT1) && rte->u.ospf.tag)
if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag)
{
buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
}
@ -639,7 +643,7 @@ static void
ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
{
oa->ac = nac;
oa->stub = nac->stub;
// FIXME NSSA check type
ospf_ifaces_reconfigure(oa, nac);
@ -797,7 +801,8 @@ ospf_sh(struct proto *p)
}
}
}
cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
// FIXME NSSA:
// cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
@ -1096,7 +1101,8 @@ show_lsa_external(struct top_hash_entry *he)
int pxlen, ebit, rt_fwaddr_valid;
u32 rt_tag, rt_metric;
he->domain = 0; /* Unmark the LSA */
if (he->lsa.type == LSA_T_EXT)
he->domain = 0; /* Unmark the LSA */
rt_metric = ext->metric & METRIC_MASK;
ebit = ext->metric & LSA_EXT_EBIT;
@ -1130,8 +1136,9 @@ show_lsa_external(struct top_hash_entry *he)
if (rt_tag)
bsprintf(str_tag, " tag %08x", rt_tag);
cli_msg(-1016, "\t\texternal %I/%d metric%s %u%s%s", ip, pxlen,
ebit ? "2" : "", rt_metric, str_via, str_tag);
cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s",
(he->lsa.type == LSA_T_NSSA) ? "nssa-ext" : "external",
ip, pxlen, ebit ? "2" : "", rt_metric, str_via, str_tag);
}
#ifdef OSPFv3
@ -1206,6 +1213,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_NSSA:
#ifdef OSPFv3
case LSA_T_PREFIX:
#endif
@ -1307,6 +1315,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
#endif
case LSA_T_EXT:
case LSA_T_NSSA:
show_lsa_external(he);
break;
}

View file

@ -123,7 +123,10 @@ struct ospf_area_config
{
node n;
u32 areaid;
u32 stub;
u32 stub_cost; /* Cost of default route for stub areas */
u8 type; /* Area type (standard, stub, NSSA), represented
by option flags (OPT_E, OPT_N) */
u8 summary; /* Import summaries to this stub/NSSA area, valid for ABR */
list patt_list;
list net_list; /* List of aggregate networks for that area */
list stubnet_list; /* List of stub networks added to Router LSA */
@ -137,12 +140,14 @@ struct ospf_area_config
#define OPT_DC 0x20
#ifdef OSPFv2
#define OPT_P 0x08 /* flags P and N share position, see NSSA RFC */
#define OPT_EA 0x10
/* VEB flags are are stored independently in 'u16 options' */
#define OPT_RT_B (0x01 << 8)
#define OPT_RT_E (0x02 << 8)
#define OPT_RT_V (0x04 << 8)
#define OPT_RT_NT (0x10 << 8)
#endif
#ifdef OSPFv3
@ -363,6 +368,7 @@ struct ospf_lsa_header
#define LSA_T_SUM_NET 3
#define LSA_T_SUM_RT 4
#define LSA_T_EXT 5
#define LSA_T_NSSA 7
#define LSA_SCOPE_AREA 0x2000
#define LSA_SCOPE_AS 0x4000
@ -377,6 +383,7 @@ struct ospf_lsa_header
#define LSA_T_SUM_NET 0x2003
#define LSA_T_SUM_RT 0x2004
#define LSA_T_EXT 0x4005
#define LSA_T_NSSA 0x2007
#define LSA_T_LINK 0x0008
#define LSA_T_PREFIX 0x2009
@ -720,12 +727,11 @@ struct ospf_area
{
node n;
u32 areaid;
struct ospf_area_config *ac; /* Related area config, might be NULL */
struct ospf_area_config *ac; /* Related area config */
struct top_hash_entry *rt; /* My own router LSA */
struct top_hash_entry *pxr_lsa; /* Originated prefix LSA */
list cand; /* List of candidates for RT calc. */
struct fib net_fib; /* Networks to advertise or not */
u32 stub; /* 0 or stub area cost */
u32 options; /* Optional features */
byte origrt; /* Rt lsa origination scheduled? */
byte trcap; /* Transit capability? */
@ -796,7 +802,6 @@ struct ospf_iface_patt
#endif
};
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
struct linpool *pool);
struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
@ -806,6 +811,16 @@ void schedule_rtcalc(struct proto_ospf *po);
void schedule_net_lsa(struct ospf_iface *ifa);
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
{ return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
static inline int oa_is_stub(struct ospf_area *oa)
{ return (oa->options & (OPT_E | OPT_N)) == 0; }
static inline int oa_is_ext(struct ospf_area *oa)
{ return oa->options & OPT_E; }
static inline int oa_is_nssa(struct ospf_area *oa)
{ return oa->options & OPT_N; }
#ifdef OSPFv3
void schedule_link_lsa(struct ospf_iface *ifa);

View file

@ -172,6 +172,8 @@ ri_better_ext(struct proto_ospf *po, orta *new, orta *old)
if (new->metric1 > old->metric1)
return 0;
/* RFC 3103, 2.5. (6e) - missing, is this necessary? */
return 0;
}
@ -826,7 +828,8 @@ ospf_rt_sum_tr(struct ospf_area *oa)
static int
decide_anet_lsa(struct ospf_area *oa, struct area_net *anet, struct ospf_area *anet_oa)
{
if (oa->stub)
/* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
if (!oa_is_ext(oa) && !oa->ac->summary)
return 0;
if (oa == anet_oa)
@ -843,8 +846,8 @@ decide_anet_lsa(struct ospf_area *oa, struct area_net *anet, struct ospf_area *a
static int
decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
{
/* 12.4.3.1. - do not send summary into stub areas, we send just default route */
if (oa->stub)
/* 12.4.3.1. - for stub/NSSA areas, originating summary routes is configurable */
if (!oa_is_ext(oa) && !oa->ac->summary)
return 0;
/* Invalid field - no route */
@ -872,7 +875,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
{
/* We call decide_sum_lsa() on preferred ASBR entries, no need for 16.4. (3) */
/* 12.4.3 p1 */
return (nf->n.options & ORTA_ASBR);
return oa_is_ext(oa) && (nf->n.options & ORTA_ASBR);
}
/* 12.4.3 p7 - inter-area route */
@ -1048,21 +1051,25 @@ ospf_rt_abr(struct proto_ospf *po)
WALK_LIST(oa, po->area_list)
{
/* 12.4.3.1. - originate or flush default summary LSA for stub areas */
if (oa->stub)
originate_sum_net_lsa(oa, &default_nf->fn, oa->stub);
/* 12.4.3.1. - originate or flush default route for stub/NSSA areas */
if (oa_is_stub(oa) || (oa_is_nssa(oa) && !oa->ac->summary))
originate_sum_net_lsa(oa, &default_nf->fn, oa->ac->stub_cost);
else
flush_sum_lsa(oa, &default_nf->fn, ORT_NET);
// FIXME NSSA add support for type 7 default route ?
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
FIB_WALK(&oa->rtr, nftmp)
if (oa_is_ext(oa))
{
nf = (ort *) nftmp;
if (nf->n.options & ORTA_ASBR)
ri_install_asbr(po, &nf->fn.prefix, &nf->n);
FIB_WALK(&oa->rtr, nftmp)
{
nf = (ort *) nftmp;
if (nf->n.options & ORTA_ASBR)
ri_install_asbr(po, &nf->fn.prefix, &nf->n);
}
FIB_WALK_END;
}
FIB_WALK_END;
}
@ -1105,7 +1112,7 @@ ospf_ext_spf(struct proto_ospf *po)
struct top_hash_entry *en;
struct proto *p = &po->proto;
struct ospf_lsa_ext *le;
int pxlen, ebit, rt_fwaddr_valid;
int pxlen, ebit, rt_fwaddr_valid, rt_propagate;
ip_addr ip, rtid, rt_fwaddr;
u32 br_metric, rt_metric, rt_tag;
struct ospf_area *atmp;
@ -1116,7 +1123,7 @@ ospf_ext_spf(struct proto_ospf *po)
WALK_SLIST(en, po->lsal)
{
/* 16.4. (1) */
if (en->lsa.type != LSA_T_EXT)
if ((en->lsa.type != LSA_T_EXT) && (en->lsa.type != LSA_T_NSSA))
continue;
if (en->lsa.age == LSA_MAXAGE)
@ -1143,6 +1150,7 @@ ospf_ext_spf(struct proto_ospf *po)
rt_fwaddr = le->fwaddr;
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
rt_tag = le->tag;
rt_propagate = en->lsa.options & OPT_P;
#else /* OSPFv3 */
u8 pxopts;
u16 rest;
@ -1162,6 +1170,8 @@ ospf_ext_spf(struct proto_ospf *po)
rt_tag = *buf++;
else
rt_tag = 0;
rt_propagate = pxopts & OPT_PX_P;
#endif
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
@ -1171,10 +1181,19 @@ ospf_ext_spf(struct proto_ospf *po)
continue;
}
/* 16.4. (3) */
/* If there are more areas, we already precomputed preferred ASBR entries
in ospf_asbr_spf() and stored them in the backbone table */
atmp = (po->areano > 1) ? po->backbone : HEAD(po->area_list);
/* If there are more areas, we already precomputed preferred ASBR
entries in ospf_rt_abr() and stored them in the backbone
table. For NSSA, we examine the area to which the LSA is assigned */
if (en->lsa.type == LSA_T_EXT)
atmp = ospf_main_area(po);
else /* NSSA */
atmp = ospf_find_area(po, en->domain);
if (!atmp)
continue; /* Should not happen */
rtid = ipa_from_rid(en->lsa.rt);
nf1 = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH);
@ -1184,6 +1203,12 @@ ospf_ext_spf(struct proto_ospf *po)
if (!(nf1->n.options & ORTA_ASBR))
continue; /* It is not ASBR */
/* 16.4. (3) NSSA - special rule for default routes */
/* ABR should use default only if P-bit is set and summaries are active */
if ((en->lsa.type == LSA_T_NSSA) && ipa_zero(ip) && (pxlen == 0) &&
(po->areano > 1) && !(rt_propagate && atmp->ac->summary))
continue;
if (!rt_fwaddr_valid)
{
nf2 = nf1;
@ -1196,8 +1221,18 @@ ospf_ext_spf(struct proto_ospf *po)
if (!nf2)
continue;
if ((nf2->n.type != RTS_OSPF) && (nf2->n.type != RTS_OSPF_IA))
continue;
if (en->lsa.type == LSA_T_EXT)
{
/* For ext routes, we accept intra-area or inter-area routes */
if ((nf2->n.type != RTS_OSPF) && (nf2->n.type != RTS_OSPF_IA))
continue;
}
else /* NSSA */
{
/* For NSSA routes, we accept just intra-area in the same area */
if ((nf2->n.type != RTS_OSPF) || (nf2->n.oa != atmp))
continue;
}
/* Next-hop is a part of a configured stubnet */
if (!nf2->n.nhs)
@ -1317,10 +1352,7 @@ ospf_rt_spf(struct proto_ospf *po)
ospf_rt_spfa(oa);
/* 16. (3) */
if (po->areano == 1)
ospf_rt_sum(HEAD(po->area_list));
else
ospf_rt_sum(po->backbone);
ospf_rt_sum(ospf_main_area(po));
/* 16. (4) */
WALK_LIST(oa, po->area_list)

View file

@ -222,7 +222,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if (po->areano > 1)
rt->options |= OPT_RT_B;
if ((po->ebit) && (!oa->stub))
if (po->ebit && !oa_is_stub(oa))
rt->options |= OPT_RT_E;
rt = NULL; /* buffer might be reallocated later */
@ -388,7 +388,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if (po->areano > 1)
rt->options |= OPT_RT_B;
if ((po->ebit) && (!oa->stub))
if (po->ebit && !oa_is_stub(oa))
rt->options |= OPT_RT_E;
rt = NULL; /* buffer might be reallocated later */
@ -989,36 +989,40 @@ check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_add
/**
* originate_ext_lsa - new route received from nest and filters
* @oa: ospf_area for which LSA is originated
* @n: network prefix and mask
* @e: rte
* @po: current instance of OSPF
* @attrs: list of extended attributes
*
* If I receive a message that new route is installed, I try to originate an
* external LSA.
* external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
* @oa should not be stub area.
*
* The function also sets flag ebit. If it's the first time, the new router lsa
* origination is necessary.
*/
void
originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs)
originate_ext_lsa(struct ospf_area *oa, net *n, rte *e, struct ea_list *attrs)
{
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct fib_node *fn = &n->n;
struct ospf_lsa_header lsa;
struct top_hash_entry *en = NULL;
void *body;
struct ospf_area *oa;
int nssa = oa_is_nssa(oa);
u32 dom = nssa ? oa->areaid : 0;
OSPF_TRACE(D_EVENTS, "Originating AS-external-LSA for %I/%d",
fn->prefix, fn->pxlen);
// FIXME NSSA - handle P bit
OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
lsa.age = 0;
#ifdef OSPFv2
lsa.options = 0; /* or oa->options ? */
lsa.options = oa->options;
#endif
lsa.type = LSA_T_EXT;
lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
lsa.id = fibnode_to_lsaid(po, fn);
lsa.rt = po->router_id;
@ -1035,7 +1039,12 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
(ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL))
gw = e->attrs->gw;
if ((en = ospf_hash_find_header(po->gr, 0, &lsa)) != NULL)
if (nssa)
{
// FIXME NSSA Add check for gw, update option
}
if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
{
int rv = check_ext_lsa(en, fn, metric, gw, tag);
if (rv < 0)
@ -1053,8 +1062,8 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
body = originate_ext_lsa_body(po, &lsa.length, n, metric, gw, tag);
lsasum_calculate(&lsa, body);
en = lsa_install_new(po, &lsa, 0, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, 0, 1);
en = lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
if (po->ebit == 0)
{
@ -1067,18 +1076,22 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
}
void
flush_ext_lsa(net *n, struct proto_ospf *po)
flush_ext_lsa(struct ospf_area *oa, net *n)
{
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
struct fib_node *fn = &n->n;
struct top_hash_entry *en;
int nssa = oa_is_nssa(oa);
OSPF_TRACE(D_EVENTS, "Flushing AS-external-LSA for %I/%d",
fn->prefix, fn->pxlen);
OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
u32 dom = nssa ? oa->areaid : 0;
u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
u32 lsaid = fibnode_to_lsaid(po, fn);
if (en = ospf_hash_find(po->gr, 0, lsaid, po->router_id, LSA_T_EXT))
if (en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type))
{
if (check_ext_lsa(en, fn, 0, IPA_NONE, 0) < 0)
{

View file

@ -72,9 +72,8 @@ void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric
void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
struct ea_list *attrs);
void flush_ext_lsa(net *n, struct proto_ospf *po);
void originate_ext_lsa(struct ospf_area *oa, net *n, rte *e, struct ea_list *attrs);
void flush_ext_lsa(struct ospf_area *oa, net *n);
#ifdef OSPFv2