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.