Skip to content

bgpd: bmp: don't prepend local-AS to AS_PATH in BMP updates - #21815

Merged
eqvinox merged 2 commits into
FRRouting:masterfrom
kalash-nexthop:bmp-no-local-as-prepend
May 26, 2026
Merged

bgpd: bmp: don't prepend local-AS to AS_PATH in BMP updates#21815
eqvinox merged 2 commits into
FRRouting:masterfrom
kalash-nexthop:bmp-no-local-as-prepend

Conversation

@kalash-nexthop

Copy link
Copy Markdown

bgpd: bmp: don't prepend local-AS to AS_PATH in BMP updates

BMP Route Monitoring messages for monitored routes carried an AS_PATH
with the local AS prepended, as if the route were being re-advertised
outbound. Observed with a peer in AS 40001 advertising 100.100.100.1/32
to a router in AS 40002:

"as_path":[40002,40001], "as_path_count":2, "peer_asn":40001

The collector expected AS_PATH=[40001] -- the value as received from
the peer -- but saw [40002,40001] because the local AS was prepended
on its way out to the collector.

Root cause: bmp_update() in bgp_bmp.c reuses bgp_packet_attribute(),
the outbound attribute serializer, which performs peer-specific outbound
transformations on AS_PATH (prepend peer->local_as for eBGP, confed-seq
handling, change-local-as). These are correct for sending an UPDATE to
a peer, but BMP is a reporting channel -- pre-policy, post-policy, and
loc-rib must all emit the AS_PATH as stored (received / selected),
never with the outbound local-AS prepended.

Fix: add a bool for_bmp parameter to bgp_packet_attribute(). When
true:

  • Skip the peer-sort-based AS_PATH transformations and emit
    attr->aspath as-is (no local-AS prepend, no confed-seq
    manipulation).

  • Force 32-bit ASN encoding regardless of the peer's AS4 capability
    state. This is needed for loc-rib re-dumps after a VRF/peer flap:
    peer->cap can be momentarily cleared while the session
    renegotiates, which would otherwise cause aspath_put() to emit
    16-bit AS_PATH segments. Modern BMP collectors always parse ASNs as
    32-bit, so a 16-bit segment produces a byte-level parse error and
    the collector disconnects, losing all subsequent peer-up / peer-down
    / route-monitor messages.

bmp_update() passes for_bmp=true (covers pre-policy, post-policy,
and loc-rib). The outbound callers in bgp_updgrp_packet.c pass false
to keep their current behaviour.

Also update the bgp_bmp topotest expected JSON files for all three
modes: previously they encoded the prepended local-AS ("65501 65502"
where 65501 is the local AS); now they expect the raw AS_PATH
"65502" as received from the peer in AS 65502.

@greptile-apps

greptile-apps Bot commented Apr 29, 2026

Copy link
Copy Markdown

Greptile Summary

Fixes a long-standing correctness bug in BMP Route Monitoring: bgp_packet_attribute() was applying outbound eBGP/confed AS_PATH transformations (local-AS prepend, confed-seq) to BMP messages, causing collectors to see a modified AS_PATH instead of the stored received path. The fix adds a bool for_bmp parameter that suppresses those transformations and forces 32-bit AS encoding (guarding against a secondary disconnection bug when a peer's AS4 capability is transiently cleared). All three call sites are correctly updated, and the topotest expected JSON files are aligned with the corrected behaviour across pre-policy, post-policy, and loc-rib modes.

Confidence Score: 4/5

Safe to merge; the fix is correct, all callers are updated, and memory management is unaffected.

Only P2 findings (a slightly inaccurate inline comment). Core logic, memory ownership, and the for_bmp guard are all correct. Score held at 4 rather than 5 due to the minor comment inaccuracy.

bgpd/bgp_attr.c β€” the new inline comment at line ~5363 overstates that Adj-RIB-In is the only BMP mode FRR supports.

Important Files Changed

Filename Overview
bgpd/bgp_attr.c Adds for_bmp parameter to bgp_packet_attribute(); when true, forces 32-bit AS encoding and skips all peer-sort-based AS_PATH transformations (eBGP local-AS prepend, confed-seq). Memory management is correct β€” the existing aspath != attr->aspath guard at line 5704 handles cleanup safely for all branches including the new for_bmp=true path.
bgpd/bgp_attr.h Function declaration updated to add bool for_bmp parameter, matching the implementation change in bgp_attr.c.
bgpd/bgp_bmp.c Passes for_bmp=true to bgp_packet_attribute() so BMP Route Monitoring messages emit the AS_PATH as stored, without outbound eBGP/confed-seq transformations.
bgpd/bgp_updgrp_packet.c Both bgp_packet_attribute() call sites updated to pass for_bmp=false, preserving existing outbound BGP UPDATE behaviour.
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json Expected AS_PATH updated from "65501 65502" to "65502" to reflect the raw received path without the local-AS prepend.
tests/topotests/bgp_bmp/bmp1vrf/bmp-update-pre-policy-step1.json VRF-specific expected AS_PATH corrected from "65501 65502" to "65502" for the pre-policy mode, consistent with all other BMP step files.

Sequence Diagram

sequenceDiagram
    participant Peer as BGP Peer (AS 65502)
    participant FRR as FRR Router (AS 65501)
    participant BMP as BMP Collector

    Peer->>FRR: UPDATE [AS_PATH=65502] prefix=172.31.0.15/32
    FRR->>FRR: Store attr->aspath = [65502]

    note over FRR,BMP: Before fix: bmp_update() called bgp_packet_attribute()<br/>with no for_bmp flag β€” eBGP path applied local-AS prepend
    FRR--xBMP: BMP Route Monitor [AS_PATH=65501 65502] ❌

    note over FRR,BMP: After fix: bmp_update() passes for_bmp=true
    FRR->>BMP: BMP Route Monitor [AS_PATH=65502] βœ… (as stored)

    note over FRR: Outbound BGP UPDATE to other peers unchanged
    FRR->>Peer: UPDATE [AS_PATH=65501 65502] (for_bmp=false, normal eBGP prepend)
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: bgpd/bgp_attr.c
Line: 5363-5371

Comment:
**Inaccurate comment: FRR already emits loc-rib messages**

The comment says "BMP Adj-RIB-In monitoring (the only BMP mode FRR currently supports)", but the test-suite changes in this very PR update expected JSON for `loc-rib`, `pre-policy`, and `post-policy` modes β€” meaning FRR already supports at least three BMP table types. Calling it "the only BMP mode" is misleading to future readers and may cause confusion when RFC 8671 Adj-RIB-Out work begins.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "bgpd: bmp: don't prepend local-AS to AS_..." | Re-trigger Greptile

Comment thread bgpd/bgp_attr.c Outdated
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 435b95d to a305dba Compare April 29, 2026 21:47
@donaldsharp

Copy link
Copy Markdown
Member

I see two separate bug fixes, at the very least. Why is this not two commits?

I would also like to see discussion from some of our bgp operators on what they want to do here since this will be a non-backwards compatible change to what is delivered and we need to ensure that this is thought out and that operators have a path forward that makes sense to them.

@kalash-nexthop

Copy link
Copy Markdown
Author

I see two separate bug fixes, at the very least. Why is this not two commits?

I would also like to see discussion from some of our bgp operators on what they want to do here since this will be a non-backwards compatible change to what is delivered and we need to ensure that this is thought out and that operators have a path forward that makes sense to them.

Thanks for looking @donaldsharp . Appreciate the quick feedback.

You are right. While fixing the BMP local-as issue, I had to fix the 32-bit ASN encoding issue in order for the modified tests to pass. So there are exactly two fixes here.

I can split this now. Should have done it like that to begin with, but the local-as path tests in the second PR wouldn't pass without the first change, and I wasn't sure what's the strategy for posting stacked PRs (first time contributor here).

About the backward compatibility concern, is there any action item on me?

@donaldsharp

Copy link
Copy Markdown
Member

I just think I want to discuss this in next weeks tech meeting. We should go over it because it's a new PR that came in during the week. Feel free to join and have the discussion with us.

Comment thread bgpd/bgp_attr.c Outdated
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from a305dba to 69a7b2c Compare May 4, 2026 20:12
@github-actions github-actions Bot added the rebase PR needs rebase label May 4, 2026

@ton31337 ton31337 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.

Please fix frrbot styling issues.

@eqvinox
eqvinox self-requested a review May 5, 2026 15:51
@github-actions github-actions Bot added size/L and removed size/M labels May 5, 2026
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 4bc3402 to c5dcc07 Compare May 5, 2026 16:36
@kalash-nexthop

Copy link
Copy Markdown
Author

Please fix frrbot styling issues.

Done. Thanks.

@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from c5dcc07 to 89b89c3 Compare May 5, 2026 16:40
kalash-nexthop added a commit to nexthop-ai/sonic-buildimage that referenced this pull request May 5, 2026
Add FRR patch backporting the BMP local-AS fix from upstream PR
FRRouting/frr#21815 to the FRR 10.5.1 base
in this repo. See the patch file for the full commit message.

Patch numbered 0108 (master had reached 0107 since the original
0106 number was chosen).
@kemp-rv

kemp-rv commented May 5, 2026

Copy link
Copy Markdown

Happy to see this option go in. I was just about to file a bug report on the same issue, about prepending local AS to BMP monitor messages. I concur with the reading in RFC7854 4271 and 9069. This flag addition should help turn off that prepend behavior for BMP monitor.

kalash-nexthop added a commit to nexthop-ai/sonic-buildimage that referenced this pull request May 5, 2026
Add FRR patch backporting the BMP local-AS fix from upstream PR
FRRouting/frr#21815 to the FRR 10.5.1 base
in this repo. See the patch file for the full commit message.

Patch numbered 0108 (master had reached 0107 since the original
0106 number was chosen).

Signed-off-by: Kalash Nainwal <kalash@nexthop.ai>
@ton31337

ton31337 commented May 6, 2026

Copy link
Copy Markdown
Member

@kalash-nexthop what do you think by adding a new configuration knob to control this (append vs. no-append)? Then we don't need any changes once we have adj-rib-out.

@kalash-nexthop

Copy link
Copy Markdown
Author

@kalash-nexthop what do you think by adding a new configuration knob to control this (append vs. no-append)? Then we don't need any changes once we have adj-rib-out.

@ton31337 A new config knob would still mean either rib-in policy behavior would be wrong or the future rib-out behavior (based on operator's configured value). IMHO we shouldn't leave the behavior here to operator preference.

The current single-arg design already accommodates the future Adj-RIB-Out cleanly, as a future bmp_update_post_policy_adj_rib_out() would call bgp_packet_attribute(... for_bmp=false ...) which would make it fall into the regular eBGP/confed branches, and get the local-AS prepend exactly as the egress packet builder does.

That said, the arg for_bmp might look confusing at that point, and we can rename it to convey its purpose better. I can change it to something like skip_egress_xforms to make it unambiguous (where only adj-rib-in bmp policy would set it to true). What do you think?

@kemp-rv

kemp-rv commented May 7, 2026

Copy link
Copy Markdown

Just to concur, it looks like @kalash-nexthop has everything correct for what we would expect. I like the flag rename suggestion, but any name is fine in my book.

@ton31337

Copy link
Copy Markdown
Member

Please squash these two commits (styling fix + actual fix) into a single one.

@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 89b89c3 to d1fce47 Compare May 19, 2026 18:26
@kalash-nexthop

Copy link
Copy Markdown
Author

Please squash these two commits (styling fix + actual fix) into a single one.

Done. Thanks @ton31337

@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from d1fce47 to 6b1cda1 Compare May 19, 2026 20:47
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch 2 times, most recently from 0b3dbb3 to 43047cb Compare May 21, 2026 02:02
@kalash-nexthop

Copy link
Copy Markdown
Author

Three CI runs in a row have failed on different unrelated tests (bgp_soo, then ospf_rfc4222_dscp, then bgp_conditional_advertisement_track_peer). The same failures are hitting other open PRs β€” #22008, #21992, #21967, #21943 on bgp_soo, and #22009 on bgp_conditional_advertisement_track_peer. This seems to be a CI/test-side flakiness. CI used to pass earlier on this PR before I rebased today. Any advise @ton31337 ?

@ton31337

Copy link
Copy Markdown
Member

bgp soo & friends should have been fixed in master already, so let's see what we have right now.

@eqvinox

eqvinox commented May 21, 2026

Copy link
Copy Markdown
Contributor

Quick update from talking with other BMP people: nobody seems to be entirely sure what the behavior should be in this case, and there is very little practical data.

@kemp-rv

kemp-rv commented May 21, 2026

Copy link
Copy Markdown

Quick update from talking with other BMP people: nobody seems to be entirely sure what the behavior should be in this case, and there is very little practical data.

I'd like to push back on this comment. People at CAIDA noticed this bug at the point it was introduced (years ago). I myself only recently saw the impact when checking on some of the data that RouteViews generates. So there is no confusion on our part. We are seeing the impact of the prepend bug in the data in our system currently.

Let me help you understand a little bit. You have a monitor. It collects BMP Monitor data. It is not pushing traffic around. Adding the asnum of the monitor in the pre-policy, post-policy-in, or loc-rib, as if it were part of a BGP UPDATE msg that came to the peer, makes no sense. So I would again say we are hopeful that the patch in this commit, or the equivalent, goes through.

adj-RIB-out is the only place you could argue for a prepend. And we're not talking about that case here.

@kalash-nexthop

Copy link
Copy Markdown
Author

Three CI runs in a row have failed on different unrelated tests (bgp_soo, then ospf_rfc4222_dscp, then bgp_conditional_advertisement_track_peer). The same failures are hitting other open PRs β€” #22008, #21992, #21967, #21943 on bgp_soo, and #22009 on bgp_conditional_advertisement_track_peer. This seems to be a CI/test-side flakiness. CI used to pass earlier on this PR before I rebased today. Any advise @ton31337 ?

pipeline passes now.

@eqvinox

eqvinox commented May 21, 2026

Copy link
Copy Markdown
Contributor

Quick update from talking with other BMP people: nobody seems to be entirely sure what the behavior should be in this case, and there is very little practical data.

I'd like to push back on this comment. People at CAIDA noticed this bug at the point it was introduced (years ago). I myself only recently saw the impact when checking on some of the data that RouteViews generates. So there is no confusion on our part. We are seeing the impact of the prepend bug in the data in our system currently.

I poked some implementers (and one BMP operator) and you see the result above [for Adj-RIB-out. See end of this comment.] The response was basically "hmm, we never thought about that", to the degree that they didn't even know what their code does. No more and no less. I'm sad to hear that this is causing issues for your data collection.

Let me help you understand a little bit. You have a monitor. It collects BMP Monitor data. It is not pushing traffic around.

Sigh.

The tone here is rather condescending. I know who you are and respect your work, so I'm ignoring that. Still, it's not helpful for the discussion.

FYI: I wrote the original BMP code in FRR. I'm not perfect, my code has bugs, this is one of them. I do, however, understand well enough what BMP is, does, and how it's used.

Adding the asnum of the monitor in the pre-policy, post-policy-in, or loc-rib, as if it were part of a BGP UPDATE msg that came to the peer, makes no sense. So I would again say we are hopeful that the patch in this commit, or the equivalent, goes through.

adj-RIB-out is the only place you could argue for a prepend. And we're not talking about that case here.

You might've noticed I haven't previously commented on this PR. My going around asking people was triggered by the discussion of this PR on our weekly tech call. My understanding from the call was that this PR is for Adj-RIB-out. Funnily enough, this miscommunication might've happened because for Adj-RIB-in I could've answered that right there on the call. It made no sense to me that there'd be a discussion on that.

Anyway. I'm not sure what the uncertainty was that triggered the discussion on the call, I'm going to assume it's resolved.

I do hope we didn't lose a bug report about this (I couldn't find one), but if the CAIDA people knew about this for years and just didn't report it, that's… unfortunate. We can't fix bugs we're not aware of.

@kemp-rv

kemp-rv commented May 21, 2026

Copy link
Copy Markdown

Quick update from talking with other BMP people: nobody seems to be entirely sure what the behavior should be in this case, and there is very little practical data.

I'd like to push back on this comment. People at CAIDA noticed this bug at the point it was introduced (years ago). I myself only recently saw the impact when checking on some of the data that RouteViews generates. So there is no confusion on our part. We are seeing the impact of the prepend bug in the data in our system currently.

I poked some implementers (and one BMP operator) and you see the result above [for Adj-RIB-out. See end of this comment.] The response was basically "hmm, we never thought about that", to the degree that they didn't even know what their code does. No more and no less. I'm sad to hear that this is causing issues for your data collection.

Let me help you understand a little bit. You have a monitor. It collects BMP Monitor data. It is not pushing traffic around.

Sigh.

The tone here is rather condescending. I know who you are and respect your work, so I'm ignoring that. Still, it's not helpful for the discussion.

FYI: I wrote the original BMP code in FRR. I'm not perfect, my code has bugs, this is one of them. I do, however, understand well enough what BMP is, does, and how it's used.

Adding the asnum of the monitor in the pre-policy, post-policy-in, or loc-rib, as if it were part of a BGP UPDATE msg that came to the peer, makes no sense. So I would again say we are hopeful that the patch in this commit, or the equivalent, goes through.
adj-RIB-out is the only place you could argue for a prepend. And we're not talking about that case here.

You might've noticed I haven't previously commented on this PR. My going around asking people was triggered by the discussion of this PR on our weekly tech call. My understanding from the call was that this PR is for Adj-RIB-out. Funnily enough, this miscommunication might've happened because for Adj-RIB-in I could've answered that right there on the call. It made no sense to me that there'd be a discussion on that.

Anyway. I'm not sure what the uncertainty was that triggered the discussion on the call, I'm going to assume it's resolved.

I do hope we didn't lose a bug report about this (I couldn't find one), but if the CAIDA people knew about this for years and just didn't report it, that's… unfortunate. We can't fix bugs we're not aware of.

No issues here. We are nothing but appreciative for all the hard work on the project.

Sorry if that came across as condescending. I was just trying to be brief, and as clear as I could be to avoid any confusion about the thread topic. With the fix being so close to merge, I wanted to make sure that it was clear that there really are people who know what the issue is, and have a use for this particular fix.

Again, we appreciate all the hard work here.

@kalash-nexthop

Copy link
Copy Markdown
Author

Hi @eqvinox, I appreciate the time and effort you spent in soliciting feedback from other bmp folks on this. From our (Nexthop systems) side, this issue is caught while executing a customer testcase, who clearly want the behavior of not prepending local-as to these BMP updates. Sadly, the RFC doesn't explicitly mention this the datapoint that I have here is anecdotal in that sense.

@eqvinox

eqvinox commented May 22, 2026

Copy link
Copy Markdown
Contributor

@kalash-nexthop you said you'd split it in 2 commits, are you still going to do that? Personally it's below my threshold for caring since the 32bit fix is 1 code line, but you did say yes you'll do that πŸ˜ƒ

@eqvinox

eqvinox commented May 22, 2026

Copy link
Copy Markdown
Contributor

Sorry if that came across as condescending. I was just trying to be brief […]

No worries. If anything I was just making sure we don't get a slow creep in the community at large, better to say something on a tiny thing vs. having a big deal later after tone's drifted πŸ˜„

Again, we appreciate all the hard work here.

Thank you! Like I said I appreciate and respect your work as well! Fun fact: I'm writing this while attending RIPE 92, trying to make sure we keep up with the needs the DFZ operator community. The DFZ is hard enough to understand with all the monitoring and analysis tools we have, without them we'd be blundering around in the dark.

@kalash-nexthop

Copy link
Copy Markdown
Author

@kalash-nexthop you said you'd split it in 2 commits, are you still going to do that? Personally it's below my threshold for caring since the 32bit fix is 1 code line, but you did say yes you'll do that πŸ˜ƒ

@eqvinox Sorry I couldn't do it earlier. I didn't explain the issue I hit when I was trying to split this (although I briefly mentioned earlier in this PR that without the 32bit asn I couldn't get the CI for local-as related change to pass).

When I applied just the local-AS hunks, bgp_bmp topotests failed; adding the 32-bit force made them pass. My best guess was an interaction with the A-flag-never-set bug in FRR's BMP per-peer header during peer-flap triggered in router id change test. Maybe the test was flaky and folding 32bit asn change in this PR itself was indirectly making it go away.

Shall I try to split the PR and see if the topotests pass? Asking again as I saw two approvals on this already.

@eqvinox

eqvinox commented May 22, 2026

Copy link
Copy Markdown
Contributor

@kalash-nexthop you said you'd split it in 2 commits, are you still going to do that? Personally it's below my threshold for caring since the 32bit fix is 1 code line, but you did say yes you'll do that πŸ˜ƒ

@eqvinox Sorry I couldn't do it earlier. I didn't explain the issue I hit when I was trying to split this (although I briefly mentioned earlier in this PR that without the 32bit asn I couldn't get the CI for local-as related change to pass).

When I applied just the local-AS hunks, bgp_bmp topotests failed; adding the 32-bit force made them pass. My best guess was an interaction with the A-flag-never-set bug in FRR's BMP per-peer header during peer-flap triggered in router id change test. Maybe the test was flaky and folding 32bit asn change in this PR itself was indirectly making it go away.

Shall I try to split the PR and see if the topotests pass? Asking again as I saw two approvals on this already.

commit != PR, looks like we had a misunderstanding :) - you can just split it into 2 commits and leave it in the same PR.

@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 43047cb to 1d665cf Compare May 22, 2026 23:06
@kalash-nexthop

Copy link
Copy Markdown
Author

@kalash-nexthop you said you'd split it in 2 commits, are you still going to do that? Personally it's below my threshold for caring since the 32bit fix is 1 code line, but you did say yes you'll do that πŸ˜ƒ

@eqvinox Sorry I couldn't do it earlier. I didn't explain the issue I hit when I was trying to split this (although I briefly mentioned earlier in this PR that without the 32bit asn I couldn't get the CI for local-as related change to pass).
When I applied just the local-AS hunks, bgp_bmp topotests failed; adding the 32-bit force made them pass. My best guess was an interaction with the A-flag-never-set bug in FRR's BMP per-peer header during peer-flap triggered in router id change test. Maybe the test was flaky and folding 32bit asn change in this PR itself was indirectly making it go away.
Shall I try to split the PR and see if the topotests pass? Asking again as I saw two approvals on this already.

commit != PR, looks like we had a misunderstanding :) - you can just split it into 2 commits and leave it in the same PR.

Ah right, thanks for clarifying. Split this into two commits now.

@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 1d665cf to 777af0e Compare May 23, 2026 03:02
BMP Route Monitoring messages for monitored routes carried an AS_PATH
with the local AS prepended, as if the route were being re-advertised
outbound. Observed with a peer in AS 40001 advertising 100.100.100.1/32
to a router in AS 40002:

    "as_path":[40002,40001], "as_path_count":2, "peer_asn":40001

The collector expected AS_PATH=[40001] -- the value as received from
the peer -- but saw [40002,40001] because the local AS was prepended on
its way out to the collector.

Root cause: bmp_update() in bgp_bmp.c reuses bgp_packet_attribute(),
the outbound attribute serializer, which performs peer-specific
outbound transformations on AS_PATH (prepend peer->local_as for eBGP,
confed-seq handling, change-local-as). These are correct for sending
an UPDATE to a peer, but the BMP modes FRR currently emits
(pre-policy / post-policy Adj-RIB-In and Loc-RIB) feed receive-side
stored attributes into the serializer and must report them as stored.

Fix: add a bool for_bmp parameter to bgp_packet_attribute(). When
true, skip the peer-sort-based AS_PATH transformations and emit
attr->aspath as-is (no local-AS prepend, no confed-seq manipulation,
no change-local-as).

bmp_update() passes for_bmp=true. The outbound callers in
bgp_updgrp_packet.c pass false to keep their current behaviour.

Also update the bgp_bmp topotest expected JSON files for all three
modes: previously they encoded the prepended local-AS ("65501 65502"
where 65501 is the local AS); now they expect the raw AS_PATH "65502"
as received from the peer in AS 65502.

Signed-off-by: Kalash Nainwal <kalash@nexthop.ai>
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 777af0e to 65f5512 Compare May 25, 2026 21:28
BMP route-monitoring messages need a stable AS_PATH ASN encoding width:
the per-peer header's A flag (RFC 7854 4.2) tells the collector whether
AS_PATH ASNs are 2-byte or 4-byte. FRR's BMP code never sets the A flag
(only V and L are ever set in bgp_bmp.c), so every BMP message
advertises A=0 (4-byte AS_PATH format).

However, the AS_PATH bytes that bgp_packet_attribute() actually writes
to the wire are governed by use32bit, which derives from the peer's AS4
capability state:

    use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
               CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);

peer->cap can be transiently cleared while a session re-establishes
(e.g. during a peer/VRF flap or a router-id change). If a BMP
route-monitoring emit happens in that window, use32bit becomes false,
FRR writes 2-byte ASN bytes on the wire, but the per-peer header still
claims A=0 (4-byte format). The collector decodes 2-byte bytes as
4-byte, the bytes misalign, and parsing fails -- often dropping
subsequent peer-up / peer-down / route-monitor messages until the BMP
session is re-established.

Fix: force use32bit=true whenever for_bmp is set, decoupling BMP
emission from peer->cap state. RFC 9069 5.4.1 in fact requires 4-byte
ASN encoding for Loc-RIB BMP messages, and RFC 7854 4.2 allows a BMP
speaker to "reformat all AS_PATH information into a 4-byte format
regardless of how it was received from the peer." As a side effect this
also suppresses the AS4_PATH backward-compat attribute (send_as4_path
is only set when use32bit is false), which BMP collectors don't need.

Signed-off-by: Kalash Nainwal <kalash@nexthop.ai>
@kalash-nexthop
kalash-nexthop force-pushed the bmp-no-local-as-prepend branch from 65f5512 to 4726014 Compare May 25, 2026 23:19
@kalash-nexthop

Copy link
Copy Markdown
Author

@ton31337 @eqvinox The PR is ready to be merged, but the merge workflow needs to be approved by a maintainer. Do I need to contact someone else or would you be able to trigger that workflow?

@eqvinox
eqvinox merged commit 3123102 into FRRouting:master May 26, 2026
11 checks passed
@kalash-nexthop

Copy link
Copy Markdown
Author

Thanks a lot @eqvinox !

kalash-nexthop added a commit to nexthop-ai/sonic-buildimage that referenced this pull request May 26, 2026
Add FRR patch backporting the BMP local-AS fix from upstream FRR PR
FRRouting/frr#21815 (merged) to the FRR base
in this repo. See the patch file for the full commit message.

Signed-off-by: Kalash Nainwal <kalash@nexthop.ai>
kalash-nexthop added a commit to nexthop-ai/sonic-buildimage that referenced this pull request Jun 2, 2026
Add FRR patch backporting the BMP local-AS fix from upstream FRR PR
FRRouting/frr#21815 (merged) to the FRR base
in this repo. See the patch file for the full commit message.

Signed-off-by: Kalash Nainwal <kalash@nexthop.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants