Skip to content

ospfd: prevent stale LSA from corrupting local OSPF DB after reboot - #20601

Merged
riw777 merged 1 commit into
FRRouting:masterfrom
Jafaral:fix-ospf-stale-lsa
May 22, 2026
Merged

ospfd: prevent stale LSA from corrupting local OSPF DB after reboot#20601
riw777 merged 1 commit into
FRRouting:masterfrom
Jafaral:fix-ospf-stale-lsa

Conversation

@Jafaral

@Jafaral Jafaral commented Jan 26, 2026

Copy link
Copy Markdown
Member

Ensure local LSA's have the highest sequence number and neighbors are refreshed in the event a stale LSA is detected.

Current behavior assuming we have two ospf routers: R1 <–> R2

  • R1 and R2 are ospf neighbors
  • R1 has a summary route being advertised to R2 This summary route has some LSA sequence number that is higher than 1

At this point everything is working fine. But then:

  • R1 reboots
  • R1 and R2 re-establish ospf neighborship
  • R2 sends R1 the summary route with R1 as the advertising router
  • R1 installs this summary route with the higher sequence number. It will also set all the flags from R1, including the LSA_RECEIVED flag. This prevents subsequent LSA refresh events from firing
  • The summary route eventually times out (age 3600) and it uninstalled on R2
  • R1 never refreshes the summary route. It reaches age 3600, but never gets deleted

Expected behavior:

  • R1 should override R2's LSA with R1's router-id

@Jafaral

Jafaral commented Jan 26, 2026

Copy link
Copy Markdown
Member Author

@Mergifyio backport stable/10.5 stable/10.4

@mergify

mergify Bot commented Jan 26, 2026

Copy link
Copy Markdown

backport stable/10.5 stable/10.4

🟠 Waiting for conditions to match

Details
  • merged [πŸ“Œ backport requirement]

@greptile-apps

greptile-apps Bot commented Jan 26, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds detection of stale self-originated LSAs after a reboot and handles them per RFC 2328 Β§13.4: if no local copy exists (current == NULL), the received LSA is MaxAge-flooded to flush it from the domain; if a local copy with a lower sequence number exists, the sequence number is bumped and a fresh instance is immediately flooded.

  • current == NULL path: sends an ACK, removes the entry from the LS request list, stamps MaxAge on the received LSA, and intentionally falls through to the normal step-(5) code path so ospf_flood installs and re-floods the MaxAge LSA; ospf_process_self_originated_lsa is then invoked, which schedules ABR-task / router-LSA re-origination as appropriate.
  • else if (ospf_lsa_more_recent(lsa, current) > 0) path: sets current->data->ls_seqnum to the received value so that ospf_lsa_refresh produces a new instance with stale_seq + 1, sends an immediate ACK, and discards the stale LSA; the flooding inside ospf_lsa_refresh also clears the stale entry from the neighbor's LS-request list via ospf_flood_through_interface.

Confidence Score: 4/5

The fix is RFC 2328 Β§13.4 compliant and addresses the described reboot scenario correctly; the only findings are minor code clarity issues.

The core logic β€” MaxAge-flooding when no local copy exists, and bumping the sequence number and refreshing when a local copy is present β€” follows the RFC correctly. The current == NULL fall-through correctly reaches ospf_process_self_originated_lsa via ospf_flood, the LS request list is cleaned up in both branches, and assertions inside ospf_lsa_refresh are safe because any installed self-originated LSA will have OSPF_LSA_SELF set by ospf_lsa_is_self_originated. The two findings are a redundant unreachable continue and a missing fall-through comment.

ospfd/ospf_packet.c β€” the new stale-LSA detection block around lines 2015–2069.

Important Files Changed

Filename Overview
ospfd/ospf_packet.c Adds pre-step-5 self-originated stale LSA detection; logic is RFC-compliant but the else if branch has an unreachable continue after DISCARD_LSA, and the fall-through in the current == NULL branch lacks an explicit intent comment.

Sequence Diagram

sequenceDiagram
    participant R1 as R1 (rebooted)
    participant R2 as R2 (neighbor)

    Note over R1,R2: R1 reboots and re-establishes adjacency

    R2->>R1: "DBD (stale LSA seq=5, adv_router=R1)"
    R1->>R2: LS Request

    alt "current == NULL"
        R2->>R1: "LS Update (seq=5)"
        Note over R1: Set MaxAge, ACK, remove from request list
        Note over R1: Fall through to step-5 ospf_flood()
        R1->>R2: "LS Update (seq=5, MaxAge) flush"
        Note over R1: ospf_process_self_originated_lsa schedules re-origination
    else "current != NULL and lsa.seq > current.seq"
        R2->>R1: "LS Update (seq=5)"
        Note over R1: current.ls_seqnum=5, ospf_lsa_refresh() -> seq=6
        R1->>R2: "LS Update (seq=6) via flooding"
        R1->>R2: LS ACK (direct)
        Note over R1: DISCARD stale LSA
    end
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
ospfd/ospf_packet.c:2067
**Unreachable `continue` after `DISCARD_LSA`**

The `DISCARD_LSA` macro already ends with its own `continue` statement (see the macro definition at line 1816), so the `continue` on this line is never reached. It can be removed.

### Issue 2 of 2
ospfd/ospf_packet.c:2046-2047
**Intentional fall-through should be documented**

After `LS_AGE_SET(lsa, OSPF_LSA_MAXAGE)`, there is no `continue`, so execution falls through to the step-(5) block at line 2079. This is intentional: `ospf_flood` will install and re-flood the MaxAge LSA, and `ospf_process_self_originated_lsa` will then schedule re-origination. A short `/* fall through: ospf_flood() below will re-flood the MaxAge LSA */` comment would make the intent clear and avoid the appearance of a missing `continue`.

Reviews (6): Last reviewed commit: "ospfd: prevent stale LSA from corrupting..." | Re-trigger Greptile

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread ospfd/ospf_packet.c Outdated
Comment thread ospfd/ospf_packet.c Outdated
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from b1ec3b5 to 4a49e85 Compare January 27, 2026 05:23
@github-actions github-actions Bot added size/M and removed size/S labels Jan 27, 2026
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from 4a49e85 to 303d4c5 Compare January 27, 2026 05:26
@riw777
riw777 self-requested a review January 27, 2026 16:25
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from 303d4c5 to e86c50c Compare January 28, 2026 06:08
@Jafaral
Jafaral marked this pull request as draft January 28, 2026 06:15
@mwinter-osr

Copy link
Copy Markdown
Member

@greptileai review this draft

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread ospfd/ospf_packet.c Outdated
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch 2 times, most recently from 4636540 to 14553eb Compare February 1, 2026 20:45
@Jafaral

Jafaral commented Feb 1, 2026

Copy link
Copy Markdown
Member Author

@greptile review

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread ospfd/ospf_packet.c
Comment thread ospfd/ospf_packet.c Outdated
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch 2 times, most recently from 9108394 to 7ca05d5 Compare February 2, 2026 03:03
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from 7ca05d5 to 82738c5 Compare March 6, 2026 16:24
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from 82738c5 to aade230 Compare March 15, 2026 05:22
@mergify

mergify Bot commented May 13, 2026

Copy link
Copy Markdown

backport stable/10.5 stable/10.4

βœ… Backports have been created

Details

@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from aade230 to 294e030 Compare May 13, 2026 03:44
@Jafaral

Jafaral commented May 13, 2026

Copy link
Copy Markdown
Member Author

@greptile review

@riw777 riw777 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@riw777

riw777 commented May 20, 2026

Copy link
Copy Markdown
Member

ci failures look related ... need to be cleaned up ...

@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch 2 times, most recently from 0693321 to e3a5a0a Compare May 22, 2026 03:58
Ensure local LSA's have the highest sequence number and neighbors
are refreshed in the event a stale LSA is detected.

Current behavior assuming we have two ospf routers: R1 <–> R2

- R1 and R2 are ospf neighbors
- R1 has a summary route being advertised to R2
  This summary route has some LSA sequence number that is higher than 1

At this point everything is working fine. But then:

- R1 reboots
- R1 and R2 re-establish ospf neighborship
- R2 sends R1 the summary route with R1 as the advertising router
- R1 installs this summary route with the higher sequence number.
  It will also set all the flags from R1, including the LSA_RECEIVED flag.
  This prevents subsequent LSA refresh events from firing
- The summary route eventually times out (age 3600) and it
  uninstalled on R2
- R1 never refreshes the summary route. It reaches age 3600,
  but never gets deleted

Expected behavior:
- R1 should override R2's LSA with R1's router-id

Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
@Jafaral
Jafaral force-pushed the fix-ospf-stale-lsa branch from e3a5a0a to e955c07 Compare May 22, 2026 04:03
@Jafaral

Jafaral commented May 22, 2026

Copy link
Copy Markdown
Member Author

@greptile review

@Jafaral

Jafaral commented May 22, 2026

Copy link
Copy Markdown
Member Author

@Mergifyio backport stable/10.6

@mergify

mergify Bot commented May 22, 2026

Copy link
Copy Markdown

backport stable/10.6

βœ… Backports have been created

Details

@Jafaral
Jafaral marked this pull request as ready for review May 22, 2026 04:23
@riw777
riw777 merged commit ba4ec5a into FRRouting:master May 22, 2026
23 checks passed
Jafaral added a commit that referenced this pull request May 25, 2026
ospfd: prevent stale LSA from corrupting local OSPF DB after reboot (backport #20601)
@Jafaral
Jafaral deleted the fix-ospf-stale-lsa branch May 29, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants