summaryrefslogtreecommitdiff
path: root/proto/ospf/topology.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2014-07-18 18:24:12 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2014-07-18 18:24:12 +0200
commita7a7372aa7c527619ee527e3b37013f9fb87d618 (patch)
treea242ba4528900b5a8b2b68de1c2ab8939eaa7ae7 /proto/ospf/topology.c
parent70945cb645402a4bb1d3dc46a07928caeb954c1f (diff)
Temporary integrated OSPF commit.
Diffstat (limited to 'proto/ospf/topology.c')
-rw-r--r--proto/ospf/topology.c340
1 files changed, 143 insertions, 197 deletions
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 5ed3cf7a..bc2de79f 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -40,11 +40,13 @@ static inline void lsab_reset(struct ospf_proto *p);
* new routing table calculation is necessary. This is described in 13.2 of RFC
* 2328. This function is for received LSA only, locally originated LSAs are
* installed by ospf_originate_lsa().
+ *
+ * The LSA body in @body is expected to be mb_allocated by the caller and its
+ * ownership is transferred to the LSA entry structure.
*/
struct top_hash_entry *
ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u32 domain, void *body)
{
- /* LSA can be temporary, but body must be mb_allocated. */
struct top_hash_entry *en;
int change = 0;
@@ -61,8 +63,8 @@ ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u3
memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
change = 1;
- DBG("Inst lsa: Id: %R, Rt: %R, Type: %u, Age: %u, Sum: %u, Sn: 0x%x\n",
- lsa->id, lsa->rt, lsa->type, lsa->age, lsa->checksum, lsa->sn);
+ if ((en->lsa.age == LSA_MAXAGE) && (lsa->age == LSA_MAXAGE))
+ change = 0;
mb_free(en->lsa_body);
en->lsa_body = body;
@@ -70,16 +72,43 @@ ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u3
en->init_age = en->lsa.age;
en->inst_time = now;
+ /*
+ * We do not set en->mode. It is either default LSA_M_BASIC, or in a special
+ * case when en is local but flushed, there is postponed LSA, self-originated
+ * LSA is received and ospf_install_lsa() is called from ospf_advance_lse(),
+ * then we have en->mode from the postponed LSA origination.
+ */
+
+ OSPF_TRACE(D_EVENTS, "Installing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
+
if (change)
- schedule_rtcalc(p);
+ ospf_schedule_rtcalc(p);
return en;
}
+/**
+ * ospf_advance_lsa - handle received unexpected self-originated LSA
+ * @p: OSPF protocol instance
+ * @en: current LSA entry or NULL
+ * @lsa: new LSA header
+ * @type: type of LSA
+ * @domain: domain of LSA
+ * @body: pointer to LSA body
+ *
+ * This function handles received unexpected self-originated LSA (@lsa, @body)
+ * by either advancing sequence number of the local LSA instance (@en) and
+ * propagating it, or installing the received LSA and immediately flushing it
+ * (if there is no local LSA; i.e., @en is NULL or MaxAge).
+ *
+ * The LSA body in @body is expected to be mb_allocated by the caller and its
+ * ownership is transferred to the LSA entry structure or it is freed.
+ */
void
ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_lsa_header *lsa, u32 type, u32 domain, void *body)
{
- // OSPF_TRACE(D_EVENTS, "Reflooding new self-originated LSA with newer sequence number");
+ /* RFC 2328 13.4 */
if (en && (en->lsa.age < LSA_MAXAGE))
{
@@ -101,6 +130,9 @@ ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ls
en->init_age = 0;
en->inst_time = now;
lsasum_calculate(&en->lsa, en->lsa_body);
+
+ OSPF_TRACE(D_EVENTS, "Advancing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
}
else
{
@@ -129,6 +161,11 @@ ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ls
en->lsa.age = LSA_MAXAGE;
en->init_age = lsa->age;
en->inst_time = now;
+
+ OSPF_TRACE(D_EVENTS, "Resetting LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
+ OSPF_TRACE(D_EVENTS, "Postponing LSA: Type: %04x, Id: %R, Rt: %R",
+ en->lsa_type, en->lsa.id, en->lsa.rt);
}
}
else
@@ -137,6 +174,7 @@ ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ls
* We do not have received LSA in the database. We have to flush the
* received LSA. It has to be installed in the database to secure
* retransmissions. Note that the received LSA may already be MaxAge.
+ * Also note that en->next_lsa_* may be defined.
*/
lsa->age = LSA_MAXAGE;
@@ -150,7 +188,7 @@ ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ls
* the neighbor we received it from), we cheat a bit here.
*/
- ospf_lsupd_flood(p, en, NULL);
+ ospf_flood_lsa(p, en, NULL);
}
@@ -167,11 +205,11 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa
/* Prepare to flush old LSA */
if (en->lsa.age != LSA_MAXAGE)
{
- OSPF_TRACE(D_EVENTS, "Resetting LSA: Type: %04x, Id: %R, Rt: %R",
- en->lsa_type, en->lsa.id, en->lsa.rt);
+ OSPF_TRACE(D_EVENTS, "Resetting LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
en->lsa.age = LSA_MAXAGE;
- ospf_lsupd_flood(p, en, NULL);
+ ospf_flood_lsa(p, en, NULL);
return 0;
}
@@ -183,9 +221,6 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa
en->lsa.sn = LSA_ZEROSEQNO;
}
- OSPF_TRACE(D_EVENTS, "Originating LSA: Type: %04x, Id: %R, Rt: %R",
- en->lsa_type, en->lsa.id, en->lsa.rt);
-
/*
* lsa.type_raw is initialized by ospf_hash_get() to OSPFv3 LSA type.
* lsa_set_options() implicitly converts it to OSPFv2 LSA type, assuming that
@@ -205,7 +240,13 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa
en->inst_time = now;
lsasum_calculate(&en->lsa, en->lsa_body);
- ospf_lsupd_flood(p, en, NULL);
+ OSPF_TRACE(D_EVENTS, "Originating LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
+
+ ospf_flood_lsa(p, en, NULL);
+
+ if (en->mode == LSA_M_BASIC)
+ ospf_schedule_rtcalc(p);
return 1;
}
@@ -244,15 +285,20 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
{
log(L_ERR "%s: LSA ID collision for %I/%d",
p->p.name, lsa->nf->fn.prefix, lsa->nf->fn.pxlen);
+
+ en = NULL;
goto drop;
}
- /* XXXX check for maxage or opts change */
+ if (en->mode != lsa->mode)
+ en->mode = lsa->mode;
if (en->next_lsa_body)
{
/* Ignore the new LSA if it is the same as the scheduled one */
- if ((lsa_blen == en->next_lsa_blen) && !memcmp(lsa_body, en->next_lsa_body, lsa_blen))
+ if ((lsa_blen == en->next_lsa_blen) &&
+ !memcmp(lsa_body, en->next_lsa_body, lsa_blen) &&
+ (!ospf_is_v2(p) || (lsa->opts == en->next_lsa_opts)))
goto drop;
/* Free scheduled LSA */
@@ -263,13 +309,19 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
}
/* Ignore the the new LSA if is the same as the current one */
- if ((lsa_length == en->lsa.length) && !memcmp(lsa_body, en->lsa_body, lsa_blen))
+ if ((en->lsa.age < LSA_MAXAGE) &&
+ (lsa_length == en->lsa.length) &&
+ !memcmp(lsa_body, en->lsa_body, lsa_blen) &&
+ (!ospf_is_v2(p) || (lsa->opts == lsa_get_options(&en->lsa))))
goto drop;
lsa_body = lsab_flush(p);
if (! ospf_do_originate_lsa(p, en, lsa_body, lsa_blen, lsa->opts))
{
+ OSPF_TRACE(D_EVENTS, "Postponing LSA: Type: %04x, Id: %R, Rt: %R",
+ en->lsa_type, en->lsa.id, en->lsa.rt);
+
en->next_lsa_body = lsa_body;
en->next_lsa_blen = lsa_blen;
en->next_lsa_opts = lsa->opts;
@@ -293,8 +345,6 @@ ospf_originate_next_lsa(struct ospf_proto *p, struct top_hash_entry *en)
en->next_lsa_body = NULL;
en->next_lsa_blen = 0;
en->next_lsa_opts = 0;
-
- // XXXX: schedule_rtcalc(p);
}
static void
@@ -309,8 +359,8 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
* switched lsa.age to LSA_MAXAGE.
*/
- OSPF_TRACE(D_EVENTS, "Refreshing LSA: Type: %04x, Id: %R, Rt: %R",
- en->lsa_type, en->lsa.id, en->lsa.rt);
+ OSPF_TRACE(D_EVENTS, "Refreshing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
ASSERT(en->next_lsa_body == NULL);
@@ -324,7 +374,7 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
en->next_lsa_opts = ospf_is_v2(p) ? lsa_get_options(&en->lsa) : 0;
en->lsa.age = LSA_MAXAGE;
- ospf_lsupd_flood(p, en, NULL);
+ ospf_flood_lsa(p, en, NULL);
return;
}
@@ -333,7 +383,7 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
en->init_age = 0;
en->inst_time = now;
lsasum_calculate(&en->lsa, en->lsa_body);
- ospf_lsupd_flood(p, en, NULL);
+ ospf_flood_lsa(p, en, NULL);
}
/**
@@ -349,16 +399,13 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
* immediately removed when being flushed, the caller may assume that @en still
* exists after the call. The function is the opposite of ospf_originate_lsa()
* and is supposed to do the right thing even in cases of postponed
- * origination. Note that this function do not schedule routing table
- * calculation, the caller is responsible to do it if necessary.
+ * origination.
*/
void
ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
{
- OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R",
- en->lsa_type, en->lsa.id, en->lsa.rt);
-
- en->rtcalc = 0;
+ OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+ en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
if (en->next_lsa_body)
{
@@ -372,7 +419,12 @@ ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
return;
en->lsa.age = LSA_MAXAGE;
- ospf_lsupd_flood(p, en, NULL);
+ ospf_flood_lsa(p, en, NULL);
+
+ if (en->mode == LSA_M_BASIC)
+ ospf_schedule_rtcalc(p);
+
+ en->mode = LSA_M_BASIC;
}
static void
@@ -450,7 +502,6 @@ ospf_update_lsadb(struct ospf_proto *p)
if (real_age >= LSA_MAXAGE)
{
ospf_flush_lsa(p, en);
- schedule_rtcalc(p);
continue;
}
@@ -510,9 +561,9 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
static void *
-lsab_alloc(struct ospf_proto *p, unsigned size)
+lsab_alloc(struct ospf_proto *p, uint size)
{
- unsigned offset = p->lsab_used;
+ uint offset = p->lsab_used;
p->lsab_used += size;
if (p->lsab_used > p->lsab_size)
{
@@ -524,7 +575,7 @@ lsab_alloc(struct ospf_proto *p, unsigned size)
}
static inline void *
-lsab_allocz(struct ospf_proto *p, unsigned size)
+lsab_allocz(struct ospf_proto *p, uint size)
{
void *r = lsab_alloc(p, size);
bzero(r, size);
@@ -547,7 +598,7 @@ lsab_reset(struct ospf_proto *p)
}
static inline void *
-lsab_offset(struct ospf_proto *p, unsigned offset)
+lsab_offset(struct ospf_proto *p, uint offset)
{
return ((byte *) p->lsab) + offset;
}
@@ -815,15 +866,6 @@ prepare_rt3_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
rt->options = get_rt_options(p, oa, bitv) | (oa->options & LSA_OPTIONS_MASK);
}
-/**
- * ospf_originate_rt_lsa - build new instance of router LSA
- * @oa: ospf_area which is LSA built to
- *
- * It builds router LSA walking through all OSPF interfaces in
- * specified OSPF area. This function is mostly called from
- * area_disp(). Builds new LSA, increases sequence number (if old
- * instance exists) and sets age of LSA to zero.
- */
static void
ospf_originate_rt_lsa(struct ospf_proto *p, struct ospf_area *oa)
{
@@ -834,6 +876,8 @@ ospf_originate_rt_lsa(struct ospf_proto *p, struct ospf_area *oa)
.opts = oa->options
};
+ OSPF_TRACE(D_EVENTS, "Updating router state for area %R", oa->areaid);
+
if (ospf_is_v2(p))
prepare_rt2_lsa_body(p, oa);
else
@@ -908,15 +952,6 @@ prepare_net3_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
net->optx = options & LSA_OPTIONS_MASK;
}
-/**
- * ospf_originate_net_lsa - originates of deletes network LSA
- * @ifa: interface which is LSA originated for
- *
- * Interface counts number of adjacent neighbors. If this number is
- * lower than one or interface is not in state %OSPF_IS_DR it deletes
- * and premature ages instance of network LSA for specified interface.
- * In other case, new instance of network LSA is originated.
- */
static void
ospf_originate_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
{
@@ -928,6 +963,8 @@ ospf_originate_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
.ifa = ifa
};
+ OSPF_TRACE(D_EVENTS, "Updating network state for %s (Id: %R)", ifa->ifname, lsa.id);
+
if (ospf_is_v2(p))
prepare_net2_lsa_body(p, ifa);
else
@@ -977,10 +1014,9 @@ prepare_sum3_rt_lsa_body(struct ospf_proto *p, u32 drid, u32 metric, u32 options
void
ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric)
{
- struct top_hash_entry *en;
-
struct ospf_new_lsa lsa = {
.type = LSA_T_SUM_NET,
+ .mode = LSA_M_RTCALC,
.dom = oa->areaid,
.id = ort_to_lsaid(p, nf),
.opts = oa->options,
@@ -992,32 +1028,26 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf,
else
prepare_sum3_net_lsa_body(p, nf, metric);
- en = ospf_originate_lsa(p, &lsa);
- en->rtcalc = LSA_RTCALC;
+ ospf_originate_lsa(p, &lsa);
}
void
ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options)
{
- struct top_hash_entry *en;
- u32 rid = ipa_to_rid(nf->fn.prefix);
-
- /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
-
struct ospf_new_lsa lsa = {
.type = LSA_T_SUM_RT,
+ .mode = LSA_M_RTCALC,
.dom = oa->areaid,
- .id = rid,
+ .id = ipa_to_rid(nf->fn.prefix), /* Router ID of ASBR, irrelevant for OSPFv3 */
.opts = oa->options
};
if (ospf_is_v2(p))
prepare_sum2_lsa_body(p, 0, metric);
else
- prepare_sum3_rt_lsa_body(p, rid, metric, options & LSA_OPTIONS_MASK);
+ prepare_sum3_rt_lsa_body(p, lsa.id, metric, options & LSA_OPTIONS_MASK);
- en = ospf_originate_lsa(p, &lsa);
- en->rtcalc = LSA_RTCALC;
+ ospf_originate_lsa(p, &lsa);
}
@@ -1076,13 +1106,15 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
/**
* originate_ext_lsa - new route received from nest and filters
+ * @p: OSPF protocol instance
* @oa: ospf_area for which LSA is originated
* @nf: network prefix and mask
- * @src: the source of origination of the LSA (EXT_EXPORT/EXT_NSSA)
- * @metric: the metric of a route (possibly with appropriate E-bit)
+ * @mode: the mode of the LSA (LSA_M_EXPORT or LSA_M_RTCALC)
+ * @metric: the metric of a route
+ * @ebit: E-bit for route metric (bool)
* @fwaddr: the forwarding address
* @tag: the route tag
- * @pbit: P-bit for NSSA LSAs, ignored for external LSAs
+ * @pbit: P-bit for NSSA LSAs (bool), ignored for external LSAs
*
* 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.
@@ -1091,13 +1123,12 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
* the export from ospf_rt_notify(), or the NSSA-EXT translation.
*/
void
-ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 rtcalc,
+ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode,
u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit)
{
- struct top_hash_entry *en;
-
struct ospf_new_lsa lsa = {
.type = oa ? LSA_T_NSSA : LSA_T_EXT,
+ .mode = mode, /* LSA_M_EXPORT or LSA_M_RTCALC */
.dom = oa ? oa->areaid : 0,
.id = ort_to_lsaid(p, nf),
.opts = oa ? (pbit ? OPT_P : 0) : OPT_E,
@@ -1109,8 +1140,7 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 r
else
prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit);
- en = ospf_originate_lsa(p, &lsa);
- en->rtcalc = rtcalc;
+ ospf_originate_lsa(p, &lsa);
}
static void
@@ -1228,7 +1258,7 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
/* Old external route might blocked some NSSA translation */
if ((p->areano > 1) && rt_is_nssa(nf) && nf->n.oa->translate)
- schedule_rtcalc(p);
+ ospf_schedule_rtcalc(p);
return;
}
@@ -1262,7 +1292,7 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
}
nf = (ort *) fib_get(&p->rtf, &n->n.prefix, n->n.pxlen);
- ospf_originate_ext_lsa(p, oa, nf, 0, metric, ebit, fwd, tag, 1);
+ ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1);
nf->external_rte = 1;
}
@@ -1320,6 +1350,8 @@ ospf_originate_link_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
.ifa = ifa
};
+ OSPF_TRACE(D_EVENTS, "Updating link state for %s (Id: %R)", ifa->ifname, lsa.id);
+
prepare_link_lsa_body(p, ifa);
ifa->link_lsa = ospf_originate_lsa(p, &lsa);
@@ -1576,6 +1608,8 @@ ospf_originate_prefix_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa)
ifa->pxn_lsa = ospf_originate_lsa(p, &lsa);
}
+static inline int breaks_minlsinterval(struct top_hash_entry *en)
+{ return en && (en->lsa.age < LSA_MAXAGE) && ((en->inst_time + MINLSINTERVAL) > now); }
void
ospf_update_topology(struct ospf_proto *p)
@@ -1587,6 +1621,25 @@ ospf_update_topology(struct ospf_proto *p)
{
if (oa->update_rt_lsa)
{
+ /*
+ * Generally, MinLSInterval is enforced in ospf_do_originate_lsa(), but
+ * origination of (prefix) router LSA is a special case. We do not want to
+ * prepare a new router LSA body and then postpone it in en->next_lsa_body
+ * for later origination, because there are side effects (updates of
+ * rt_pos_* and px_pos_* in ospf_iface structures) during that, which may
+ * confuse routing table calculation if executed after LSA body
+ * preparation but before final LSA origination (as rtcalc would use
+ * current rt_pos_* indexes but the old router LSA body).
+ *
+ * Here, we ensure that MinLSInterval is observed and we do not even try
+ * to originate these LSAs if it is not. Therefore, origination, when
+ * requested, will succeed unless there is also a seqnum wrapping, which
+ * is not a problem because in that case rtcalc is blocked by MaxAge.
+ */
+
+ if (breaks_minlsinterval(oa->rt) || breaks_minlsinterval(oa->pxr_lsa))
+ continue;
+
ospf_originate_rt_lsa(p, oa);
ospf_originate_prefix_rt_lsa(p, oa);
oa->update_rt_lsa = 0;
@@ -1624,8 +1677,6 @@ ospf_update_topology(struct ospf_proto *p)
ifa->update_net_lsa = 0;
}
}
-
- // XXXX schedule_rtcalc(p);
}
@@ -1664,7 +1715,7 @@ ospf_top_hash_u32(u32 a)
return a;
}
-static unsigned
+static uint
ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
{
/* In OSPFv2, we don't know Router ID when looking for network LSAs.
@@ -1685,12 +1736,14 @@ ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
/**
* ospf_top_new - allocated new topology database
* @p: OSPF protocol instance
+ * @pool: pool for allocation
*
- * this dynamically hashed structure is often used for keeping lsas. mainly
- * its used in @ospf_area structure.
+ * This dynamically hashed structure is used for keeping LSAs. Mainly it is used
+ * for the LSA database of the OSPF protocol, but also for LSA retransmission
+ * and request lists of OSPF neighbors.
*/
struct top_graph *
-ospf_top_new(pool *pool)
+ospf_top_new(struct ospf_proto *p, pool *pool)
{
struct top_graph *f;
@@ -1701,6 +1754,7 @@ ospf_top_new(pool *pool)
ospf_top_ht_alloc(f);
f->hash_entries = 0;
f->hash_entries_min = 0;
+ f->ospf2 = ospf_is_v2(p);
return f;
}
@@ -1715,8 +1769,8 @@ ospf_top_free(struct top_graph *f)
static void
ospf_top_rehash(struct top_graph *f, int step)
{
- unsigned int oldn, oldh;
struct top_hash_entry **n, **oldt, **newt, *e, *x;
+ uint oldn, oldh;
oldn = f->hash_size;
oldt = f->hash_table;
@@ -1752,7 +1806,7 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
e = e->next;
/* Hide hash entry with empty lsa_body */
- return e->lsa_body ? e : NULL;
+ return (e && e->lsa_body) ? e : NULL;
}
/* In OSPFv2, lsa.id is the same as lsa.rt for router LSA. In OSPFv3, we don't know
@@ -1780,11 +1834,15 @@ ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
return rv;
}
+/*
+ * ospf_hash_find_rt3_first() and ospf_hash_find_rt3_next() are used exclusively
+ * for lsa_walk_rt_init(), lsa_walk_rt(), therefore they skip MaxAge entries.
+ */
static inline struct top_hash_entry *
find_matching_rt3(struct top_hash_entry *e, u32 domain, u32 rtr)
{
while (e && (e->lsa.rt != rtr || e->lsa_type != LSA_T_RT ||
- e->domain != domain || e->lsa_body == NULL))
+ e->domain != domain || e->lsa.age == LSA_MAXAGE))
e = e->next;
return e;
}
@@ -1917,7 +1975,7 @@ ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
void
ospf_top_dump(struct top_graph *f, struct proto *p)
{
- unsigned int i;
+ uint i;
OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries);
for (i = 0; i < f->hash_size; i++)
@@ -1928,115 +1986,3 @@ ospf_top_dump(struct top_graph *f, struct proto *p)
}
}
*/
-
-
-
-#if 0
-
-void
-update_rt_lsa(struct ospf_area *oa)
-{
- struct ospf_proto *po = oa->po;
-
- if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
- return;
-
- originate_rt_lsa(oa);
- if (ospf_is_v3(p))
- originate_prefix_rt_lsa(oa);
-
- schedule_rtcalc(p);
- oa->origrt = 0;
-}
-
-
-
-
-static inline int
-check_sum2_net_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric)
-{
- struct ospf_lsa_sum2 *sum = en->lsa_body;
-
- if (fn->pxlen != ip4_masklen(sum->netmask))
- return -1;
-
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
-}
-
-static inline int
-check_sum3_net_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric)
-{
- struct ospf_lsa_sum3_net *sum = en->lsa_body;
- ip6_addr prefix;
- int pxlen;
- u8 pxopts;
- u16 rest;
- lsa_get_ipv6_prefix(sum->prefix, &prefix, &pxlen, &pxopts, &rest);
-
-
- if ((fn->pxlen != pxlen) || !ip6_equal(fn->prefix, prefix))
- return -1;
-
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
-}
-
-
-static int
-check_sum_net_lsa(struct ospf_proto *po, struct top_hash_entry *en, struct fib_node *fn, u32 metric)
-{
- int rv = ospf_is_v2(po) ?
- check_sum2_net_lsa(en, fn, metric) :
- check_sum3_net_lsa(en, fn, metric);
-
- if (rv < 0)
- log(L_ERR "%s: LSAID collision for %I/%d", p->p.name, fn->prefix, fn->pxlen);
-
- return rv;
-}
-
-static int
-check_sum_rt_lsa(struct ospf_proto *po, struct top_hash_entry *en, u32 drid, u32 metric, u32 options)
-{
- if (en->lsa.sn == LSA_MAXSEQNO)
- return 0;
-
- if (ospf_is_v2(po))
- {
- struct ospf_lsa_sum2 *sum = en->lsa_body;
- return (sum->metric == metric);
- }
- else
- {
- struct ospf_lsa_sum3_rt *sum = en->lsa_body;
- return (sum->options == options) && (sum->metric == metric) && (sum->drid == drid);
- }
-}
-
-
-
-
-
-
-
- OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
- OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s", ifa->ifname);
- OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)", fn->prefix, fn->pxlen, metric);
- OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)", rid, metric);
- OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
- nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
- OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->ifname);
- OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
- OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s", ifa->ifname);
-
-
- en = ospf_hash_find(po->gr, lsa.dom, lsa.id, po->router_id, lsa.type);
- if (en && check_ext_lsa(po, en, fn, metric, fwaddr, tag))
- return;
-
- *length = sizeof(struct ospf_lsa_header) + po->lsab_used;
- return lsab_flush(po);
-
- *length = po->lsab_used + sizeof(struct ospf_lsa_header);
- return lsab_flush(po);
-
-#endif