-
Notifications
You must be signed in to change notification settings - Fork 20
Add support for dynamic routing on ipv6 (ospfv3 and ripng) #1577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
saba8814
wants to merge
4
commits into
kernelkit:main
Choose a base branch
from
saba8814:dynamic-routing-on-ipv6
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
7bc0935
routing: add IPv6 dynamic routing (RIPng and OSPFv3)
saba8814 c0138a4
doc: updated RIPng and OSPFv3 documentation
saba8814 9c1ec91
fix: unsupport address-family
saba8814 f636c35
frr: patch OSPFv3 default route loss after ospf6d restart
saba8814 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,8 +7,8 @@ Currently supported YANG models: | |
| | ietf-routing | Base model for all other models | | ||
| | ietf-ipv4-unicast-routing | Static IPv4 unicast routing | | ||
| | ietf-ipv6-unicast-routing | Static IPv6 unicast routing | | ||
| | ietf-ospf | OSPF routing | | ||
| | ietf-rip | RIP routing | | ||
| | ietf-ospf | OSPFv2 and OSPFv3 routing | | ||
| | ietf-rip | RIPv2 and RIPng routing | | ||
| | infix-routing | Infix deviations and extensions | | ||
|
|
||
| The base model, ietf-routing, is where all the other models hook in. It | ||
|
|
@@ -305,6 +305,62 @@ admin@example:/> | |
| </code></pre> | ||
|
|
||
|
|
||
| ## OSPFv3 Routing | ||
|
|
||
| The system also supports OSPF for IPv6, i.e., OSPFv3. It uses the same | ||
| `ietf-ospf` model as OSPFv2, selected by the control plane protocol type | ||
| `ospfv3`. OSPFv3 has no IPv4 interface address to derive a router ID | ||
| from, so an `explicit-router-id` must be set. | ||
|
|
||
| <pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ospfv3 name default ospf</b> | ||
| admin@example:/config/routing/…/ospf/> <b>set explicit-router-id 1.1.1.1</b> | ||
| admin@example:/config/routing/…/ospf/> <b>set area 0.0.0.0 interface e0 enabled</b> | ||
| admin@example:/config/routing/…/ospf/> <b>leave</b> | ||
| admin@example:/> | ||
| </code></pre> | ||
|
|
||
| > [!TIP] | ||
| > Remember to enable [IPv6 forwarding](ip.md#ipv6-forwarding) for all the | ||
| > interfaces you want to route between. | ||
|
|
||
| Areas, interface settings (cost, timers, BFD, `point-to-point`), | ||
| redistribution and default route advertisement work the same way as for | ||
| [OSPFv2](#ospfv2-routing), with the differences listed below. | ||
|
|
||
|
|
||
| ### Differences from OSPFv2 | ||
|
|
||
| OSPFv3 runs on FRR's `ospf6d`, which does not implement every feature | ||
| available for OSPFv2: | ||
|
|
||
| - OSPFv3 carries IPv6 routes only; IPv4-over-OSPFv3 (RFC 5838) is not | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is good to mention though, deviations from standards. |
||
| supported, so there is no `address-family` setting. | ||
| - `explicit-router-id` is required (there is no IPv4 address to derive it | ||
| from). | ||
| - Interface types are limited to `broadcast`, `point-to-point` and | ||
| multicast Point-to-Multipoint (`hybrid`). Non-broadcast interfaces and | ||
| static neighbors are not supported and are rejected by the model. | ||
| - NSSA areas are supported as regular NSSA only; the `summary` flag has no | ||
| effect (no totally-NSSA). Stub areas do support totally-stubby | ||
| (`summary false`). | ||
| - Per-area `default-cost` is not available. | ||
|
|
||
|
|
||
| ### OSPFv3 status | ||
|
|
||
| The CLI mirrors the OSPFv2 commands under `show ipv6 ospf`: | ||
|
|
||
| <pre class="cli"><code>admin@example:/> <b>show ipv6 ospf</b> | ||
| admin@example:/> <b>show ipv6 ospf neighbor</b> | ||
| admin@example:/> <b>show ipv6 ospf interface</b> | ||
| admin@example:/> <b>show ipv6 ospf route</b> | ||
| </code></pre> | ||
|
|
||
| Debug logging is configured under the `ospfv3` protocol `debug` container, | ||
| analogous to OSPFv2. Available categories are `packet`, `ism`, `nsm` and | ||
| `nssa`. | ||
|
|
||
|
|
||
| ## RIP Routing | ||
|
|
||
| The system supports RIP dynamic routing for IPv4, i.e., RIPv2. To enable | ||
|
|
@@ -425,6 +481,51 @@ admin@example:/> | |
| </code></pre> | ||
|
|
||
|
|
||
| ## RIPng Routing | ||
|
|
||
| RIPng is RIP for IPv6. It uses the same `ietf-rip` model as RIPv2, | ||
| selected by the control plane protocol type `ripng`: | ||
|
|
||
| <pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ripng name default rip</b> | ||
| admin@example:/config/routing/…/rip/> <b>set interfaces interface e0</b> | ||
| admin@example:/config/routing/…/rip/> <b>set interfaces interface e1</b> | ||
| admin@example:/config/routing/…/rip/> <b>leave</b> | ||
| admin@example:/> | ||
| </code></pre> | ||
|
|
||
| > [!TIP] | ||
| > Remember to enable [IPv6 forwarding](ip.md#ipv6-forwarding) for all the | ||
| > interfaces you want to route between. | ||
|
|
||
| Passive interfaces, redistribution (`set redistribute connected` / | ||
| `static`) and timers are configured the same way as for | ||
| [RIPv2](#rip-routing), with the differences below. | ||
|
|
||
|
|
||
| ### Differences from RIPv2 | ||
|
|
||
| RIPng runs on FRR's `ripngd`: | ||
|
|
||
| - RIPng has no protocol version, so the per-interface `send-version` and | ||
| `receive-version` settings do not apply. | ||
| - The global `distance` and unicast `neighbor` settings are not supported | ||
| (`ripngd` has no such commands). | ||
| - `set redistribute ospf` redistributes OSPFv3, as there is no OSPFv2 in | ||
| an IPv6 domain. | ||
|
|
||
|
|
||
| ### RIPng status | ||
|
|
||
| RIPng-learned routes appear in the [IPv6 routing table](#ipv6-routing-table): | ||
|
|
||
| <pre class="cli"><code>admin@example:/> <b>show ipv6 route</b> | ||
| </code></pre> | ||
|
|
||
| Debug logging is configured under the `ripng` protocol `debug` container, | ||
| analogous to RIPv2. Available categories are `events`, `packet` and | ||
| `kernel`. | ||
|
|
||
|
|
||
| ## View routing table | ||
|
|
||
| The routing table can be inspected from the operational datastore, XPath | ||
|
|
@@ -500,7 +601,8 @@ Default distances used (lower numeric value wins): | |
| | 0 | Kernel routes, i.e., connected routes | | ||
| | 1 | Static routes | | ||
| | 5 | DHCP routes | | ||
| | 110 | OSPF | | ||
| | 110 | OSPF (OSPFv2 and OSPFv3) | | ||
| | 120 | RIP (RIPv2 and RIPng) | | ||
| | 254 | IPv4LL (ZeroConf) device routes | | ||
| | 255 | Route will not be used or redistributed | | ||
|
|
||
|
|
@@ -527,6 +629,8 @@ The source protocol describes the origin of the route. | |
| | kernel | Added when setting a subnet address on an interface | | ||
| | static | User created, learned from DHCP, or IPv4LL | | ||
| | ospfv2 | Routes learned from OSPFv2 | | ||
| | ospfv3 | Routes learned from OSPFv3 | | ||
| | rip | Routes learned from RIPv2 or RIPng | | ||
|
|
||
| The YANG model *ietf-routing* support multiple ribs but only two are | ||
| currently supported, namely `ipv4` and `ipv6`. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # --log-level debug | ||
| OSPF6D_ARGS="-A 127.0.0.1 -u frr -g frr -f /etc/frr/ospf6d.conf --log syslog" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # --log-level debug | ||
| RIPNGD_ARGS="-A 127.0.0.1 -u frr -g frr --log syslog" |
4 changes: 3 additions & 1 deletion
4
package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/ospf6d.conf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| service [2345] log:null <!pid/zebra> ospf6d -A 127.0.0.1 -u frr -g frr -- OSPF IPv6 daemon | ||
| service <!pid/zebra> pid:!/run/frr/ospf6d.pid env:-/etc/default/ospf6d \ | ||
| [2345] ospf6d $OSPF6D_ARGS \ | ||
| -- OSPF IPv6 daemon |
1 change: 0 additions & 1 deletion
1
package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/ripng.conf
This file was deleted.
Oops, something went wrong.
3 changes: 3 additions & 0 deletions
3
package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/ripngd.conf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| service <pid/zebra> pid:!/run/frr/ripngd.pid env:-/etc/default/ripngd \ | ||
| [2345] ripngd $RIPNGD_ARGS \ | ||
| -- RIPng daemon |
96 changes: 96 additions & 0 deletions
96
patches/frr/10.5.4/0004-ospf6d-bypass-MinLSArrival-for-self-originated-MaxAge.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| From e77f915ebd328e913669054996a22e11fbd60a6c Mon Sep 17 00:00:00 2001 | ||
| From: harini <hnattamaisub@nvidia.com> | ||
| Date: Thu, 28 May 2026 21:45:05 -0700 | ||
| Subject: [PATCH] ospf6d: bypass MinLSArrival for self-originated MaxAge LSAs | ||
|
|
||
| [This was part of PR 22103] | ||
|
|
||
| Deployment / how this surfaced: | ||
| The failure was observed in an EVPN VXLAN L2VPN setup with the | ||
| following ingredients: | ||
| - Several VTEP nodes (TOR / border-TOR roles) terminating EVPN | ||
| type-2/3/5 routes. | ||
| - iBGP EVPN sessions between VTEPs, sourced from each VTEP's | ||
| IPv6 loopback (multi-hop iBGP through one or more spines). | ||
| - OSPFv3 (IPv6) as the underlay, advertising the VTEP loopback | ||
| /128s area-wide via Intra-Area-Prefix-LSAs. | ||
|
|
||
| Trigger is a plain `systemctl stop frr` followed shortly by | ||
| `systemctl start frr` on one VTEP X (the "DUT"). After the restart, | ||
| ospf6d on X reforms adjacencies but never re-injects the remote VTEP | ||
| loopback /128s into zebra's RIB. With those loopbacks missing, | ||
| multi-hop iBGP nexthop resolution on X fails (BGP "nexthop_set | ||
| failed"), EVPN L2VPN sessions to X stay down, and remote bridging / | ||
| routing traffic to hosts behind X is indefinitely broken. | ||
|
|
||
| Rootcause and fix: | ||
| After the restart X re-originates its self LSAs from | ||
| InitialSequenceNumber (0x80000001). Meanwhile X's OSPFv3 peers | ||
| still hold the pre-restart instance at a higher seqnum S, and | ||
| re-flood it back to X at MaxAge as the bounce-back synchronisation | ||
| described in RFC 2328 section 13.4. | ||
|
|
||
| For (self-originated, MaxAge) LSAs that arrive within 1 second | ||
| (MinLSArrival, default 1000 ms) of X's just-installed fresh instance, | ||
| in ospf6_receive_lsa() calls ospf6_lsa_check_min_arrival() | ||
| which returns true and silently drops the bounce-back. This prevents | ||
| ospf6_install_lsa() from running, the self-originated handler | ||
| is never reached, and X never advances its seqnum past S. | ||
| Every peer keeps believing the stale MaxAge S is X's most recent | ||
| LSA, BGP nexthop tracking for X's loopback fails to resolve, and EVPN | ||
| sessions to X never re-establish. | ||
|
|
||
| This issue is rarely reproduces because of timing. | ||
| The race window is exactly MinLSArrival wide. | ||
|
|
||
| Fix: | ||
| Scope of the bypass is intentionally narrow: only (self_originated && | ||
| MaxAge). Ordinary rapid floods from other routers, non-MaxAge | ||
| self-originated LSAs is untouched. | ||
|
|
||
| Signed-off-by: harini <hnattamaisub@nvidia.com> | ||
| Upstream: https://github.com/FRRouting/frr/pull/23005 (stable/10.5 backport of #22103) | ||
| --- | ||
| ospf6d/ospf6_flood.c | 22 +++++++++++++++++----- | ||
| 1 file changed, 17 insertions(+), 5 deletions(-) | ||
|
|
||
| diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c | ||
| index 08b4dde9f71f..3c72d3b25b24 100644 | ||
| --- a/ospf6d/ospf6_flood.c | ||
| +++ b/ospf6d/ospf6_flood.c | ||
| @@ -1001,8 +1001,23 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, | ||
| /* in case we have no database copy */ | ||
| ismore_recent = -1; | ||
|
|
||
| - /* (a) MinLSArrival check */ | ||
| - if (old) { | ||
| + self_originated = (new->header->adv_router == | ||
| + from->ospf6_if->area->ospf6->router_id); | ||
| + | ||
| + /* After any restart of DUT node, receiving self-originated | ||
| + * LSAs with MaxAge from peers within 1 second (MinLSArrival, | ||
| + * default 1000 ms) can make ospf6_lsa_check_min_arrival() | ||
| + * return true, which prevents ospf6_install_lsa() from being | ||
| + * called and results in a sequence-number race. So hardened | ||
| + * the check accordingly to bypass MinLSArrival only for | ||
| + * self-originated MaxAge LSAs. This is in compliance with | ||
| + * RFC 2328 §13.4. | ||
| + */ | ||
| + if (old && self_originated && OSPF6_LSA_IS_MAXAGE(new)) { | ||
| + if (IS_OSPF6_DEBUG_FLOODING || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header->type)) | ||
| + zlog_debug("Bypassing MinLSArrival for self-originated MaxAge LSA %s (RFC 2328 13.4)", | ||
| + new->name); | ||
| + } else if (old) { | ||
| if (ospf6_lsa_check_min_arrival(old, from)) { | ||
| ospf6_lsa_delete(new); | ||
| return; /* examin next lsa */ | ||
| @@ -1019,9 +1034,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, | ||
| if (old) | ||
| ospf6_flood_clear(old); | ||
|
|
||
| - self_originated = (new->header->adv_router | ||
| - == from->ospf6_if->area->ospf6->router_id); | ||
| - | ||
| /* Received non-self-originated Grace LSA. */ | ||
| if (IS_GRACE_LSA(new) && !self_originated) { | ||
| struct ospf6 *ospf6; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation detail, not for user facing documentation. Should describe what infix supoorts, not FRR.