| Family | Config Name | AFI/SAFI | Encode | Decode | Route Config |
|---|---|---|---|---|---|
| IPv4 Unicast | ipv4/unicast |
1/1 | Yes | Yes | Yes |
| IPv6 Unicast | ipv6/unicast |
2/1 | Yes | Yes | Yes |
| IPv4 Multicast | ipv4/multicast |
1/2 | Yes | Yes | Yes |
| IPv6 Multicast | ipv6/multicast |
2/2 | Yes | Yes | Yes |
| IPv4 VPN | ipv4/mpls-vpn |
1/128 | Yes | Yes | Yes |
| IPv6 VPN | ipv6/mpls-vpn |
2/128 | Yes | Yes | Yes |
| IPv4 FlowSpec | ipv4/flow |
1/133 | Yes | Yes | Yes |
| IPv6 FlowSpec | ipv6/flow |
2/133 | Yes | Yes | Yes |
| IPv4 FlowSpec VPN | ipv4/flow-vpn |
1/134 | Yes | Yes | Yes |
| IPv6 FlowSpec VPN | ipv6/flow-vpn |
2/134 | Yes | Yes | Yes |
| IPv4 MPLS Label | ipv4/mpls-label |
1/4 | Yes | Yes | Yes |
| IPv6 MPLS Label | ipv6/mpls-label |
2/4 | Yes | Yes | Yes |
| L2VPN EVPN | l2vpn/evpn |
25/70 | Yes | Yes | Yes |
| L2VPN VPLS | l2vpn/vpls |
25/65 | Yes | Yes | Yes |
| BGP-LS | bgp-ls/bgp-ls |
16388/71 | No | Yes | No |
| BGP-LS VPN | bgp-ls/bgp-ls-vpn |
16388/72 | No | Yes | No |
| IPv4 MVPN | ipv4/mvpn |
1/5 | Yes | Yes | Partial |
| IPv6 MVPN | ipv6/mvpn |
2/5 | Yes | Yes | Partial |
| IPv4 RTC | ipv4/rtc |
1/132 | Yes | Yes | No |
| IPv4 MUP | ipv4/mup |
1/85 | Yes | Yes | Yes |
| IPv6 MUP | ipv6/mup |
2/85 | Yes | Yes | Yes |
| IPv4 SR-Policy | ipv4/sr-policy |
1/73 | Yes | Yes | Yes |
| IPv6 SR-Policy | ipv6/sr-policy |
2/73 | Yes | Yes | Yes |
The BGP-LS rows describe the general NLRI codec and route-configuration API.
The separate bgp-ls-export
plugin originates standard SAFI 71 routes from native IGP or EPE state. It does
not add generic text/API BGP-LS encoding or SAFI 72 origination.
SR-Policy route encoding leaves the Binding SID's unassigned flag bits clear (RFC 9830 Section 2.4.2). It does not request S-Flag or I-Flag behavior.
An SR-Policy route carries an SRv6 Binding SID in one of two sub-TLVs, and the operator chooses which:
| Route keyword | Sub-TLV written | Value |
|---|---|---|
srv6-binding-sid <ipv6-address> |
SRv6 Binding SID, type 20 (RFC 9830 Section 2.4.3) | Length 18: Flags, RESERVED, the 16-octet SID |
binding-sid srv6 <ipv6-address> |
Binding SID, type 13 (RFC 9830 Section 2.4.2) | Length 18: Flags, RESERVED, the 16-octet SID |
binding-sid mpls <label> |
Binding SID, type 13 | Length 6: Flags, RESERVED, the label entry |
binding-sid null |
Binding SID, type 13 | Length 2: Flags, RESERVED, no BSID |
RFC 9830 recommends type 20 for an SRv6 BSID and keeps the type-13 form for
speakers that followed early drafts, so use binding-sid srv6 only toward such a
peer. binding-sid srv6 takes an IPv6 address; an IPv4, IPv4-mapped or zoned
address is refused at load with the token and the fix. One Binding SID
sub-TLV is written per route: when a route names several binding-sid forms,
mpls wins over srv6, which wins over null.
ze bgp decode --json shows a received Tunnel Encapsulation attribute under
tunnel-encapsulation, one entry per tunnel TLV. A Binding SID sub-TLV is shown
with its flags and its mpls-label (Length 6), its srv6-sid (Length 18), or
neither (Length 2); any other length is shown malformed with its value octets
in hex. The SRv6 Binding SID sub-TLV (type 20) is shown the same way with its
srv6-sid. Every other sub-TLV is shown as its type and its value in hex.
An SR-Policy route configured in nlri { ipv4/sr-policy add ... } or encoded
with ze bgp encode -f ipv4/sr-policy carries only labels it can send as
written. binding-sid mpls accepts 16 to 1048575: 0 to 15 are the reserved
MPLS values RFC 9830 Section 2.4.2 forbids, and a label is 20 bits wide.
type-a mpls accepts 0 to 1048575. A value outside the range is refused with
the token, the value and the range, before any UPDATE is built.
On receipt, an SR-Policy NLRI whose length is not 12 octets (AFI 1) or 24 octets (AFI 2) makes its UPDATE treat-as-withdraw, and NLRI framing that cannot be walked resets the session (RFC 9830 Section 5). An SR-Policy announcement with no Tunnel Encapsulation attribute is treat-as-withdraw (RFC 9830 Section 4.2.1).
| Capability | Code | RFC | Description |
|---|---|---|---|
| Multiprotocol Extensions | 1 | RFC 4760 | Multi-protocol BGP (AFI/SAFI negotiation) |
| 4-byte ASN | 65 | RFC 6793 | 32-bit AS numbers |
| Route Refresh | 2 | RFC 2918 | Request full route re-advertisement |
| Enhanced Route Refresh | 70 | RFC 7313 | Bounded clear and re-send |
| ADD-PATH | 69 | RFC 7911 | Multiple paths per prefix |
| Extended Message | 6 | RFC 8654 | Up to 65535 bytes: local advertisement permits receive, peer advertisement permits send; OPEN and KEEPALIVE are unchanged |
| Extended Next Hop | 5 | RFC 8950 | IPv6 next-hop for IPv4 NLRI |
| Graceful Restart | 64 | RFC 4724 | Session preservation across restarts (Restarting Speaker: R-bit via zefs marker on ze signal restart) |
| Long-Lived GR | 71 | RFC 9494 | Extended stale route retention with LLGR_STALE community and depreference |
| BGP Role | 9 | RFC 9234 | Peer relationship role |
| Hostname | 73 | RFC 8516 | FQDN capability |
| Software Version | 75 | draft | Software version advertisement |
| Link-Local Next Hop | 77 | draft-ietf-idr-linklocal-capability | A 16-octet next hop holding one IPv6 link-local address, which RFC 2545 has no form for |
| PATHS-LIMIT | 76 | draft-abraitis-idr-addpath-paths-limit | Per-family path count limit for ADD-PATH |
An AS number is one 4-octet number on the wire (RFC 6793). RFC 5396 Section 2 names three ways to write that number in text. Ze READS all three wherever an AS number is configured or typed at a command.
That includes a route distinguisher in every form Ze parses one, and the
administrator of an extended community such as target:1.10:5. It also
includes the as-path of show bgp encode route, the MVPN source-as, the
show bgp rib path filter, the AS<n> peer selector, and rpki validate. The
./le mrt command reads them on --peer-asn and --local-as.
One reader answers each of those forms. selector.ParseASNSelector is the
AS<n> selector, for every peer command and for the policy filter.
attribute.ParseExtCommunityAdmin is the extended-community administrator, for
all four of its parsers. A private copy of either is what ./le repo check now reports.
The L suffix of an extended community forces the four-octet encoding, and it
is orthogonal to the spelling: 65000L, 0.100L and 1.10L each say it. For
a value of more than 65535 the value forces that encoding by itself, so the
suffix is redundant there and is accepted.
AS 65546 is written 65546 in asplain, and 1.10 in both asdot and asdot+.
Each field of the dotted form is a 16-bit value, so 0.65546 is not a spelling
of it. The tree stores the decimal form, so the notation an operator types
changes nothing downstream.
These configured fields hold an AS number and still read decimal only:
- the AS half of a standard community. RFC 1997 page 3 encodes it in the first
two octets. Two octets hold no four-byte AS number. The only dotted spelling
that fits is
0.Y, and that names the AS numberYalready names. - the Global Administrator of a large community. RFC 8092 Section 5 pins the canonical representation to three decimal integers.
- the 2-octet administrator of a route origin (
origin:ASN:IP) and of a filter's extended-community match. Two octets again, as above.
bgp { as-notation } selects the notation Ze WRITES. asplain is the default,
and RFC 5396 Section 3 recommends it. asdot writes an AS number of 65536 or
more as X.Y, and leaves a lower one as a decimal integer. asdot+ writes
every AS number as X.Y.
The leaf reaches every surface an operator reads an AS number on:
- the route rows of
show bgp rib - the peer rows of
show bgpandshow bgp peer detail - the ROA and ASPA rows of
show bgp rpki - the
show bgp irrrows - the CLI dashboard
- the looking glass tables and topology graph
- the BGP pages of the web interface
Under a dotted notation those AS numbers are JSON STRINGS rather than JSON
numbers, because 1.10 is not a JSON number. Every Ze reader of such a payload
accepts both forms (asn.Number, asn.FromJSON), so a client renders what the
producer rendered.
Five surfaces stay asplain whatever the leaf says, because their text is a contract rather than a display:
- the AS path of the plugin event stream
- the
update textcommand Ze replays to itself - the filter text a filter plugin matches
- the text form of the plugin process protocol
- the
as_pathof the birdwatcher-compatible looking glass API
A dotted AS number there would stop a configured filter matching, or fail a client that parses an integer. The ExaBGP bridge writes ExaBGP's own text format, and that program fixes the spelling.
Ze refuses an OPEN whose AS is not the one the peer is configured for, and an
OPEN carrying AS 0, with NOTIFICATION 2/2 Bad Peer AS. The AS judged is the
Four-octet AS capability's value when the peer sends one. A dynamic peer, whose
AS is learned from its OPEN, is exempt. Each refusal is counted in
ze_bgp_open_rejected_bad_peer_as_total (docs/guide/monitoring.md).
session { asn { migration <asn> } }, on a peer or a group, runs one iBGP
session under either of two local AS numbers (RFC 7705 Section 4.2). Ze accepts
an OPEN carrying the local or the migration AS, treats the session as internal
whichever AS won, and opens with the local AS first, switching to the other one
on the next attempt only after the peer answers Bad Peer AS. The external-session
options of RFC 7705 Section 3.3 are local and local-options. Both are in
docs/guide/configuration.md, "AS Migration (local-as)" and "Internal AS
Migration (RFC 7705 Section 4.2)".
When several BGP candidates tie under multipath selection, Ze carries the winner and its equal-cost sibling next hops into the shared Loc-RIB. The system RIB then emits one ECMP group to the active FIB backend. Membership-only changes, such as one equal-cost peer disappearing, update the installed group without requiring the winning peer to change.
show rib reports the primary next-hop and the additional ecmp-paths.
Together they are the complete installed next-hop set.
bgp update-delay max-delay <seconds> holds the first advertisement of a
speaker that has just started, so a neighbor receives one settled route set
instead of an initial set followed by corrections. The optional
establish-wait <seconds> ends the hold early, on the peers that have reached
Established by then. It must not be more than max-delay, and Ze refuses a
configuration where it is, at ze config validate as well as at startup.
While Ze holds, sessions negotiate, reach Established and receive UPDATE
messages as usual. Ze sends no UPDATE and no End-of-RIB marker, because the
initial routing update has not completed and RFC 4724 Section 4.1 makes the
marker a claim that it has. The hold ends on the first of three conditions:
every configured peer sends its own End-of-RIB marker, establish-wait expires
with one or more peers established, or max-delay expires. A peer that never
comes up cannot extend the wait past max-delay.
Ze waits for the marker rather than for Established, because Established says only that the neighbor answered. RFC 4724 Section 4.1 excludes two kinds of peer from that wait by name, and Ze excludes the same two: a peer that advertised no graceful-restart capability, which has promised no marker, and a peer whose capability carries the Restart State bit, which is deferring its own initial update. A dynamic-group member is held like every other peer and is never counted toward the release.
show bgp update-delay reports the hold: whether it is running, which condition
ended it, and how many expected peers have converged.
The hold applies at startup alone. A reload validates a changed update-delay
and Ze keeps the hold it already armed, or none: re-arming would withhold routes
from a neighbor that already has them.
An absent max-delay, or max-delay 0, is the default and holds nothing.
RFC 9494 stale-route handling is applied per destination on both normal
forwarding and RIB readvertisement. An LLGR-capable peer receives the stale
route unchanged. A non-LLGR eBGP peer receives a withdrawal. A non-LLGR iBGP
peer receives the route with NO_EXPORT and LOCAL_PREF=0, allowing partial
deployments to retain reachability without preferring stale information.
This applies to a route at the LLGR stale level, one Ze marked LLGR stale or one
received with LLGR_STALE from a neighbor Ze sent LLGR to, on every path that
advertises it: live forwarding, RIB replay and route refresh, and the
bgp-adj-rib-in replay. A route in its conventional GR period carries no
LLGR_STALE and is advertised like any other.
Only the LLGR filter runs during stale readvertisement. Other export policy has already run on the original announcement and is not applied twice.
Several rails write an UPDATE: the announce rails that encode a route Ze produced, the forward rail that relays another speaker's UPDATE, and the route-server rail. Each rule below is answered at one site that every rail asks, rather than re-derived per rail. The rails that re-derived a rule disagreed about it: the announce rail stripped LOCAL_PREF toward an external peer and the forward rail did not.
| Rule | RFC | Behavior |
|---|---|---|
| LOCAL_PREF off an external session | 4271 Section 5.1.5 | Removed from every UPDATE toward an external peer, relayed UPDATEs included. Recorded after the export filter pass, so a filter that sets LOCAL_PREF does not override the prohibition. A session is internal when LocalAS == PeerAS. Ze names no confederation member-AS, so the RFC 3065 exception is never active. |
| LOCAL_PREF on an internal session | 4271 Section 5.1.5 | Present in every UPDATE toward an internal peer. A relayed route that arrives without LOCAL_PREF, such as one learned from an external peer, gets LOCAL_PREF 100, the value the announce rail writes. A received value, or one an export filter sets, is kept. |
| IPv4 NLRI behind an IPv6 next hop needs Extended Next Hop | 8950 Section 4 | A relayed route whose MP_REACH_NLRI carries IPv4 or VPN-IPv4 NLRI with an IPv6 next hop is withheld from a peer that did not negotiate the Extended Next Hop pair for that AFI/SAFI, and logged. The next hop a configured next-hop mode or an export filter writes is the one judged. Withdrawals in the same UPDATE still reach the peer. An announce with an explicit IPv6 next hop is refused for such a peer. |
| A received MULTI_EXIT_DISC is not relayed | 4271 Section 5.1.4 | Removed when the value about to be written is the value that arrived. A metric an announce rail or an export filter sets is kept, because that is Ze originating one. A route-server client keeps the received metric (RFC 7947 Section 2.2.3). |
| Configured MULTI_EXIT_DISC removal | 4271 Section 5.1.4 | bgp/policy/modify/<name>/del/med, on an import chain only. An export chain refuses the directive and logs why (Section 9.1.2.2). |
| No peer receives its own address as next hop | 4271 Section 5.1.3 | Asked of the built body, after the export chain, for a relayed route and for an originated one. The route is withheld from that peer and logged; it is never rewritten, which keeps RFC 7947 Section 2.2.2 transparency. Withdrawals in the same UPDATE still reach the peer. |
| A route naming this speaker is not installed | 4271 Section 5.1.3 | Excluded from best-path candidacy rather than refused at install, so a sound alternative wins. "Itself" is the set of session-local addresses. |
| Partial bit on an unrecognized transitive optional attribute | 4271 Sections 5 and 9; 7947 Section 2.2 | Stamped at ordinary-session ingest. A configured route-server client's optional attributes instead retain their received flags and values, including unknown non-transitive attributes, for transparent client redistribution. A relayed UPDATE going to an ordinary peer is normalized on its outgoing copy without changing the client copy. Recognition comes from Ze's attribute registry. Session-reset and treat-as-withdraw skip the ingest stamp, since they propagate nothing. |
| Partial bit on a well-known or optional non-transitive attribute | 4271 Section 4.3 | Cleared at ingest, at the same site as the stamp above and over the same bytes, so the RIB, the route-server relay and every rebuild carry the repaired octet. RFC 7606 Section 3(c) judges the Optional and Transitive bits only, so a peer's forbidden Partial bit arrives as a valid attribute and would otherwise be relayed unchanged. The two walks act on disjoint classes: an optional transitive attribute keeps the bit an earlier AS set. |
| Redundant Large Community values are removed | 8092 Section 3 | Removed at ingest, at the same site as the Partial-bit walks, keeping the first occurrence of each value in the order received, so the RIB, the route-server relay and every rebuild carry the attribute without the repeat. The removal is silent: no RFC 7606 action, no NOTIFICATION. An attribute with no repeated value is only read, and the received bytes are published unchanged. |
| Withdrawals before announces | 4271 Section 4.3 | All withdrawals run before all announces, in the legacy sections and the multiprotocol ones, so one UPDATE naming a prefix in both leaves it reachable. |
| A relayed withdrawal carries no path attributes | 4271 Sections 4.3 and 6.3 | An UPDATE advertising no reachable NLRI gets no attribute created on it: no next-hop rewrite, no RFC 4456 reflection stamp, no community tag, no policy delta, no AS_PATH prepend. Rewriting an attribute the source already carries stays allowed, which keeps the RFC 6793 Section 4.2.2 width transcode. |
| One attribute order for every builder | 4271 Section 5 | Path attributes are inserted by type code in ascending order on every rail. MP_UNREACH_NLRI stays first, out of type-code order, so a withdrawal precedes an announcement in one message. |
| The next-hop wire form matches its length octet | 4760, 2545 Section 3 | The MP_REACH Next Hop length and the bytes written derive from one value. The IPv6 link-local address is appended after the global one only when this speaker shares a locally connected subnet with the peer and with the entity the global next hop names, and only when that global is this speaker's own address: the link-local is this speaker's, so it is never paired with another router's global. A next hop Ze writes that names another router on the shared link (an explicit session next-hop, a static or API route) is sent as its global alone, because Ze holds no source for that router's link-local (a recorded RFC 2545 gap). A relayed pair must have an IPv6 global unicast first address and an IPv6 link-local unicast second address, apart from the canonical VPN exception below; otherwise the native route is withdrawn before the pair can be advertised or silently reduced to a single address. These checks judge effective policy output, not obsolete received addresses, and preserve an independently valid legacy sibling. For valid pairs, the implemented prefix-membership predicates retain the received link-local only when both the destination and the effective global address belong to locally connected prefixes. Otherwise the link-local half is removed and the global goes alone. This is not proof of next-hop-entity identity or whole RFC2545-3-3 adjacency. The global-unicast requirement also covers unpaired IPv6 globals: loopback, unspecified, multicast and IPv4-mapped next hops in an IPv6-family MP_REACH cause a withdrawal even toward an on-link peer. Native IPv4-family MP next hops and negotiated standalone link-local IPv6 retain separate handling. RFC 4659 Section 3.2.1.1 permits its canonical 48-octet VPN-IPv6 unspecified-global/link-local pair on an established link-local-only peering; that pair is preserved with zero RDs. The link-local leaf supplies the address; it does not decide that the address is sent. The second address rides on the NEXT HOP being IPv6 rather than on the prefix, so IPv4 NLRI carried behind an IPv6 next hop (RFC 8950 Section 3) gets the same 32-octet field. |
| A 16-octet link-local next hop needs capability 77 | draft-ietf-idr-linklocal-capability Sections 2, 3 and 5 | The Link-Local-only form is sent only where the session negotiated the capability, and for IPv4 NLRI only where RFC 8950 Extended Next Hop Encoding was negotiated as well. A route whose next hop is link-local is left out of the announcement on any other session, and logged, rather than encoded in a form RFC 2545 Section 3 forbids. This holds for originated and forwarded routes alike, including next-hop self on a session that runs over a link-local address. |
| A malformed 32-octet next hop on a capability-77 session is withdrawn | draft-ietf-idr-linklocal-capability Section 6 | A received Next Hop field of 32 octets must be a Global (or ::) followed by a Link-Local, or two Link-Locals. Any other pair makes the UPDATE treat-as-withdraw (RFC 7606 Section 7.3). Without the capability, only the length is judged |
| A reflected link-local-only next hop stays on its own segment | draft-ietf-idr-linklocal-capability Section 4 | A route reflector withholds such a route from a client that shares no connected subnet with the original advertiser, and logs the suppression. A client the operator configured next-hop-self for receives it with this speaker's address instead, which is the other answer Section 4 allows. A link-local prefix is never read as evidence of a shared segment. |
| No AS_SET or AS_CONFED_SET is advertised | 9774 Section 3 | Asked of the built body on every rail except raw injection, after the export chain: an UPDATE whose AS_PATH or AS4_PATH, in any occurrence, holds a set segment is written as the withdrawal of its prefixes instead, logged as a rate-limited warning that names the peer and the route count, and counted on ze_bgp_as_set_withdrawn_total. Proven against FRR by the interop scenario bgp-rfc9774-as-set-frr. |
| A received AS_SET or AS_CONFED_SET is treat-as-withdraw | 9774 Section 3 | An UPDATE whose AS_PATH or AS4_PATH holds a set segment is handled as a withdrawal of its prefixes (RFC 7606), on every session whatever the AS width. The log line carries RFC 9774 Section 3: AS_SET in AS_PATH. Proven by test/plugin/rfc9774-as-set-receive-treat-as-withdraw.ci and by bgp-rfc9774-as-set-frr, where Ze's own RIB never holds the injected set route. |
| A modification that cannot be applied suppresses the route | none | The route is withheld from that destination rather than forwarded unmodified. Counted on ze_bgp_update_modify_failed_total{reason}. |
RFC 7606 Section 5.4 requires a speaker advertising a typed address family to discard routes carrying an NLRI type it does not implement, "unless the relevant specification for that address family specifies otherwise". The ruling is registered per family by the plugin that owns the family, so compiling that plugin out removes both the advertisement and the obligation.
| Family | Ruling |
|---|---|
l2vpn/evpn |
Discard an unrecognized route type |
ipv4/mvpn, ipv6/mvpn |
Discard an unrecognized route type (RFC 6514 Section 4 framing) |
ipv4/mup, ipv6/mup |
Discard an unrecognized route type (draft-ietf-bess-mup-safi Section 3.1 framing). Treat a malformed route of an implemented type as withdrawn (Section 3.1.3.1). Treat a Direct Segment Discovery route announced with no Prefix-SID attribute as withdrawn (Section 3.3.6) |
bgp-ls/bgp-ls, bgp-ls/bgp-ls-vpn |
No discard. RFC 9552 Section 5.2 requires an unknown Link-State NLRI type to be preserved and propagated |
| Every other family | No discard. A family nobody has ruled on discards nothing |
Every recognizer answers about the route TYPE. A family whose specification
answers a malformed body with treat-as-withdraw also judges the body: BGP-MUP
runs every check its decoder makes (draft-ietf-bess-mup-safi Sections 3.1.1 to
3.1.5), so a T1ST whose mandatory fields overrun its Length, whose TLV area is
one octet, or whose TLV overruns the NLRI leaves the announcement and becomes a
withdrawal. The withdrawal joins the same UPDATE as an MP_UNREACH_NLRI, or rides
its own withdraw-only UPDATE when that UPDATE already carries one (RFC 7606
Section 3(g) allows one per UPDATE). Its siblings are kept byte for byte and the
session stays up. A malformed route whose route key cannot form is discarded
instead, because no withdrawal can name it. Both are logged at debug with the
NLRI bytes and counted in ze_bgp_update_nlri_malformed_total
(docs/guide/monitoring.md).
The withdrawal never carries the malformed bytes. A receiver decodes every field
of a withdrawn NLRI, so for a family whose recognizer judges the body
(nlritype.RegisterBodyRecognizer) each peer keeps the last well-formed
generation it announced for each route key, and the withdrawal of a malformed
route names that generation. When no generation is held, the peer never
installed the route and nothing is relayed for it. The same rule applies to a
malformed or unkeyable NLRI a peer sends in an MP_UNREACH_NLRI. FRR and BIRD
build their withdrawals the same way, from the route they hold.
A held generation can be longer than the malformed NLRI it replaces, so the replacements join the UPDATE only while it carries no other MP_UNREACH_NLRI and still fits the session's message limit; otherwise they leave in withdraw-only UPDATEs sized to that limit. The hold lives as long as the routes it mirrors (RFC 4724 Section 4.2): it survives a reconnect that negotiates Graceful Restart, is emptied by one that does not, and an End-of-RIB drops the generations of its family the new session did not announce again.
A family can also register an UPDATE-level check beside its recognizer, for a rule that judges a route by the UPDATE carrying it. BGP-MUP registers one for draft-ietf-bess-mup-safi Section 3.3.6: a Direct Segment Discovery route in an MP_REACH_NLRI whose UPDATE carries no Prefix-SID attribute is withdrawn the same way, and the other routes of the UPDATE are kept. A Prefix-SID that RFC 7606 attribute-discard removes counts as absent, so a DSD route from an EBGP peer not configured to accept the Prefix-SID (RFC 8669 Section 4) is withdrawn too.
When the length fields do not agree with the section the NLRI boundaries are unknowable, so no decision is made rather than one being guessed, and RFC 7606 Section 5.3 resets the session.
RFC 7911 Section 2 requires a speaker that re-advertises a route to generate its own Path Identifier, assigned so that (prefix, identifier) uniquely names a path advertised to a neighbor. Both forward rails do that instead of relaying the identifier the source chose.
The key is the path at ingress, and how much of the path it holds follows what the source framed. A source that negotiated no ADD-PATH names a path by its prefix alone and sends every one of them under identifier 0, so ze holds one identifier for that source's whole session. A source that negotiated ADD-PATH names a path by (prefix, identifier), so ze holds one entry per family, received identifier and prefix. A withdrawn route carries no path attributes, so an attribute-derived identifier could not be recomputed when the path leaves; the ingress key can. The same key makes a re-announcement with changed attributes replace rather than duplicate.
An identifier of the first kind is released only when the peer is removed. One of the second kind is released when ze has relayed that pair's withdraw, at the point the recent-update cache evicts the UPDATE that carried it. Neither is released at session down, so a reconnecting peer re-announces under the identifiers its destinations already hold. Zero is minted and accepted like any other value (RFC 7911 Section 3).
Regeneration runs whenever either side of the forward frames identifiers. A session where neither side negotiated ADD-PATH keeps its zero-copy forward.
A peer writes every message it receives to a bounded JSONL file, together with
the config operations applied while the capture runs. le test replay <file>
feeds the file back through the same read path with an injected clock.
The tee sits on the complete wire message in both read paths, before message processing. RFC 7606 enforcement rewrites attributes and synthesizes withdrawals, and the family and prefix-limit checks can return before anything is dispatched, so the plugin message-observer hook cannot see what a bug capture needs.
Off by default. The tee costs one nil comparison and no allocation per received
message. Config payloads pass a redactor, and TCP-MD5 keys never appear on the
wire, so the file holds routing data and no local secret. ze doctor reports
whether an enabled peer's capture directory is usable
(doctor-bgp-capture-directory).
le test replay [--json] [--local-as N] [--peer-as N] [--router-id N] <capture-file|->| Attribute | Code | JSON Key | Description |
|---|---|---|---|
| ORIGIN | 1 | origin |
igp / egp / incomplete |
| AS_PATH | 2 | as-path |
AS path segments |
| NEXT_HOP | 3 | next-hop |
Next hop IP address |
| MED | 4 | med |
Multi-Exit Discriminator. A configured med 0 is sent as 0; a route that configures no med carries none |
| LOCAL_PREF | 5 | local-preference |
Local preference, sent to iBGP peers only. A configured local-preference 0 is sent as 0; a route that configures none carries 100 |
| ATOMIC_AGGREGATE | 6 | atomic-aggregate |
Atomic aggregate flag |
| AGGREGATOR | 7 | aggregator |
Aggregator ASN:IP |
| COMMUNITY | 8 | community |
Standard communities |
| ORIGINATOR_ID | 9 | originator-id |
Route reflector originator |
| CLUSTER_LIST | 10 | cluster-list |
Route reflector cluster list |
| MP_REACH_NLRI | 14 | none | Multiprotocol reachable NLRI |
| MP_UNREACH_NLRI | 15 | none | Multiprotocol unreachable NLRI |
| EXTENDED_COMMUNITY | 16 | extended-community |
Extended communities |
| LARGE_COMMUNITY | 32 | large-community |
Large communities (RFC 8092) |
| PREFIX_SID | 40 | prefix-sid |
Segment Routing prefix SID |