ripd: poison redistributed routes on route-map change#22370
Conversation
Greptile SummaryThis PR fixes issue #22360 by introducing a "policy withdraw" mechanism for RIP redistributed routes: when a redistribution route-map is changed, previously advertised routes that are now denied by the new map are sent with metric=16 (poison reverse) instead of being silently dropped from future updates.
Confidence Score: 3/5The withdrawal logic works correctly in the common case, but marks all routes of the given type for poisoning — including ones that were always filtered and never advertised — causing unnecessary metric=16 messages to peers. Additionally, if a periodic update races ahead of the triggered update, the POLICY_WITHDRAW flag is never cleared and metric=16 keeps appearing in every subsequent periodic update for the affected routes. The core mechanism is sound and the normal path works correctly. However, the unconditional marking of all type-X routes without pre-filtering against the previous route-map means peers receive spurious withdrawal messages for routes they never knew about, and the flag-persistence edge case can cause metric=16 to appear in every periodic update until the entry is replaced or times out. ripd/ripd.c — specifically rip_redistribute_policy_update (marking logic) and the interaction between rip_clear_changed_flag and the triggered-update suppression path in rip_update. Important Files Changed
Sequence DiagramsequenceDiagram
participant CLI as CLI/NETCONF
participant NB as Northbound
participant RIPD as ripd
participant EVQ as Event Queue
participant Zebra as Zebra
CLI->>NB: set redistribute route-map new-map
NB->>RIPD: ripd_instance_redistribute_route_map_modify
RIPD->>RIPD: "update rip->redist[type].route_map to new map"
RIPD->>RIPD: "rip_redistribute_policy_update() mark ALL type-X routes RIP_RTF_CHANGED | RIP_RTF_POLICY_WITHDRAW"
RIPD->>EVQ: event_add_event(rip_triggered_update)
NB->>RIPD: ripd_instance_redistribute_apply_finish
RIPD->>Zebra: ZEBRA_REDISTRIBUTE_ADD async
EVQ-->>RIPD: rip_triggered_update fires
RIPD->>RIPD: rip_update_process(rip_changed_route)
Note over RIPD: route-map DENIES + POLICY_WITHDRAW: metric_out=16 send RTE
Note over RIPD: route-map PERMITS: advertised normally
RIPD->>RIPD: rip_clear_changed_flag() clears both flags
Zebra-->>RIPD: re-sends type-X routes async
RIPD->>RIPD: rip_redistribute_add() rip_ecmp_replace() set RIP_RTF_CHANGED
RIPD->>EVQ: event_add_event(rip_triggered_update)
EVQ-->>RIPD: 2nd triggered update fires
Note over RIPD: route-map DENIES POLICY_WITHDRAW not set continue route omitted
|
01696c7 to
94b293d
Compare
| tmp.tag_out = tmp.tag; | ||
| tmp.nexthop_out.s_addr = 0; | ||
|
|
||
| if (route_map_apply(rip->redist[type].route_map.map, |
There was a problem hiding this comment.
why not just set a flag on the rinfo when the route map is applied once every 30 seconds on what choice was made. Then you just compare the old value to the new route map application and do the right thing. Then we don't need this loop at all.
riw777
left a comment
There was a problem hiding this comment.
Signed off by needs to be fixed. Waiting on @donaldsharp 's comments as well.
94b293d to
b4e4394
Compare
|
Sign-off email fixed ( |
b4e4394 to
504cc56
Compare
|
Thanks @donaldsharp, reworked along the lines you suggested. Dropped the separate Since the comparison happens on the regular update where the route-map is already applied, there's no extra loop and no config-time trigger. This also resolves the two greptile notes: routes denied from the start are never flagged (no spurious metric 16), and there is no separate withdraw flag that could persist across a suppressed triggered update. |
|
Tick the box to add this pull request to the merge queue (same as
|
|
Can you fix the linter errors? :-) |
When a redistribution route-map is changed so that a previously advertised route is now denied, ripd silently stopped advertising the route, leaving neighbors with a stale entry until it timed out. Record on each route whether it was advertised under the current redistribute policy (RIP_RTF_POLICY_ADVERTISED), set when the route passes the route-map during an update. When a later update finds the route now denied, if it was previously advertised send a single metric 16 (poison) so neighbors withdraw it, then clear the flag; routes that were never advertised are simply skipped as before. The decision is re-evaluated on the normal update where the route-map is already applied, so no separate table walk is needed. Closes FRRouting#22360 Signed-off-by: Evelyn0828 <jxshuibei@gmail.com>
504cc56 to
dbf44ca
Compare
|
Fixed the style — applied the frrbot/clang-format suggestion and force-pushed. Thanks @riw777. |
riw777
left a comment
There was a problem hiding this comment.
looks good, will wait a bit to see if @donaldsharp has the time to check his comments and look at this again
When a RIP redistribution route-map is changed, routes advertised under the previous policy need to be withdrawn if the new policy denies them. Mark existing redistributed routes on route-map changes and let the triggered update send metric 16 for denied entries instead of skipping them.
CLOSES #22360