Fixes for OSPF NSSA handling.
This commit is contained in:
parent
b1b1943360
commit
2918e61046
9 changed files with 170 additions and 45 deletions
|
@ -1655,10 +1655,12 @@ protocol ospf <name> {
|
||||||
tick <num>;
|
tick <num>;
|
||||||
ecmp <switch> [limit <num>];
|
ecmp <switch> [limit <num>];
|
||||||
area <id> {
|
area <id> {
|
||||||
stub <switch>;
|
stub;
|
||||||
nssa <switch>;
|
nssa;
|
||||||
summary <switch>;
|
summary <switch>;
|
||||||
stub cost <num>;
|
default nssa <switch>;
|
||||||
|
default cost <num>;
|
||||||
|
default cost2 <num>;
|
||||||
translator <switch>;
|
translator <switch>;
|
||||||
translator stability <num>;
|
translator stability <num>;
|
||||||
|
|
||||||
|
@ -1747,20 +1749,20 @@ protocol ospf <name> {
|
||||||
address, similarly to a router ID). The most important area is
|
address, similarly to a router ID). The most important area is
|
||||||
the backbone (ID 0) to which every other area must be connected.
|
the backbone (ID 0) to which every other area must be connected.
|
||||||
|
|
||||||
<tag>stub <M>switch</M></tag>
|
<tag>stub</tag>
|
||||||
This option configures the area to be a stub area. External
|
This option configures the area to be a stub area. External
|
||||||
routes are not flooded into stub areas. Also summary LSAs can be
|
routes are not flooded into stub areas. Also summary LSAs can be
|
||||||
limited in stub areas (see option <cf/summary/). Default
|
limited in stub areas (see option <cf/summary/).
|
||||||
value is no. (Area is not stub.)
|
By default, the area is not a stub area.
|
||||||
|
|
||||||
<tag>nssa <M>switch</M></tag>
|
<tag>nssa</tag>
|
||||||
This option configures the area to be a NSSA (Not-So-Stubby
|
This option configures the area to be a NSSA (Not-So-Stubby
|
||||||
Area). NSSA is a variant of a stub area which allows a
|
Area). NSSA is a variant of a stub area which allows a
|
||||||
limited way of external route propagation. Global external
|
limited way of external route propagation. Global external
|
||||||
routes are not propagated into a NSSA, but an external route
|
routes are not propagated into a NSSA, but an external route
|
||||||
can be imported into NSSA as a (area-wide) NSSA-LSA (and
|
can be imported into NSSA as a (area-wide) NSSA-LSA (and
|
||||||
possibly translated and/or aggregated on area boundary).
|
possibly translated and/or aggregated on area boundary).
|
||||||
Default value is no. (Area is not NSSA.)
|
By default, the area is not NSSA.
|
||||||
|
|
||||||
<tag>summary <M>switch</M></tag>
|
<tag>summary <M>switch</M></tag>
|
||||||
This option controls propagation of summary LSAs into stub or
|
This option controls propagation of summary LSAs into stub or
|
||||||
|
@ -1771,10 +1773,22 @@ protocol ospf <name> {
|
||||||
summary LSAs could lead to more efficient routing at the cost
|
summary LSAs could lead to more efficient routing at the cost
|
||||||
of larger link state database. Default value is no.
|
of larger link state database. Default value is no.
|
||||||
|
|
||||||
<tag>stub cost <M>num</M></tag>
|
<tag>default nssa <M>switch</M></tag>
|
||||||
|
When <cf/summary/ option is enabled, default summary route is
|
||||||
|
no longer propagated to the NSSA. In that case, this option
|
||||||
|
allows to originate default route as NSSA-LSA to the NSSA.
|
||||||
|
Default value is no.
|
||||||
|
|
||||||
|
<tag>default cost <M>num</M></tag>
|
||||||
This option controls the cost of a default route propagated to
|
This option controls the cost of a default route propagated to
|
||||||
stub and NSSA areas. Default value is 1000.
|
stub and NSSA areas. Default value is 1000.
|
||||||
|
|
||||||
|
<tag>default cost2 <M>num</M></tag>
|
||||||
|
When a default route is originated as NSSA-LSA, its cost
|
||||||
|
can use either type 1 or type 2 metric. This option allows
|
||||||
|
to specify the cost of a default route in type 2 metric.
|
||||||
|
By default, type 1 metric (option <cf/default cost/) is used.
|
||||||
|
|
||||||
<tag>translator <M>switch</M></tag>
|
<tag>translator <M>switch</M></tag>
|
||||||
This option controls translation of NSSA-LSAs into external
|
This option controls translation of NSSA-LSAs into external
|
||||||
LSAs. By default, one translator per NSSA is automatically
|
LSAs. By default, one translator per NSSA is automatically
|
||||||
|
|
|
@ -59,6 +59,15 @@ ospf_area_finish(void)
|
||||||
{
|
{
|
||||||
if ((this_area->areaid == 0) && (this_area->type != OPT_E))
|
if ((this_area->areaid == 0) && (this_area->type != OPT_E))
|
||||||
cf_error("Backbone area cannot be stub/NSSA");
|
cf_error("Backbone area cannot be stub/NSSA");
|
||||||
|
|
||||||
|
if (this_area->summary && (this_area->type == OPT_E))
|
||||||
|
cf_error("Only Stub/NSSA areas can use summary propagation");
|
||||||
|
|
||||||
|
if (this_area->default_nssa && ((this_area->type != OPT_N) || ! this_area->summary))
|
||||||
|
cf_error("Only NSSA areas with summary propagation can use NSSA default route");
|
||||||
|
|
||||||
|
if ((this_area->default_cost & LSA_EXT_EBIT) && ! this_area->default_nssa)
|
||||||
|
cf_error("Only NSSA default route can use type 2 metric");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -94,10 +103,17 @@ ospf_proto_finish(void)
|
||||||
cf_error( "Vlinks cannot be used on single area router");
|
cf_error( "Vlinks cannot be used on single area router");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
check_defcost(int cost)
|
||||||
|
{
|
||||||
|
if ((cost <= 0) || (cost >= LSINFINITY))
|
||||||
|
cf_error("Default cost must be in range 1-%d", LSINFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
|
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
|
||||||
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
|
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
|
||||||
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
||||||
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
||||||
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
|
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
|
||||||
|
@ -139,7 +155,7 @@ ospf_area_start: AREA idval {
|
||||||
this_area = cfg_allocz(sizeof(struct ospf_area_config));
|
this_area = cfg_allocz(sizeof(struct ospf_area_config));
|
||||||
add_tail(&OSPF_CFG->area_list, NODE this_area);
|
add_tail(&OSPF_CFG->area_list, NODE this_area);
|
||||||
this_area->areaid = $2;
|
this_area->areaid = $2;
|
||||||
this_area->stub_cost = DEFAULT_STUB_COST;
|
this_area->default_cost = DEFAULT_STUB_COST;
|
||||||
this_area->type = OPT_E;
|
this_area->type = OPT_E;
|
||||||
this_area->transint = DEFAULT_TRANSINT;
|
this_area->transint = DEFAULT_TRANSINT;
|
||||||
|
|
||||||
|
@ -159,10 +175,13 @@ ospf_area_opts:
|
||||||
;
|
;
|
||||||
|
|
||||||
ospf_area_item:
|
ospf_area_item:
|
||||||
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 */ }
|
||||||
| STUB bool { this_area->type = $2 ? 0 : OPT_E; /* We should remove the option */ }
|
|
||||||
| NSSA { this_area->type = OPT_N; }
|
| NSSA { this_area->type = OPT_N; }
|
||||||
| SUMMARY bool { this_area->summary = $2; }
|
| SUMMARY bool { this_area->summary = $2; }
|
||||||
|
| DEFAULT NSSA bool { this_area->default_nssa = $3; }
|
||||||
|
| DEFAULT COST expr { this_area->default_cost = $3; check_defcost($3); }
|
||||||
|
| DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; check_defcost($3); }
|
||||||
|
| STUB COST expr { this_area->default_cost = $3; check_defcost($3); }
|
||||||
| TRANSLATOR bool { this_area->translator = $2; }
|
| TRANSLATOR bool { this_area->translator = $2; }
|
||||||
| TRANSLATOR STABILITY expr { this_area->transint = $3; }
|
| TRANSLATOR STABILITY expr { this_area->transint = $3; }
|
||||||
| NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
|
| NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
|
||||||
|
|
|
@ -127,7 +127,7 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
|
||||||
case LSA_SCOPE_AS:
|
case LSA_SCOPE_AS:
|
||||||
if (ifa->type == OSPF_IT_VLINK)
|
if (ifa->type == OSPF_IT_VLINK)
|
||||||
return 0;
|
return 0;
|
||||||
if (ifa->oa->stub)
|
if (!oa_is_ext(ifa->oa))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,14 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
|
||||||
oa->options = OPT_R | ac->type | OPT_V6;
|
oa->options = OPT_R | ac->type | OPT_V6;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set E-bit for NSSA ABR routers. No need to explicitly call
|
||||||
|
* schedule_rt_lsa() for other areas, will be done anyway.
|
||||||
|
* We use cf->abr because po->areano is not yet complete.
|
||||||
|
*/
|
||||||
|
if (oa_is_nssa(oa) && ((struct ospf_config *) (p->cf))->abr)
|
||||||
|
po->ebit = 1;
|
||||||
|
|
||||||
if (reconf)
|
if (reconf)
|
||||||
ospf_ifaces_reconfigure(oa, ac);
|
ospf_ifaces_reconfigure(oa, ac);
|
||||||
}
|
}
|
||||||
|
@ -453,7 +461,7 @@ area_disp(struct ospf_area *oa)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_disp - invokes routing table calctulation, aging and also area_disp()
|
* ospf_disp - invokes routing table calculation, aging and also area_disp()
|
||||||
* @timer: timer usually called every @proto_ospf->tick second, @timer->data
|
* @timer: timer usually called every @proto_ospf->tick second, @timer->data
|
||||||
* point to @proto_ospf
|
* point to @proto_ospf
|
||||||
*/
|
*/
|
||||||
|
@ -572,6 +580,8 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
|
||||||
/* Old external route might blocked some NSSA translation */
|
/* Old external route might blocked some NSSA translation */
|
||||||
if (po->areano > 1)
|
if (po->areano > 1)
|
||||||
schedule_rtcalc(po);
|
schedule_rtcalc(po);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get route attributes */
|
/* Get route attributes */
|
||||||
|
@ -587,7 +597,7 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
|
||||||
(ospf_iface_find((struct proto_ospf *) p, new->attrs->iface) != NULL))
|
(ospf_iface_find((struct proto_ospf *) p, new->attrs->iface) != NULL))
|
||||||
gw = new->attrs->gw;
|
gw = new->attrs->gw;
|
||||||
|
|
||||||
originate_ext_lsa(oa, fn, EXT_EXPORT, metric, gw, tag);
|
originate_ext_lsa(oa, fn, EXT_EXPORT, metric, gw, tag, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -674,7 +684,15 @@ static void
|
||||||
ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||||
{
|
{
|
||||||
oa->ac = nac;
|
oa->ac = nac;
|
||||||
// FIXME NSSA check type
|
|
||||||
|
// FIXME better area type reconfiguration
|
||||||
|
#ifdef OSPFv2
|
||||||
|
oa->options = nac->type;
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
oa->options = OPT_R | nac->type | OPT_V6;
|
||||||
|
#endif
|
||||||
|
if (oa_is_nssa(oa) && (oa->po->areano > 1))
|
||||||
|
oa->po->ebit = 1;
|
||||||
|
|
||||||
ospf_ifaces_reconfigure(oa, nac);
|
ospf_ifaces_reconfigure(oa, nac);
|
||||||
|
|
||||||
|
|
|
@ -126,10 +126,11 @@ struct ospf_area_config
|
||||||
{
|
{
|
||||||
node n;
|
node n;
|
||||||
u32 areaid;
|
u32 areaid;
|
||||||
u32 stub_cost; /* Cost of default route for stub areas */
|
u32 default_cost; /* Cost of default route for stub areas */
|
||||||
u8 type; /* Area type (standard, stub, NSSA), represented
|
u8 type; /* Area type (standard, stub, NSSA), represented
|
||||||
by option flags (OPT_E, OPT_N) */
|
by option flags (OPT_E, OPT_N) */
|
||||||
u8 summary; /* Import summaries to this stub/NSSA area, valid for ABR */
|
u8 summary; /* Import summaries to this stub/NSSA area, valid for ABR */
|
||||||
|
u8 default_nssa; /* Generate default NSSA route for NSSA+summary area */
|
||||||
u8 translator; /* Translator role, for NSSA ABR */
|
u8 translator; /* Translator role, for NSSA ABR */
|
||||||
u32 transint; /* Translator stability interval */
|
u32 transint; /* Translator stability interval */
|
||||||
list patt_list;
|
list patt_list;
|
||||||
|
|
|
@ -1059,11 +1059,11 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf)
|
||||||
|
|
||||||
/* RFC 3103 3.2 (3) - originate the aggregated address range */
|
/* RFC 3103 3.2 (3) - originate the aggregated address range */
|
||||||
if (anet && anet->active && !anet->hidden && oa->translate)
|
if (anet && anet->active && !anet->hidden && oa->translate)
|
||||||
originate_ext_lsa(po->backbone, fn, EXT_NSSA, anet->metric, IPA_NONE, anet->tag);
|
originate_ext_lsa(po->backbone, fn, EXT_NSSA, anet->metric, IPA_NONE, anet->tag, 0);
|
||||||
|
|
||||||
/* RFC 3103 3.2 (2) - originate the same network */
|
/* RFC 3103 3.2 (2) - originate the same network */
|
||||||
else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag))
|
else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag))
|
||||||
originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag);
|
originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
|
||||||
|
|
||||||
else if (fn->x1 == EXT_NSSA)
|
else if (fn->x1 == EXT_NSSA)
|
||||||
flush_ext_lsa(po->backbone, fn);
|
flush_ext_lsa(po->backbone, fn);
|
||||||
|
@ -1173,11 +1173,24 @@ ospf_rt_abr1(struct proto_ospf *po)
|
||||||
|
|
||||||
/* 12.4.3.1. - originate or flush default route for stub/NSSA areas */
|
/* 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))
|
if (oa_is_stub(oa) || (oa_is_nssa(oa) && !oa->ac->summary))
|
||||||
originate_sum_net_lsa(oa, &default_nf->fn, oa->ac->stub_cost);
|
originate_sum_net_lsa(oa, &default_nf->fn, oa->ac->default_cost);
|
||||||
else
|
else
|
||||||
flush_sum_lsa(oa, &default_nf->fn, ORT_NET);
|
flush_sum_lsa(oa, &default_nf->fn, ORT_NET);
|
||||||
|
|
||||||
// FIXME NSSA add support for type 7 default route ?
|
/*
|
||||||
|
* Originate type-7 default route for NSSA areas
|
||||||
|
*
|
||||||
|
* Because type-7 default LSAs are originated by ABRs, they do not
|
||||||
|
* collide with other type-7 LSAs (as ABRs generate type-5 LSAs
|
||||||
|
* for both external route export or external-NSSA translation),
|
||||||
|
* so we use 0 for the src arg.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (oa_is_nssa(oa) && oa->ac->default_nssa)
|
||||||
|
originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0);
|
||||||
|
else
|
||||||
|
flush_ext_lsa(oa, &default_nf->fn);
|
||||||
|
|
||||||
|
|
||||||
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
|
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
|
||||||
if (oa_is_ext(oa))
|
if (oa_is_ext(oa))
|
||||||
|
@ -1256,7 +1269,6 @@ ospf_rt_abr2(struct proto_ospf *po)
|
||||||
{
|
{
|
||||||
translate = 0;
|
translate = 0;
|
||||||
goto decided;
|
goto decided;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
|
@ -1286,7 +1298,7 @@ ospf_rt_abr2(struct proto_ospf *po)
|
||||||
FIB_WALK(&po->rtf, nftmp)
|
FIB_WALK(&po->rtf, nftmp)
|
||||||
{
|
{
|
||||||
nf = (ort *) nftmp;
|
nf = (ort *) nftmp;
|
||||||
if (rt_is_nssa(nf))
|
if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP))
|
||||||
{
|
{
|
||||||
struct area_net *anet = (struct area_net *)
|
struct area_net *anet = (struct area_net *)
|
||||||
fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen);
|
fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen);
|
||||||
|
@ -1503,9 +1515,11 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
/* Whether the route is preferred in route selection according to 16.4.1 */
|
/* Whether the route is preferred in route selection according to 16.4.1 */
|
||||||
nfa.options = epath_preferred(&nf2->n) ? ORTA_PREF : 0;
|
nfa.options = epath_preferred(&nf2->n) ? ORTA_PREF : 0;
|
||||||
if (en->lsa.type == LSA_T_NSSA)
|
if (en->lsa.type == LSA_T_NSSA)
|
||||||
|
{
|
||||||
nfa.options |= ORTA_NSSA;
|
nfa.options |= ORTA_NSSA;
|
||||||
if (rt_propagate)
|
if (rt_propagate)
|
||||||
nfa.options |= ORTA_PROP;
|
nfa.options |= ORTA_PROP;
|
||||||
|
}
|
||||||
|
|
||||||
nfa.tag = rt_tag;
|
nfa.tag = rt_tag;
|
||||||
nfa.rid = en->lsa.rt;
|
nfa.rid = en->lsa.rt;
|
||||||
|
|
|
@ -76,7 +76,6 @@ ort;
|
||||||
static inline int rt_is_nssa(ort *nf)
|
static inline int rt_is_nssa(ort *nf)
|
||||||
{ return nf->n.options & ORTA_NSSA; }
|
{ return nf->n.options & ORTA_NSSA; }
|
||||||
|
|
||||||
|
|
||||||
#define EXT_EXPORT 1
|
#define EXT_EXPORT 1
|
||||||
#define EXT_NSSA 2
|
#define EXT_NSSA 2
|
||||||
|
|
||||||
|
|
|
@ -885,7 +885,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
|
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
|
||||||
u32 metric, ip_addr fwaddr, u32 tag)
|
u32 metric, ip_addr fwaddr, u32 tag, int pbit UNUSED)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext));
|
struct ospf_lsa_ext *ext = mb_alloc(po->proto.pool, sizeof(struct ospf_lsa_ext));
|
||||||
*length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext);
|
*length = sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsa_ext);
|
||||||
|
@ -929,10 +929,10 @@ check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_add
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
|
originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
|
||||||
u32 metric, ip_addr fwaddr, u32 tag)
|
u32 metric, ip_addr fwaddr, u32 tag, int pbit)
|
||||||
{
|
{
|
||||||
int size = sizeof(struct ospf_lsa_ext)
|
int size = sizeof(struct ospf_lsa_ext)
|
||||||
+ IPV6_PREFIX_SPACE(n->n.pxlen)
|
+ IPV6_PREFIX_SPACE(fn->pxlen)
|
||||||
+ (ipa_nonzero(fwaddr) ? 16 : 0)
|
+ (ipa_nonzero(fwaddr) ? 16 : 0)
|
||||||
+ (tag ? 4 : 0);
|
+ (tag ? 4 : 0);
|
||||||
|
|
||||||
|
@ -942,7 +942,7 @@ originate_ext_lsa_body(struct proto_ospf *po, u16 *length, struct fib_node *fn,
|
||||||
ext->metric = metric;
|
ext->metric = metric;
|
||||||
|
|
||||||
u32 *buf = ext->rest;
|
u32 *buf = ext->rest;
|
||||||
buf = put_ipv6_prefix(buf, fn->prefix, fn->pxlen, 0, 0);
|
buf = put_ipv6_prefix(buf, fn->prefix, fn->pxlen, pbit ? OPT_PX_P : 0, 0);
|
||||||
|
|
||||||
if (ipa_nonzero(fwaddr))
|
if (ipa_nonzero(fwaddr))
|
||||||
{
|
{
|
||||||
|
@ -993,25 +993,77 @@ check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_add
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline ip_addr
|
||||||
|
find_surrogate_fwaddr(struct ospf_area *oa)
|
||||||
|
{
|
||||||
|
struct proto_ospf *po = oa->po;
|
||||||
|
struct ospf_iface *ifa;
|
||||||
|
struct ifa *a, *cur_addr = NULL;
|
||||||
|
int np, cur_np = 0;
|
||||||
|
|
||||||
|
WALK_LIST(ifa, po->iface_list)
|
||||||
|
{
|
||||||
|
if ((ifa->oa != oa) ||
|
||||||
|
(ifa->state == OSPF_IS_DOWN) ||
|
||||||
|
(ifa->type == OSPF_IT_VLINK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
a = ifa->addr;
|
||||||
|
if (a->flags & IA_PEER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
|
||||||
|
if (np > cur_np)
|
||||||
|
{
|
||||||
|
cur_addr = a;
|
||||||
|
cur_np = np;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* OSPFv3 */
|
||||||
|
WALK_LIST(a, ifa->iface->addrs)
|
||||||
|
{
|
||||||
|
if ((a->flags & IA_SECONDARY) ||
|
||||||
|
(a->flags & IA_PEER) ||
|
||||||
|
(a->scope <= SCOPE_LINK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
|
||||||
|
if (np > cur_np)
|
||||||
|
{
|
||||||
|
cur_addr = a;
|
||||||
|
cur_np = np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_addr ? cur_addr->ip : IPA_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* originate_ext_lsa - new route received from nest and filters
|
* originate_ext_lsa - new route received from nest and filters
|
||||||
* @oa: ospf_area for which LSA is originated
|
* @oa: ospf_area for which LSA is originated
|
||||||
* @fn: network prefix and mask
|
* @fn: network prefix and mask
|
||||||
* @type: the reason for origination of the LSA (EXT_EXPORT/EXT_NSSA)
|
* @src: the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
|
||||||
* @metric: the metric of a route
|
* @metric: the metric of a route
|
||||||
* @fwaddr: the forwarding address
|
* @fwaddr: the forwarding address
|
||||||
* @tag: the route tag
|
* @tag: the route tag
|
||||||
|
* @pbit: P-bit for NSSA LSAs, ignored for external LSAs
|
||||||
*
|
*
|
||||||
* If I receive a message that new route is installed, I try to originate an
|
* If I receive a message that new route is installed, I try to originate an
|
||||||
* external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
|
* external LSA. If @oa is an NSSA area, NSSA-LSA is originated instead.
|
||||||
* @oa should not be a stub area.
|
* @oa should not be a stub area. @src does not specify whether the LSA
|
||||||
|
* is external or NSSA, but it specifies the source of origination -
|
||||||
|
* the export from ospf_rt_notify(), or the NSSA-EXT translation.
|
||||||
*
|
*
|
||||||
* The function also sets flag ebit. If it's the first time, the new router lsa
|
* The function also sets flag ebit. If it's the first time, the new router lsa
|
||||||
* origination is necessary.
|
* origination is necessary.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int type,
|
originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
|
||||||
u32 metric, ip_addr fwaddr, u32 tag)
|
u32 metric, ip_addr fwaddr, u32 tag, int pbit)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
|
@ -1021,22 +1073,28 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int type,
|
||||||
int nssa = oa_is_nssa(oa);
|
int nssa = oa_is_nssa(oa);
|
||||||
u32 dom = nssa ? oa->areaid : 0;
|
u32 dom = nssa ? oa->areaid : 0;
|
||||||
|
|
||||||
// FIXME NSSA - handle P bit, currently always set (from oa->options)
|
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
|
OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
|
||||||
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
|
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
lsa.options = oa->options;
|
lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E;
|
||||||
#endif
|
#endif
|
||||||
lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
|
lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT;
|
||||||
lsa.id = fibnode_to_lsaid(po, fn);
|
lsa.id = fibnode_to_lsaid(po, fn);
|
||||||
lsa.rt = po->router_id;
|
lsa.rt = po->router_id;
|
||||||
|
|
||||||
if (nssa)
|
if (nssa && pbit && ipa_zero(fwaddr))
|
||||||
{
|
{
|
||||||
// FIXME NSSA Add check for gw, update option
|
/* NSSA-LSA with P-bit set must have non-zero forwarding address */
|
||||||
|
|
||||||
|
fwaddr = find_surrogate_fwaddr(oa);
|
||||||
|
if (ipa_zero(fwaddr))
|
||||||
|
{
|
||||||
|
log(L_ERR, "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
|
||||||
|
p->name, fn->prefix, fn->pxlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
|
if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL)
|
||||||
|
@ -1054,10 +1112,12 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int type,
|
||||||
}
|
}
|
||||||
lsa.sn = get_seqnum(en);
|
lsa.sn = get_seqnum(en);
|
||||||
|
|
||||||
body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag);
|
body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
|
||||||
lsasum_calculate(&lsa, body);
|
lsasum_calculate(&lsa, body);
|
||||||
|
|
||||||
fn->x1 = type;
|
if (src)
|
||||||
|
fn->x1 = src;
|
||||||
|
|
||||||
en = lsa_install_new(po, &lsa, dom, body);
|
en = lsa_install_new(po, &lsa, dom, body);
|
||||||
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
||||||
|
|
||||||
|
@ -1325,7 +1385,7 @@ prefix_advance(u32 *buf)
|
||||||
return buf + IPV6_PREFIX_WORDS(pxl);
|
return buf + IPV6_PREFIX_WORDS(pxl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME eliminate items wit LA bit set? see 4.4.3.9 */
|
/* FIXME eliminate items with LA bit set? see 4.4.3.9 */
|
||||||
static void
|
static void
|
||||||
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
|
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,7 +71,7 @@ int can_flush_lsa(struct proto_ospf *po);
|
||||||
void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric);
|
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 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 flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
||||||
void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int type, u32 metric, ip_addr fwaddr, u32 tag);
|
void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
|
||||||
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn);
|
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue