RFC 8538 Graceful Notification / N-bit / Hard Reset support
Hello BIRD maintainers, I would like to report that BIRD does not currently implement RFC 8538 (Notification Message Support for BGP Graceful Restart). This is not a protocol violation — RFC 8538 is an optional extension that a speaker may choose not to implement. However, the lack of N-bit advertisement and Hard Reset handling limits interoperability with implementations that do support RFC 8538 (e.g., FRR, Cisco IOS-XR, Junos). ## Summary RFC 8538 extends RFC 4724 Graceful Restart with three mechanisms: 1. **N-bit** (Notification bit, 0x4000 in the 16-bit Restart Flags + Time field, i.e., 0x40 in the first byte): A speaker that is willing to send and receive NOTIFICATION messages under RFC 8538 semantics MUST advertise this bit. Only when both peers have advertised the N-bit is RFC 8538 behavior active. 2. **Hard Reset** (CEASE/subcode=9): When N-bit is mutually negotiated and a session teardown is intended to be unconditional (routes must be flushed immediately), the sender wraps applicable CEASE notifications inside a Hard Reset outer envelope (code=6, subcode=9, data=original notification). 3. **Soft notification handling**: When N-bit is negotiated and a non-CEASE notification is sent/received, routes are retained in stale state (GR hold) to allow a GR-style recovery, instead of being immediately withdrawn. BIRD 2.x implements RFC 4724 base Graceful Restart but has no code for any of the above RFC 8538 behaviors. ## Affected Version ```text BIRD version 2.0.7 ``` Static code analysis also confirms the absence in the current development tree. ## Observed Behavior ### Test 1 — N-bit not advertised in OPEN A Python BGP peer connected to BIRD 2.0.7 with `graceful restart yes; graceful restart time 120;` and captured BIRD's OPEN message. The Graceful Restart capability (type=64) contained: ```text Raw GR capability data: 0x007800010100 16-bit Restart Flags + Time field: 0x0078 Restart Flags nibble (bits 15-12): 0x0 R-bit (0x8000 / bit 15): False N-bit (0x4000 / bit 14, RFC 8538): False ← not set Restart Time (bits 11-0): 120s Per-AF: IPv4 unicast, F-bit=0 ``` The N-bit (0x4000 in the 16-bit field, 0x40 in the first byte) is not set. BIRD's only defined GR restart flag is `BGP_GRF_RESTART` (0x80, the R-bit). There is no definition or code path for the RFC 8538 N-bit. ### Test 2 — CEASE not wrapped as Hard Reset After session establishment, `birdc disable gr_test` triggered an admin shutdown. BIRD sent: ```text NOTIFICATION: code=6 (CEASE), subcode=2 (Administrative Shutdown) Data: (none) ``` This is a raw CEASE/AdminShutdown. RFC 8538 recommends that, when the N-bit has been exchanged, CEASE subcodes such as Administrative Shutdown be wrapped as Hard Reset (code=6, subcode=9) so the peer immediately flushes preserved routes. ## Expected Behavior RFC 8538 is an optional extension, so BIRD is not required to implement it. However, if BIRD intends to support RFC 8538, the expected behavior would be: 1. Provide a configuration knob to advertise the N-bit (0x4000) in the GR capability when the operator enables RFC 8538 notification mode. 2. When the N-bit has been mutually negotiated and an admin shutdown occurs, use Hard Reset encapsulation: ```text NOTIFICATION: code=6 (CEASE), subcode=9 (Hard Reset) Data: [original code=6][original subcode=2] ``` 3. When receiving a non-CEASE notification from a peer that negotiated the N-bit, retain the peer's routes in stale state instead of immediately withdrawing them, enabling GR-style recovery from notification-triggered session drops. ## Source-Level Analysis In `proto/bgp/packets.c`, `bgp_write_capabilities()` builds the GR capability: ```c if (caps->gr_aware) { *buf++ = 64; /* Capability 64: Support for graceful restart */ *buf++ = 0; /* length, filled later */ data = buf; put_u16(buf, caps->gr_time); buf[0] |= caps->gr_flags; /* only BGP_GRF_RESTART (0x80) defined */ buf += 2; ... } ``` `caps->gr_flags` is set in `bgp_prepare_capabilities()`: ```c caps->gr_flags = p->p.gr_recovery ? BGP_GRF_RESTART : 0; ``` `BGP_GRF_RESTART` is defined as `0x80` (R-bit). The N-bit (`0x40` in the first byte, `0x4000` in the 16-bit field) is not defined anywhere in BIRD's source. `bgp_create_notification()` writes NOTIFICATION messages directly: ```c buf[0] = conn->notify_code; buf[1] = conn->notify_subcode; memcpy(buf+2, conn->notify_data, conn->notify_size); return buf + 2 + conn->notify_size; ``` There is no Hard Reset wrapping, no N-bit negotiation check, and no soft-notification route-retention logic anywhere in the BIRD source. ## Comparison with FRR FRR bgpd fully implements RFC 8538 (`bgp_open.h`): ```c #define GRACEFUL_RESTART_R_BIT 0x8000 #define GRACEFUL_RESTART_N_BIT 0x4000 /* RFC 8538 */ ``` In OPEN construction: ```c SET_FLAG(gr_restart_time, GRACEFUL_RESTART_N_BIT); SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV); ``` Negotiation check: ```c bool bgp_has_graceful_restart_notification(struct peer *peer) { return CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV) && CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV); } ``` Because BIRD never advertises the N-bit, `bgp_has_graceful_restart_notification()` always returns false on the FRR side for BIRD peers. Both implementations correctly fall back to RFC 4724 base GR behavior: this is an interoperability limitation, not a negotiated RFC 8538 failure. ## Dynamic Verification Verified against BIRD 2.0.7 using a Python BGP peer that: - Advertised the N-bit (0x4000) in its own OPEN to offer RFC 8538 to BIRD - Parsed BIRD's OPEN response for the N-bit - Triggered admin shutdown via `birdc` and captured BIRD's outgoing NOTIFICATION ```text TEST 1 (N-bit in OPEN) : N_BIT_NOT_SET GR data 0x0078... → Restart Flags nibble = 0x0 → N-bit absent TEST 2 (Hard Reset on CEASE) : CEASE_RAW NOTIFICATION code=6/sub=2 (AdminShutdown) — not wrapped as Hard Reset RESULT: BIRD does NOT implement RFC 8538 ``` ## Impact There is no current security or operational impact in BIRD-only or BIRD-FRR deployments, because the N-bit is never mutually negotiated and both sides fall back to standard RFC 4724 GR behavior. The forward-looking concern is: if BIRD adds N-bit advertisement in the future without also implementing Hard Reset and soft-notification semantics, sessions with RFC 8538-capable peers could exhibit asymmetric teardown. Specifically: - BIRD sends a raw CEASE/AdminShutdown (no Hard Reset envelope) - The RFC 8538 peer interprets this as a soft GR event and retains stale routes for the full restart timer window, instead of flushing them immediately This would be a behavioral surprise for operators who configure BIRD as an RFC 8538 peer in a mixed-vendor network. ## Suggested Fix If RFC 8538 support is planned: 1. Define the N-bit flag: ```c #define BGP_GRF_NOTIFICATION 0x40 /* RFC 8538 N-bit, 0x4000 in 16-bit field */ ``` 2. Add a configuration knob and set the bit in `bgp_prepare_capabilities()` when the operator enables GR notification mode. 3. Implement Hard Reset wrapping in the NOTIFICATION send path when N-bit is active. 4. On NOTIFICATION receive, when N-bit has been negotiated and the notification is not a Hard Reset, retain peer routes (stale hold) instead of immediate withdrawal. Best regards.
Howdy! On Tue, Jul 07, 2026 at 03:38:31PM +0800, xinzhe liu wrote:
I would like to report that BIRD does not currently implement RFC 8538 (Notification Message Support for BGP Graceful Restart). This is not a protocol violation
This seems to be correct.
## Affected Version
BIRD version 2.0.7
This is quite old, the current versions are 3.3.1 and 2.19.1.
## Source-Level Analysis
[...]
This looks like you already checked implementation feasibility. Feel free to send a patch. -- Maria Matejka (she/her) | BIRD Team Leader | CZ.NIC, z.s.p.o.
participants (2)
-
Maria Matejka -
xinzhe liu