mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 20:55:25 +00:00
ospfd: fix flushing of Grace-LSAs on broadcast interfaces
The ospfd opaque LSA infrastruture has an issue where it can't store different versions of the same Type-9 LSA for different interfaces. When flushing the self-originated Grace-LSAs upon exiting from the GR mode, the code was looking up the single self-originated Grace-LSA from the LSDB, setting its age to MaxAge and sending it out on all interfaces. The problem is that Grace-LSAs sent on broadcast interfaces have their own unique "IP interface address" TLV that is used to identify the restarting router. That way, just reusing the same Grace-LSA for all interfaces doesn't work. Fix this by generating a new Grace-LSA with its age manually set to MaxAge whenever one needs to be flushed. This will allow the "IP interface address" TLV to be set correctly and make GR work even in the presence of multiple broadcast interfaces. In the long term, the opaque LSA infrastructure should be updated to support Type-9 link-local LSAs correctly so that we don't need to resort to hacks like this. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
38e7e55306
commit
4a0167fee5
@ -150,7 +150,7 @@ static struct ospf_lsa *ospf_gr_lsa_new(struct ospf_interface *oi)
|
||||
}
|
||||
|
||||
/* Originate and install Grace-LSA for a given interface. */
|
||||
static void ospf_gr_lsa_originate(struct ospf_interface *oi)
|
||||
static void ospf_gr_lsa_originate(struct ospf_interface *oi, bool maxage)
|
||||
{
|
||||
struct ospf_lsa *lsa, *old;
|
||||
|
||||
@ -164,6 +164,9 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi)
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxage)
|
||||
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
|
||||
|
||||
/* Find the old LSA and increase the seqno. */
|
||||
old = ospf_gr_lsa_lookup(oi->ospf, oi->area);
|
||||
if (old)
|
||||
@ -183,37 +186,6 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi)
|
||||
ospf_flood_through_interface(oi, NULL, lsa);
|
||||
}
|
||||
|
||||
/* Flush a given self-originated Grace-LSA. */
|
||||
static struct ospf_lsa *ospf_gr_flush_grace_lsa(struct ospf_interface *oi,
|
||||
struct ospf_lsa *old)
|
||||
{
|
||||
struct ospf_lsa *lsa;
|
||||
|
||||
if (ospf_interface_neighbor_count(oi) == 0)
|
||||
return NULL;
|
||||
|
||||
if (IS_DEBUG_OSPF_GR)
|
||||
zlog_debug(
|
||||
"GR: flushing self-originated Grace-LSAs [interface %s]",
|
||||
oi->ifp->name);
|
||||
|
||||
lsa = ospf_lsa_dup(old);
|
||||
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
|
||||
lsa->data->ls_seqnum = lsa_seqnum_increment(lsa);
|
||||
|
||||
/* Install updated LSA into LSDB. */
|
||||
if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) {
|
||||
zlog_warn("%s: ospf_lsa_install() failed", __func__);
|
||||
ospf_lsa_unlock(&lsa);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Flood the LSA through out the interface */
|
||||
ospf_flood_through_interface(oi, NULL, lsa);
|
||||
|
||||
return lsa;
|
||||
}
|
||||
|
||||
/* Flush all self-originated Grace-LSAs. */
|
||||
static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
|
||||
{
|
||||
@ -221,7 +193,6 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
|
||||
struct listnode *anode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
|
||||
struct ospf_lsa *lsa;
|
||||
struct ospf_interface *oi;
|
||||
struct listnode *inode;
|
||||
|
||||
@ -230,15 +201,8 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
|
||||
"GR: flushing self-originated Grace-LSAs [area %pI4]",
|
||||
&area->area_id);
|
||||
|
||||
lsa = ospf_gr_lsa_lookup(ospf, area);
|
||||
if (!lsa) {
|
||||
zlog_warn("%s: Grace-LSA not found [area %pI4]",
|
||||
__func__, &area->area_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi))
|
||||
ospf_gr_flush_grace_lsa(oi, lsa);
|
||||
ospf_gr_lsa_originate(oi, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,7 +714,7 @@ static void ospf_gr_prepare(void)
|
||||
|
||||
/* Send a Grace-LSA to all neighbors. */
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi))
|
||||
ospf_gr_lsa_originate(oi);
|
||||
ospf_gr_lsa_originate(oi, false);
|
||||
|
||||
/* Record end of the grace period in non-volatile memory. */
|
||||
ospf_gr_nvm_update(ospf);
|
||||
|
Loading…
Reference in New Issue
Block a user