[PATCH 2/2] Remember sequence number for LSAs.
Alexander V. Chernikov
melifaro at yandex-team.ru
Sun Feb 23 17:56:50 CET 2014
---
proto/ospf/iface.c | 2 +-
proto/ospf/lsalib.c | 5 +-
proto/ospf/lsupd.c | 15 +--
proto/ospf/lsupd.h | 2 +-
proto/ospf/ospf.c | 8 ++
proto/ospf/ospf.h | 4 +
proto/ospf/topology.c | 306 +++++++++++++++++++++++++++++++++++++++++++-------
proto/ospf/topology.h | 17 +++
8 files changed, 301 insertions(+), 58 deletions(-)
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index f4d9be5..171cf7e 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -318,7 +318,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{
ifa->net_lsa->lsa.age = LSA_MAXAGE;
if (state >= OSPF_IS_WAITING)
- ospf_lsupd_flush_nlsa(po, ifa->net_lsa);
+ ospf_lsupd_flush_nlsa(po, ifa->oa, ifa->net_lsa);
if (can_flush_lsa(po))
flush_lsa(ifa->net_lsa, po);
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c
index bcf7bcd..2b238e3 100644
--- a/proto/ospf/lsalib.c
+++ b/proto/ospf/lsalib.c
@@ -69,10 +69,7 @@ ospf_age(struct proto_ospf *po)
{
OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %R, Rt: %R",
en->lsa.type, en->lsa.id, en->lsa.rt);
- en->lsa.sn++;
- en->lsa.age = 0;
- en->inst_t = now;
- en->ini_age = 0;
+ update_lsa_seq(po, en, en->lsa.sn + 1); /* XXX: LSA_MAXSEQNO */
lsasum_calculate(&en->lsa, en->lsa_body);
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, en->domain, 1);
continue;
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index 8f65c53..65c9ae4 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -600,20 +600,14 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
if (lsadb)
{
OSPF_TRACE(D_EVENTS, "Reflooding new self-originated LSA with newer sequence number");
- lsadb->lsa.sn = lsatmp.sn + 1;
- lsadb->lsa.age = 0;
- lsadb->inst_t = now;
- lsadb->ini_age = 0;
- lsasum_calculate(&lsadb->lsa, lsadb->lsa_body);
+ update_lsa_seq(po, lsadb, lsatmp.sn + 1); /* XXX: lsatmp.sn == LSA_MAXSEQNO - 1 */
ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, domain, 1);
}
else
{
OSPF_TRACE(D_EVENTS, "Premature aging it");
lsatmp.age = LSA_MAXAGE;
- lsatmp.sn = LSA_MAXSEQNO;
lsa->age = htons(LSA_MAXAGE);
- lsa->sn = htonl(LSA_MAXSEQNO);
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
lsatmp.checksum = ntohs(lsa->checksum);
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
@@ -749,14 +743,13 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
void
-ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
+ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct ospf_area *oa, struct top_hash_entry *en)
{
struct ospf_lsa_header *lsa = &en->lsa;
struct proto *p = &po->proto;
- lsa->age = LSA_MAXAGE;
- lsa->sn = LSA_MAXSEQNO;
- lsasum_calculate(lsa, en->lsa_body);
+ flush_lsa_seq(po, oa, en);
+
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
diff --git a/proto/ospf/lsupd.h b/proto/ospf/lsupd.h
index 8bacfe6..780ba9d 100644
--- a/proto/ospf/lsupd.h
+++ b/proto/ospf/lsupd.h
@@ -18,7 +18,7 @@ void ospf_lsupd_receive(struct ospf_packet *ps_i,
int ospf_lsupd_flood(struct proto_ospf *po,
struct ospf_neighbor *n, struct ospf_lsa_header *hn,
struct ospf_lsa_header *hh, u32 domain, int rtl);
-void ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en);
+void ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct ospf_area *oa, struct top_hash_entry *en);
int ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa);
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index e751f7c..0684de9 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -178,6 +178,8 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
if (oa_is_nssa(oa) && ((struct ospf_config *) (p->cf))->abr)
po->ebit = 1;
+ init_seq_fib(po, oa);
+
if (reconf)
ospf_ifaces_reconfigure(oa, ac);
}
@@ -198,6 +200,8 @@ ospf_area_remove(struct ospf_area *oa)
if (oa->translator_timer)
rfree(oa->translator_timer);
+ free_seq_fib(oa->po, oa);
+
oa->po->areano--;
rem_node(NODE oa);
mb_free(oa);
@@ -265,6 +269,8 @@ ospf_start(struct proto *p)
WALK_LIST(ic, c->vlink_list)
ospf_iface_new_vlink(po, ic);
+ init_seq_fib(po, NULL);
+
return PS_UP;
}
@@ -563,6 +569,8 @@ ospf_shutdown(struct proto *p)
}
FIB_WALK_END;
+ free_seq_fib(po, NULL);
+
return PS_DOWN;
}
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 66719e3..44b3344 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -756,6 +756,8 @@ struct ospf_area
timer *translator_timer; /* For NSSA translator switch */
struct proto_ospf *po;
struct fib rtr; /* Routing tables for routers */
+ struct fib seq_fib; /* Sequence number storage for LSAs */
+ timer *seq_timer; /* Timer for seq_fib pruning */
};
#define TRANS_OFF 0
@@ -786,6 +788,8 @@ struct proto_ospf
sock *vlink_sk; /* IP socket used for vlink TX */
u32 router_id;
u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */
+ struct fib seq_fib; /* Sequence number storage for external LSAs */
+ timer *seq_timer; /* Timer for seq_fib pruning */
};
struct ospf_iface_patt
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 6498585..cc4c97a 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -27,6 +27,9 @@ void flush_prefix_net_lsa(struct ospf_iface *ifa);
static void fill_lsa_header(struct proto_ospf *po, struct ospf_area *oa,
struct ospf_lsa_header *lsa, struct fib_node *fn, struct ospf_iface *ifa);
+static s32 get_lsa_seq(struct proto_ospf *po, struct ospf_area *oa, struct ospf_lsa_header *lsa);
+static void check_seq_fibs(struct timer *timer);
+
#ifdef OSPFv2
#define ipa_to_rid(x) _I(x)
#else /* OSPFv3 */
@@ -141,23 +144,6 @@ lsab_end(struct proto_ospf *po)
return ((byte *) po->lsab) + po->lsab_used;
}
-static s32
-get_seqnum(struct top_hash_entry *en)
-{
- if (!en)
- return LSA_INITSEQNO;
-
- if (en->lsa.sn == LSA_MAXSEQNO)
- {
- log(L_WARN "OSPF: Premature origination of LSA (Type: %04x, Id: %R, Rt: %R)",
- en->lsa.type, en->lsa.id, en->lsa.rt);
- return LSA_INITSEQNO;
- }
-
- return en->lsa.sn + 1;
-}
-
-
static int
configured_stubnet(struct ospf_area *oa, struct ifa *a)
{
@@ -490,7 +476,7 @@ originate_rt_lsa(struct ospf_area *oa)
lsa.type = LSA_T_RT;
fill_lsa_header(po, oa, &lsa, NULL, NULL);
- lsa.sn = get_seqnum(oa->rt);
+ lsa.sn = get_lsa_seq(po, oa, &lsa);
u32 dom = oa->areaid;
body = originate_rt_lsa_body(oa, &lsa.length);
@@ -594,7 +580,7 @@ originate_net_lsa(struct ospf_iface *ifa)
lsa.type = LSA_T_NET;
fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa);
- lsa.sn = get_seqnum(ifa->net_lsa);
+ lsa.sn = get_lsa_seq(po, ifa->oa, &lsa);
body = originate_net_lsa_body(ifa, &lsa.length, po);
lsasum_calculate(&lsa, body);
@@ -613,9 +599,7 @@ flush_net_lsa(struct ospf_iface *ifa)
return;
OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s", ifa->ifname);
- ifa->net_lsa->lsa.sn += 1;
- ifa->net_lsa->lsa.age = LSA_MAXAGE;
- lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
+ flush_lsa_seq(po, ifa->oa, ifa->net_lsa);
ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
flush_lsa(ifa->net_lsa, po);
ifa->net_lsa = NULL;
@@ -684,7 +668,7 @@ check_sum_lsa_same(struct top_hash_entry *en, u32 metric)
{
/* Netmask already checked in check_sum_net_lsaid_collision() */
struct ospf_lsa_sum *sum = en->lsa_body;
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
+ return (en->lsa.age != LSA_MAXAGE) && (sum->metric == metric);
}
#define check_sum_net_lsa_same(en,metric) \
@@ -727,7 +711,7 @@ check_sum_net_lsa_same(struct top_hash_entry *en, u32 metric)
{
/* Prefix already checked in check_sum_net_lsaid_collision() */
struct ospf_lsa_sum_net *sum = en->lsa_body;
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->metric == metric);
+ return (en->lsa.age != LSA_MAXAGE) && (sum->metric == metric);
}
static inline void *
@@ -747,7 +731,7 @@ static inline int
check_sum_rt_lsa_same(struct top_hash_entry *en, u32 drid, u32 metric, u32 options)
{
struct ospf_lsa_sum_rt *sum = en->lsa_body;
- return (en->lsa.sn != LSA_MAXSEQNO) && (sum->options == options) &&
+ return (en->lsa.age != LSA_MAXAGE) && (sum->options == options) &&
(sum->metric == metric) && (sum->drid == drid);
}
@@ -781,7 +765,7 @@ originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
if (check_sum_net_lsa_same(en, metric))
return;
}
- lsa.sn = get_seqnum(en);
+ lsa.sn = get_lsa_seq(po, oa, &lsa);
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
lsasum_calculate(&lsa, body);
@@ -813,7 +797,7 @@ originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32
if (check_sum_rt_lsa_same(en, lsa.id, metric, options))
return;
}
- lsa.sn = get_seqnum(en);
+ lsa.sn = get_lsa_seq(po, oa, &lsa);
body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
lsasum_calculate(&lsa, body);
@@ -844,10 +828,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
return;
}
- struct ospf_lsa_sum *sum = en->lsa_body;
- en->lsa.age = LSA_MAXAGE;
- en->lsa.sn = LSA_MAXSEQNO;
- lsasum_calculate(&en->lsa, sum);
+ flush_lsa_seq(po, oa, en);
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
if (can_flush_lsa(po)) flush_lsa(en, po);
}
@@ -893,7 +874,7 @@ check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_add
if (fn->pxlen != ipa_mklen(ext->netmask))
return -1;
- return (en->lsa.sn != LSA_MAXSEQNO) && (ext->metric == metric) &&
+ return (en->lsa.age != LSA_MAXAGE) && (ext->metric == metric) &&
(ext->tag == tag) && ipa_equal(ext->fwaddr,fwaddr);
}
@@ -946,7 +927,7 @@ check_ext_lsa(struct top_hash_entry *en, struct fib_node *fn, u32 metric, ip_add
if ((fn->pxlen != pxlen) || !ipa_equal(fn->prefix, prefix))
return -1;
- if (en->lsa.sn == LSA_MAXSEQNO)
+ if (en->lsa.age == LSA_MAXAGE)
return 0;
u32 rt_metric = ext->metric & METRIC_MASK;
@@ -1081,7 +1062,7 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
if (rv > 0)
return;
}
- lsa.sn = get_seqnum(en);
+ lsa.sn = get_lsa_seq(po, NULL, &lsa);
body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
lsasum_calculate(&lsa, body);
@@ -1126,7 +1107,7 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa)
}
fn->x1 = 0;
- ospf_lsupd_flush_nlsa(po, en);
+ ospf_lsupd_flush_nlsa(po, NULL, en);
}
}
@@ -1216,6 +1197,251 @@ fill_lsa_header(struct proto_ospf *po, struct ospf_area *oa, struct ospf_lsa_hea
lsa->id = lsid;
}
+static struct seq_data *
+find_seq(struct proto_ospf *po, struct ospf_area *oa, struct ospf_lsa_header *lsa, int create)
+{
+ struct seq_fib_data *sfd;
+ struct fib *seq_fib;
+ ip_addr addr;
+
+ memset(&addr, 0, sizeof(addr));
+#ifdef IPV6
+ _I3(addr) = lsa->id;
+#else
+ addr = _I(lsa->id);
+#endif
+
+ if (oa != NULL)
+ seq_fib = &oa->seq_fib;
+ else
+ seq_fib = &po->seq_fib;
+
+ if (create != 0)
+ sfd = (struct seq_fib_data *)fib_get(seq_fib, &addr, BITS_PER_IP_ADDRESS);
+ else
+ sfd = (struct seq_fib_data *)fib_find(seq_fib, &addr, BITS_PER_IP_ADDRESS);
+
+ if (sfd == NULL)
+ return NULL;
+
+ return &sfd->type[lsa->type % SEQ_DATA_MAX];
+}
+
+static s32
+get_lsa_seq(struct proto_ospf *po, struct ospf_area *oa, struct ospf_lsa_header *lsa)
+{
+ struct seq_data *sd;
+
+ sd = find_seq(po, oa, lsa, 1);
+
+ if (sd->active == 0)
+ {
+ /* New entry */
+ sd->seq = LSA_INITSEQNO;
+ }
+ else
+ {
+ if (++sd->seq == LSA_MAXSEQNO)
+ {
+ /*
+ * According to 12.1.6 in 2338 RFC
+ * we need to ensure that previous version
+ * is flushed:
+ *
+ * 'As soon as this flood has been acknowledged by
+ * all adjacent neighbors, a new instance can be
+ * originated with sequence number of InitialSequenceNumber.'
+ *
+ * XXX: We're currently not controlling if our adjacent neighbors
+ * acknowledge LSA flush. However, since this is VERY rare case,
+ * simply set seq to InitialSequenceNumber.
+ */
+ sd->seq = LSA_INITSEQNO;
+ }
+ }
+
+ sd->active = 1;
+ sd->last = now;
+
+ return sd->seq;
+}
+
+/**
+ * update_lsa_seq - updates age/seq/checksum for given LSA.
+ * @po: OSPF protocol
+ * @oa: OSPF area
+ * @en: LSA base
+ * @sn: new checksum
+ */
+void
+update_lsa_seq(struct proto_ospf *po, struct top_hash_entry *en, s32 sn)
+{
+ struct ospf_lsa_header *lsa = &en->lsa;
+ struct ospf_area *oa = NULL;
+ struct seq_data *sd;
+
+ lsa->sn = sn;
+ lsa->age = 0;
+ en->inst_t = now;
+ en->ini_age = 0;
+ lsasum_calculate(lsa, en->lsa_body);
+
+ /*
+ * Get area to search into.
+ * Treat LSA_SCOPE_LINK as AREA and
+ * LSA_SCOPE_RES (if any) as AS
+ */
+ switch (LSA_SCOPE(lsa))
+ {
+#ifndef OSPFv2
+ case LSA_SCOPE_LINK:
+#endif
+ case LSA_SCOPE_AREA:
+ oa = ospf_find_area(po, en->domain);
+ break;
+ }
+
+ if ((sd = find_seq(po, oa, lsa, 0)) == NULL)
+ {
+ log(L_WARN "Unable to find LSA sequence for LSA (id=%R type %d)", lsa->id, lsa->type);
+ return;
+ }
+
+ sd->seq = lsa->sn;
+ sd->last = now;
+}
+
+/**
+ * flush_lsa_seq - notify we're not using given LSA anymore. Updates LSA age/checksum.
+ * @po: OSPF protocol
+ * @oa: OSPF area
+ * @en: LSA base
+ */
+void
+flush_lsa_seq(struct proto_ospf *po, struct ospf_area *oa, struct top_hash_entry *en)
+{
+ struct ospf_lsa_header *lsa = &en->lsa;
+ struct seq_data *sd;
+
+ lsa->age = LSA_MAXAGE;
+ lsasum_calculate(lsa, en->lsa_body);
+
+ if ((sd = find_seq(po, oa, lsa, 0)) == NULL)
+ {
+ log(L_WARN "Unable to flush LSA sequence for LSA (id=%R type %d)", lsa->id, lsa->type);
+ return;
+ }
+
+ sd->active = -1;
+ sd->last = now;
+}
+
+/**
+ * check_seq_fib - remove unused prefixes from fib
+ * @po: OSPF protocol
+ * @seq_fib: fib put prune
+ */
+static void
+check_seq_fib(struct proto_ospf *po, struct fib *seq_fib)
+{
+ struct fib_iterator fit;
+ struct seq_fib_data *sfd;
+ struct seq_data *sd;
+ int i, keep;
+
+ FIB_ITERATE_INIT(&fit, seq_fib);
+again:
+ FIB_ITERATE_START(seq_fib, &fit, nftmp)
+ {
+ sfd = (struct seq_fib_data *) nftmp;
+
+ /*
+ * Check if we need purge "old" prefixes.
+ *
+ * RFC 2328, 14 tells us:
+ *
+ * A MaxAge LSA must be removed immediately from the router's link
+ * state database as soon as both a) it is no longer contained on any
+ * neighbor Link state retransmission lists and b) none of the router's
+ * neighbors are in states Exchange or Loading.
+ *
+ * This basically means we have no guaranteed timing on MaxAge LSA
+ * removal, so we keep entries for considerably long amount of time.
+ */
+ keep = 0;
+ for (i = 0; i < SEQ_DATA_MAX; i++)
+ {
+ sd = &sfd->type[i];
+ if (sd->active == 1 || sd->last + 3600 >= now)
+ keep = 1;
+ }
+ if (keep == 0)
+ {
+ FIB_ITERATE_PUT(&fit, nftmp);
+ fib_delete(seq_fib, nftmp);
+ goto again;
+ }
+ }
+ FIB_ITERATE_END(nftmp);
+}
+
+/**
+ * check_seq_fib - remove unused prefixes from fib
+ * @timer: timer
+ */
+static void
+check_seq_fibs(timer *timer)
+{
+ struct proto_ospf *po = timer->data;
+ struct ospf_area *oa;
+
+ /* Check protocol fib first */
+ check_seq_fib(po, &po->seq_fib);
+
+ WALK_LIST(oa, po->area_list)
+ check_seq_fib(po, &oa->seq_fib);
+}
+
+
+/**
+ * init_seq_fib - Initialize fib for sequence storage
+ * @po: OSPF protocol
+ * @oa: OSPF area, if set
+ */
+void
+init_seq_fib(struct proto_ospf *po, struct ospf_area *oa)
+{
+ timer *t;
+ struct fib *seq_fib = (oa == NULL) ? &po->seq_fib : &oa->seq_fib;
+
+ fib_init(seq_fib, po->proto.pool, sizeof(struct seq_fib_data), 0, NULL);
+
+ if (oa == NULL)
+ {
+ t = tm_new(po->proto.pool);
+ t->data = po;
+ t->randomize = 0;
+ t->hook = check_seq_fibs;
+ t->recurrent = 3600 / 3;
+ po->seq_timer = t;
+ tm_start(t, t->recurrent);
+ }
+}
+
+/**
+ * free_seq_fib - iFree sequence storage fib
+ * @po: OSPF protocol
+ */
+void
+free_seq_fib(struct proto_ospf *po, struct ospf_area *oa)
+{
+ struct fib *seq_fib = (oa == NULL) ? &po->seq_fib : &oa->seq_fib;
+
+ fib_free(seq_fib);
+ if (oa != NULL)
+ rfree(oa->seq_timer);
+}
+
#ifdef OSPFv3
static void *
@@ -1267,7 +1493,7 @@ originate_link_lsa(struct ospf_iface *ifa)
lsa.type = LSA_T_LINK;
fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa);
- lsa.sn = get_seqnum(ifa->link_lsa);
+ lsa.sn = get_lsa_seq(po, ifa->oa, &lsa);
u32 dom = ifa->iface_id;
body = originate_link_lsa_body(ifa, &lsa.length);
@@ -1411,7 +1637,7 @@ originate_prefix_rt_lsa(struct ospf_area *oa)
lsa.type = LSA_T_PREFIX;
fill_lsa_header(po, oa, &lsa, NULL, NULL);
- lsa.sn = get_seqnum(oa->pxr_lsa);
+ lsa.sn = get_lsa_seq(po, oa, &lsa);
u32 dom = oa->areaid;
body = originate_prefix_rt_lsa_body(oa, &lsa.length);
@@ -1548,7 +1774,7 @@ originate_prefix_net_lsa(struct ospf_iface *ifa)
lsa.type = LSA_T_PREFIX;
fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa);
- lsa.sn = get_seqnum(ifa->pxn_lsa);
+ lsa.sn = get_lsa_seq(po, ifa->oa, &lsa);
u32 dom = ifa->oa->areaid;
body = originate_prefix_net_lsa_body(ifa, &lsa.length);
@@ -1570,9 +1796,7 @@ flush_prefix_net_lsa(struct ospf_iface *ifa)
OSPF_TRACE(D_EVENTS, "Flushing network prefix-LSA for iface %s", ifa->ifname);
- en->lsa.sn += 1;
- en->lsa.age = LSA_MAXAGE;
- lsasum_calculate(&en->lsa, en->lsa_body);
+ flush_lsa_seq(po, ifa->oa, en);
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, dom, 0);
flush_lsa(en, po);
ifa->pxn_lsa = NULL;
diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h
index cb87648..5cc64c9 100644
--- a/proto/ospf/topology.h
+++ b/proto/ospf/topology.h
@@ -47,6 +47,19 @@ struct top_graph
unsigned int hash_entries_min, hash_entries_max;
};
+struct seq_data {
+ int active;
+ s32 seq;
+ bird_clock_t last;
+};
+#define SEQ_DATA_MAX 16
+
+struct seq_fib_data
+{
+ struct fib_node fn;
+ struct seq_data type[SEQ_DATA_MAX]; /* One for each possible LSA types */
+};
+
struct top_graph *ospf_top_new(pool *);
void ospf_top_free(struct top_graph *);
void ospf_top_dump(struct top_graph *, struct proto *);
@@ -73,6 +86,10 @@ void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric,
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 src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa);
+void flush_lsa_seq(struct proto_ospf *po, struct ospf_area *oa, struct top_hash_entry *en);
+void update_lsa_seq(struct proto_ospf *po, struct top_hash_entry *en, s32 sn);
+void init_seq_fib(struct proto_ospf *po, struct ospf_area *oa);
+void free_seq_fib(struct proto_ospf *po, struct ospf_area *oa);
#ifdef OSPFv2
--
1.7.11.5
--------------000206050504040902070200--
More information about the Bird-users
mailing list