From 45ec3a40311a336a50e44e3328f421926e08a577 Mon Sep 17 00:00:00 2001 From: Enke Chen Date: Wed, 29 Jul 2026 09:55:58 -0700 Subject: [PATCH 1/2] ospfd: refresh external LSAs when forwarding-address-self changes When `forwarding-address-self` is configured after `redistribute`, the external LSAs that were already originated do not reflect the new forwarding address setting. This causes the LSAs to have the actual nexthop as the forwarding address instead of 0.0.0.0. Fix this by scheduling an ASBR redistribution update to refresh all external LSAs whenever the `forwarding-address-self` setting is changed. Fixes: ospf_forwarding_address_self topotest failure Signed-off-by: Enke Chen --- ospfd/ospf_vty.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index defc1763a0ec..4d80201b0888 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -9745,11 +9745,14 @@ DEFPY (ospf_forwarding_address_self, "Set forwarding address to self for external LSAs\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + bool new_value = !no; - if (no) - ospf->forwarding_address_self = false; - else - ospf->forwarding_address_self = true; + if (ospf->forwarding_address_self != new_value) { + ospf->forwarding_address_self = new_value; + + /* Refresh all external LSAs to apply the new config. */ + ospf_schedule_asbr_redist_update(ospf); + } return CMD_SUCCESS; } From dbb4db25addb1aa42a8262f50439d4436b62bc69 Mon Sep 17 00:00:00 2001 From: Enke Chen Date: Wed, 29 Jul 2026 23:54:03 -0700 Subject: [PATCH 2/2] ospfd: fix NSSA LSA refresh to use current forwarding address When `forwarding-address-self` changes, the scheduled ASBR redistribution update triggers ospf_nssa_lsa_refresh() for existing Type-7 LSAs. However, ospf_nssa_lsa_refresh() was preserving the forwarding address from the old LSA, overriding the newly computed value that respects the current `forwarding-address-self` setting. Fix this by applying the same NSSA forwarding address logic used during origination (ospf_nssa_lsa_originate): - Use the newly computed forwarding address from ospf_external_lsa_new() - Only apply the NSSA interface address fallback when the P-bit is set (per RFC 3101, Type-7 LSAs without P-bit may have zero forwarding address) - Discard the LSA if P-bit is set but no NSSA interface address is available Also fix a pre-existing issue where failed refresh would leave the old LSA orphaned in the LSDB (unregistered from refresh but still advertised with stale data). Now flush the old LSA on any refresh failure. Signed-off-by: Enke Chen --- ospfd/ospf_lsa.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 18591ab558c0..eb7dac6f4b23 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2436,7 +2436,7 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area, { struct ospf *ospf = area->ospf; struct ospf_lsa *new; - struct as_external_lsa *extlsa_old, *extlsa_new; + struct as_external_lsa *extlsa_new; /* Delete LSA from neighbor retransmit-list. */ ospf_ls_retransmit_delete_nbr_as(ospf, lsa); @@ -2450,18 +2450,37 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area, zlog_debug( "LSA[Type7:%pI4]: Could not originate NSSA-LSA", &ei->p.prefix); + ospf_lsa_flush_area(lsa, area); return NULL; } new->data->type = OSPF_AS_NSSA_LSA; new->data->ls_seqnum = lsa_seqnum_increment(lsa); new->area = area; - /* Preserve the NP bit and forwarding address. */ + /* Preserve the NP bit. */ if (CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) SET_FLAG(new->data->options, OSPF_OPTION_NP); - extlsa_old = (struct as_external_lsa *)lsa->data; + + /* + * Set forwarding address for NSSA LSA. Per RFC 3101, if the P-bit + * is set and the newly computed address is 0, use an NSSA interface + * address. Without the P-bit, a zero forwarding address is valid. + */ extlsa_new = (struct as_external_lsa *)new->data; - extlsa_new->e[0].fwd_addr = extlsa_old->e[0].fwd_addr; + if (CHECK_FLAG(new->data->options, OSPF_OPTION_NP) && + extlsa_new->e[0].fwd_addr.s_addr == INADDR_ANY) + extlsa_new->e[0].fwd_addr = ospf_get_nssa_ip(area); + + /* P-bit LSAs must have a non-zero forwarding address. */ + if (CHECK_FLAG(new->data->options, OSPF_OPTION_NP) && + extlsa_new->e[0].fwd_addr.s_addr == INADDR_ANY) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("LSA[Type-7:%pI4]: Could not refresh, no NSSA interface address", + &new->data->id); + ospf_lsa_discard(new); + ospf_lsa_flush_area(lsa, area); + return NULL; + } /* Install newly created LSA into Type-7 LSDB. */ ospf_lsa_install(ospf, NULL, new);