Skip to content

bgpd: use bm buffer for rcvd_attr_str debug logging - #22479

Merged
riw777 merged 1 commit into
FRRouting:masterfrom
enkechen-panw:bgp-memory-attrstr
Jul 10, 2026
Merged

bgpd: use bm buffer for rcvd_attr_str debug logging#22479
riw777 merged 1 commit into
FRRouting:masterfrom
enkechen-panw:bgp-memory-attrstr

Conversation

@enkechen-panw

@enkechen-panw enkechen-panw commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The embedded rcvd_attr_str[BUFSIZ] array in struct peer consumes 8192 bytes per peer, but is only used for debug logging of received BGP UPDATE attributes.

Change to a bm buffer since BGP packet processing is single-threaded in the event loop. This eliminates 8KB of memory usage per peer.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown

Greptile Summary

This PR optimizes memory usage by moving rcvd_attr_str[BUFSIZ] and rcvd_attr_printed from struct peer to the singleton struct bgp_master, saving 8 KB per peer. The change is safe under FRR's single-threaded BGP event loop, where only one UPDATE message is processed at a time.

  • bgpd/bgpd.h: Removes the two fields from struct peer and adds them to struct bgp_master, with a comment noting the single-threaded assumption.
  • bgpd/bgp_packet.c: Resets bm->rcvd_attr_str[0] = '\0' at the start of bgp_update_receive (replacing the previous full memset) and adds an explicit clear at the function's successful-exit path for defensive hygiene.
  • bgpd/bgp_route.c: All three logging sites that checked peer->rcvd_attr_printed now also guard on bm->rcvd_attr_str[0] to prevent printing a stale empty string if bgp_dump_attr was never called for the current UPDATE.

Confidence Score: 5/5

The change is safe to merge — it eliminates per-peer heap bloat without altering any observable behavior under FRR's single-threaded BGP event loop.

All three files make consistent, mechanically straightforward substitutions of peer-scoped fields for the bm singleton. The reset at function entry, the guard added in bgp_route.c (bm->rcvd_attr_str[0]), and the defensive clear at the successful-return path together maintain identical semantics to the original code. No data is dropped, no logging path is silently suppressed, and the single-threaded processing model that makes the global buffer safe is well-established in FRR.

No files require special attention.

Important Files Changed

Filename Overview
bgpd/bgpd.h Moves rcvd_attr_str[BUFSIZ] and rcvd_attr_printed from struct peer to struct bgp_master; removes the old per-peer fields and their accompanying thread-safety warning comment.
bgpd/bgp_packet.c Replaces memset-based reset with bm->rcvd_attr_str[0] = '\0' at start of bgp_update_receive, switches all attribute-string references to bm, and adds a defensive clear at the successful-return path.
bgpd/bgp_route.c Updates three attribute-logging sites to use bm->rcvd_attr_printed and bm->rcvd_attr_str, adding a bm->rcvd_attr_str[0] guard to skip printing when the buffer has not been populated.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant EL as Event Loop (single thread)
    participant BPkt as bgp_packet.c
    participant BM as bgp_master (bm)
    participant BRt as bgp_route.c

    EL->>BPkt: bgp_update_receive()
    BPkt->>BM: "rcvd_attr_str[0] = '\0'"
    BPkt->>BM: "rcvd_attr_printed = false"
    BPkt->>BPkt: bgp_attr_parse()
    alt debug ON or parse error
        BPkt->>BM: bgp_dump_attr → rcvd_attr_str
        alt UPDATE_DETAIL debug
            BPkt->>BM: zlog_debug(rcvd_attr_str)
            BPkt->>BM: "rcvd_attr_printed = true"
        end
    end
    loop for each NLRI prefix
        BPkt->>BRt: bgp_nlri_parse → bgp_update()
        alt "debug ON && !rcvd_attr_printed && rcvd_attr_str[0]"
            BRt->>BM: zlog_debug(rcvd_attr_str)
            BRt->>BM: "rcvd_attr_printed = true"
        end
    end
    BPkt->>BM: "rcvd_attr_str[0] = '\0' (defensive clear)"
    BPkt->>EL: Receive_UPDATE_message
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant EL as Event Loop (single thread)
    participant BPkt as bgp_packet.c
    participant BM as bgp_master (bm)
    participant BRt as bgp_route.c

    EL->>BPkt: bgp_update_receive()
    BPkt->>BM: "rcvd_attr_str[0] = '\0'"
    BPkt->>BM: "rcvd_attr_printed = false"
    BPkt->>BPkt: bgp_attr_parse()
    alt debug ON or parse error
        BPkt->>BM: bgp_dump_attr → rcvd_attr_str
        alt UPDATE_DETAIL debug
            BPkt->>BM: zlog_debug(rcvd_attr_str)
            BPkt->>BM: "rcvd_attr_printed = true"
        end
    end
    loop for each NLRI prefix
        BPkt->>BRt: bgp_nlri_parse → bgp_update()
        alt "debug ON && !rcvd_attr_printed && rcvd_attr_str[0]"
            BRt->>BM: zlog_debug(rcvd_attr_str)
            BRt->>BM: "rcvd_attr_printed = true"
        end
    end
    BPkt->>BM: "rcvd_attr_str[0] = '\0' (defensive clear)"
    BPkt->>EL: Receive_UPDATE_message
Loading

Reviews (4): Last reviewed commit: "bgpd: use bm buffer for rcvd_attr_str de..." | Re-trigger Greptile

Comment thread bgpd/bgp_packet.c Outdated
@enkechen-panw

Copy link
Copy Markdown
Contributor Author

@greptileai review

Comment thread bgpd/bgp_packet.c Outdated
@enkechen-panw

Copy link
Copy Markdown
Contributor Author

@greptileai review

The embedded rcvd_attr_str[BUFSIZ] array in struct peer consumes
8192 bytes per peer, but is only used for debug logging of received
BGP UPDATE attributes.

Move to bm (bgp_master) since BGP packet processing is single-threaded.
This eliminates 8KB of memory usage per peer.

The attribute string buffer is cleared at the end of bgp_update_receive()
to prevent stale state when bgp_update() is called from other paths
(RPKI, label-unicast, flowspec, EVPN handlers).

Signed-off-by: Enke Chen <enchen@paloaltonetworks.com>
@enkechen-panw

Copy link
Copy Markdown
Contributor Author

@greptileai review

@enkechen-panw enkechen-panw changed the title bgpd: use global buffer for rcvd_attr_str debug logging bgpd: use bm buffer for rcvd_attr_str debug logging Jun 30, 2026

@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 merged commit 01f9379 into FRRouting:master Jul 10, 2026
23 checks passed
@enkechen-panw
enkechen-panw deleted the bgp-memory-attrstr branch July 10, 2026 16:12
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