From b4b359a265f1b6272b4eb17c11e9c6ef9817f34b Mon Sep 17 00:00:00 2001 From: Pradosh Mohapatra Date: Mon, 28 Apr 2014 10:58:06 +0000 Subject: [PATCH] ospfd: For an ABR, ensure the right LSID is MaxAge'd PROBLEM: Accurate garbage collection of maxage LSAs. The global OSPF structure has a maxage_lsa tree - the key to the tree is tuple. Suppose the ABR has multiple areas and has originated some intra-area LSAs. The key for all those LSAs is the same. The code then ends up in a state where all but the first LSA do not get cleaned up from the areas' LSDB. A subsequent event would readvertise those LSAs. PATCH: Since the LSA is going to stick around till it actually gets cleaned up by the maxage_walker, make the LSA pointer as the key. Each distinct LSA that gets maxage'd then gets added to the tree and will get cleaned up correctly. Signed-off-by: Pradosh Mohapatra [CF: Use CHAR_BIT; use uintptr_t; use sizeof(field) instead of sizeof(type)] Signed-off-by: Christian Franke [DL: this must remain a temporary fix! needs to be redone after 0.99.23] Signed-off-by: David Lamparter --- lib/prefix.h | 9 +++++++++ ospfd/ospf_lsa.c | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/prefix.h b/lib/prefix.h index 9ef70ff50c..45889e0862 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -52,6 +52,7 @@ struct prefix struct in_addr adv_router; } lp; u_char val[8]; + uintptr_t ptr; } u __attribute__ ((aligned (8))); }; @@ -89,6 +90,14 @@ struct prefix_rd u_char val[8] __attribute__ ((aligned (8))); }; +/* Prefix for a generic pointer */ +struct prefix_ptr +{ + u_char family; + u_char prefixlen; + uintptr_t prefix __attribute__ ((aligned (8))); +}; + /* helper to get type safety/avoid casts on calls * (w/o this, functions accepting all prefix types need casts on the caller * side, which strips type safety since the cast will accept any pointer diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 369655163a..0a66b1d4c7 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2903,9 +2903,11 @@ void ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa) { struct route_node *rn; - struct prefix_ls lsa_prefix; + struct prefix_ptr lsa_prefix; - ls_prefix_set (&lsa_prefix, lsa); + lsa_prefix.family = 0; + lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; + lsa_prefix.prefix = (uintptr_t) lsa; if ((rn = route_node_lookup(ospf->maxage_lsa, (struct prefix *)&lsa_prefix))) @@ -2929,7 +2931,7 @@ ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa) void ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) { - struct prefix_ls lsa_prefix; + struct prefix_ptr lsa_prefix; struct route_node *rn; /* When we saw a MaxAge LSA flooded to us, we put it on the list @@ -2942,12 +2944,18 @@ ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) return; } - ls_prefix_set (&lsa_prefix, lsa); + lsa_prefix.family = 0; + lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; + lsa_prefix.prefix = (uintptr_t) lsa; + if ((rn = route_node_get (ospf->maxage_lsa, (struct prefix *)&lsa_prefix)) != NULL) { if (rn->info != NULL) { + if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) + zlog_debug ("LSA[%s]: found LSA (%p) in table for LSA %p %d", + dump_lsa_key (lsa), rn->info, lsa, lsa_prefix.prefixlen); route_unlock_node (rn); } else -- 2.39.5