Fixes for OSPF NSSA handling.

This commit is contained in:
Ondrej Zajicek 2011-09-03 21:31:26 +02:00
parent b1b1943360
commit 2918e61046
9 changed files with 170 additions and 45 deletions

View file

@ -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 &lt;name&gt; {
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

View file

@ -58,7 +58,16 @@ static void
ospf_area_finish(void) 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 '}'

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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