forked from Mirror/frr
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 <ls-id, adv-router> 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 <pmohapat@cumulusnetworks.com> [CF: Use CHAR_BIT; use uintptr_t; use sizeof(field) instead of sizeof(type)] Signed-off-by: Christian Franke <chris@opensourcerouting.org> [DL: this must remain a temporary fix! needs to be redone after 0.99.23] Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
8afee5c172
commit
b4b359a265
|
@ -52,6 +52,7 @@ struct prefix
|
||||||
struct in_addr adv_router;
|
struct in_addr adv_router;
|
||||||
} lp;
|
} lp;
|
||||||
u_char val[8];
|
u_char val[8];
|
||||||
|
uintptr_t ptr;
|
||||||
} u __attribute__ ((aligned (8)));
|
} u __attribute__ ((aligned (8)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,6 +90,14 @@ struct prefix_rd
|
||||||
u_char val[8] __attribute__ ((aligned (8)));
|
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
|
/* helper to get type safety/avoid casts on calls
|
||||||
* (w/o this, functions accepting all prefix types need casts on the caller
|
* (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
|
* side, which strips type safety since the cast will accept any pointer
|
||||||
|
|
|
@ -2903,9 +2903,11 @@ void
|
||||||
ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
|
ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
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,
|
if ((rn = route_node_lookup(ospf->maxage_lsa,
|
||||||
(struct prefix *)&lsa_prefix)))
|
(struct prefix *)&lsa_prefix)))
|
||||||
|
@ -2929,7 +2931,7 @@ ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
|
||||||
void
|
void
|
||||||
ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
|
ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct prefix_ls lsa_prefix;
|
struct prefix_ptr lsa_prefix;
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
|
|
||||||
/* When we saw a MaxAge LSA flooded to us, we put it on the list
|
/* 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;
|
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,
|
if ((rn = route_node_get (ospf->maxage_lsa,
|
||||||
(struct prefix *)&lsa_prefix)) != NULL)
|
(struct prefix *)&lsa_prefix)) != NULL)
|
||||||
{
|
{
|
||||||
if (rn->info != 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);
|
route_unlock_node (rn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue