SRv6 (Segment Routing over IPv6)
Ze receives BGP routes carrying SRv6 Prefix-SID attributes (RFC 8669, RFC 9252),
extracts SRv6 SIDs, validates them, and programs ingress encapsulation into the
FIB. Static route configuration and update text can also advertise an explicit
Service SID. Ze does not allocate local SIDs or install egress endpoint behaviors.
| Feature | Description |
|---|---|
| Attribute parsing | PrefixSID (code 40) stored as opaque bytes; SRv6 SID extracted lazily at best-path time |
| L3/L2 Service TLVs | Types 5 (L3 Service) and 6 (L2 Service) per RFC 9252 Section 3.1 |
| SID extraction | First SRv6 SID Information Sub-TLV (type 1) within the Service TLV |
| Transposition | SID Structure Sub-Sub-TLV reconstructs full SID from NLRI label bits (VPN/EVPN) |
| Path ineligibility | Route with SRv6 TLVs but no valid SID excluded from best-path selection |
| SID resolvability | SRv6 SID must have a covering route in Loc-RIB before FIB installation |
| EBGP filtering | PrefixSID from EBGP peers discarded unless accept-srv6-prefix-sid is set |
| EBGP propagation | PrefixSID removed on every rail that writes an UPDATE unless propagate-srv6-prefix-sid is set: the two forward rails, the two origination rails, and the API/readvertise announce rail |
| Validation | Malformed SRv6 Service TLVs trigger treat-as-withdraw (RFC 9252 Section 3.4) |
| Propagation | PrefixSID preserved on zero-copy forward; stripped when the next-hop changes, and stripped at the SR domain boundary |
| Linux FIB | SEG6 lwtunnel encap via netlink |
| VPP FIB | SR steering policy via GoVPP sr_steering_add_del |
Configuration
EBGP peers require explicit opt-in, in each direction. IBGP peers accept and advertise PrefixSID by default.
bgp {
peer pe1 {
session {
accept-srv6-prefix-sid true
propagate-srv6-prefix-sid true
}
}
}
| Option | Location | Default | Description |
|---|---|---|---|
accept-srv6-prefix-sid |
bgp/peer/session |
false |
Accept PrefixSID attribute from this EBGP peer (RFC 8669 Section 4) |
propagate-srv6-prefix-sid |
bgp/peer/session |
false |
Advertise PrefixSID attribute to this EBGP peer (RFC 8669 Section 8) |
Both leaves say the same thing about one neighbor: it is inside ze's SR domain. RFC 8669 Section 8 puts the boundary at "a single SR/administrative domain that may include one or more ASes", so the boundary is not the AS boundary and ze cannot derive it from the ASN pair. Set both leaves on an EBGP neighbor that is part of the same SR domain, and leave both unset on every other EBGP neighbor. Set neither on an IBGP peer: the section governs propagation to other ASes, so it does not reach a peer in this one.
No additional configuration is needed for IBGP sessions or for FIB programming. When an SRv6 SID is present on a best-path route and the SID is resolvable, the FIB backend programs the encapsulation automatically.
Explicit Service SID advertisement
The bgp-prefix-sid-srv6 route attribute accepts an IPv6 Service SID, an optional
endpoint behavior, and an optional SID structure:
bgp-prefix-sid-srv6 ( l3-service 2001:db8:1:2:: 0x13 [64,0,32,0,16,64] )
The six structure fields are Locator Block Length, Locator Node Length, Function Length, Argument Length, Transposition Length, and Transposition Offset, in bits. The example advertises End.DT4 with 16 function bits supplied separately in the NLRI label field. Those bits must already be zero in the configured SID; Ze rejects a conflicting SID rather than discarding its bits. A zero Transposition Length requires a zero offset, and the structure must fit within 128 bits.
Argument Length must be zero except for End.DT2M (0x18), whose Arg.FE2 carries
the egress Ethernet-segment filtering argument. An endpoint behavior unknown to
the encoder can be advertised without arguments. This is explicit signaling,
not local endpoint installation: the configured SID must belong to an endpoint
provisioned outside this ingress FIB path.
Per-neighbor service export
Use a peer's export chain to control which SRv6 services it receives. Match the
service's Route Target with community-match; rejecting a match withholds the
whole route, not just its Prefix-SID attribute:
bgp {
policy {
community-match SERVICE-20 {
entry target:65000:10 { type extended; action reject; }
entry target:65000:20 { type extended; action accept; }
}
}
peer pe1 {
filter { export [ community-match:SERVICE-20 ]; }
}
}
This peer receives service 20 but not service 10. Other peers can use different
lists or no filter. Community-match lists deny unmatched routes, so include
each service the peer should receive. This route-level control is separate from
propagate-srv6-prefix-sid, which only controls the attribute at an EBGP SR
domain boundary.
Data Flow
BGP UPDATE with PrefixSID (attr 40)
|
v
Wire parser: stores PrefixSID in OtherAttrs (opaque bytes)
|
v
RFC 7606 validator: checks TLV structure, rejects malformed
|
v
EBGP filter: discards attr 40 unless accept-srv6-prefix-sid is set
|
v
RIB best-path: IsSRv6Ineligible() excludes routes with broken SRv6 TLVs
|
v
Best-path emission: lookupSRv6SIDForBest() extracts SID from OtherAttrs
| For VPN/EVPN: applies transposition (label bits -> SID function)
|
v
sysrib: stores srv6SID on protocolRoute, tracks SID for resolution
| Suppresses FIB emission if SID has no covering route in Loc-RIB
| Cascade re-evaluates when SID reachability changes
|
v
FIB backend:
Linux: netlink.SEG6Encap{Mode: encap, Segments: [SID]}
VPP: sr.SrSteeringAddDel{BsidAddr: SID, TrafficType: IPv4/IPv6}
The egress side is a separate decision, taken once per destination peer:
Route selected for a destination peer
|
v
prefixSIDAllowedTo(isIBGP, propagate-srv6-prefix-sid)
| true -> attr 40 goes out unchanged
| false -> attr 40 is removed for this peer alone
v
Forward rails: applyFactsPrefixSID records an attribute suppression
Origination rails: the configured PrefixSID and any raw attribute 40 are dropped
The API and readvertise announce rail
The fifth rail asks the same question at the same site.
buildBatchAnnounceUpdate (internal/component/bgp/reactor/reactor_api_batch.go)
copies the caller's attribute block verbatim, so "say nothing" would emit
attribute 40; it drops the code when prefixSIDAllowedTo answers no, beside the
RFC 4271 Section 5.1.5 LOCAL_PREF drop. The destination's leaf joins
announceBuildKey, so two peers of one update group that answer differently no
longer share a built UPDATE. The rail carries an API announce, a grouped
announce, and the RFC 9494 stale readvertise (sendStaleReadvertise), which
replays a stored received block.
Transposition (VPN/EVPN)
For SAFI 128 (VPN) and SAFI 70 (EVPN), RFC 9252 Section 3.2.1 specifies that part of the SRv6 SID function bits are encoded in the MPLS label field of the NLRI instead of in the SID Information Sub-TLV. Ze reconstructs the full SID:
- Extract partial SID from SID Information Sub-TLV
- Read transposition parameters from SID Structure Sub-Sub-TLV (offset, length)
- Read label from NLRI (stored as side-data in PeerRIB)
- OR label bits into SID at the specified bit offset
When Transposition Length is 0, no reconstruction is needed (the full SID is in the Sub-TLV). This is the common case for IPv6 unicast.
FIB Backends
Linux Kernel
Routes with SRv6 SID are installed with SEG6 lightweight tunnel encapsulation:
ip route add <prefix> via <nexthop> encap seg6 mode encap segs <SID>
Implemented via netlink.SEG6Encap in buildRichRoute. A valid SRv6 Service SID
selects IPv6 encapsulation even when the NLRI carries labels. Those fields can
contain transposed SID bits and are not MPLS forwarding labels.
VPP
Routes with SRv6 SID are steered via VPP's SR policy infrastructure:
sr_steering_add_del bsid=<SID> prefix=<prefix> traffic_type=IPv4|IPv6
Implemented via GoVPP sr.SrSteeringAddDel. Requires go.fd.io/govpp/binapi/sr
(vendored). SRv6 steering takes precedence over both MPLS and plain routes in
the VPP dispatch logic.
RFC Compliance
RFC 8669 (Prefix-SID Attribute)
| Requirement | Section | Status |
|---|---|---|
| Attribute code 40, optional transitive | 3 | Implemented |
| TLV format: 1B type + 2B length | 3 | Implemented |
| Unknown TLVs preserved on propagation | 3 | Implemented (opaque forwarding) |
| EBGP: discard unless configured to accept | 4 | Implemented (accept-srv6-prefix-sid) |
| Propagation to other ASes explicitly configured | 8 | Implemented (propagate-srv6-prefix-sid): every rail that writes an UPDATE asks |
| Malformed attribute: attribute-discard | 6 | Implemented (RFC 7606 validator) |
RFC 9252 (SRv6 Overlay Services)
| Requirement | Section | Status |
|---|---|---|
| L3 Service TLV (type 5) | 3.1 | Implemented |
| L2 Service TLV (type 6) | 3.1 | Implemented |
| SID Information Sub-TLV (type 1) | 3.2 | Implemented |
| First SID Sub-TLV preferred | 3.2 SHOULD | Implemented |
| SID Structure Sub-Sub-TLV | 3.2.1 | Implemented |
| Transposition reconstruction | 3.2.1 | Implemented (VPN/EVPN) |
| LBL+LNL+FL+AL <= 128 validation | 3.2.1 | Implemented (errata 7817) |
| NH unchanged: preserve TLVs | 3.3 | Implemented (zero-copy forward) |
| NH changed: strip PrefixSID | 3.3 | Implemented (AttrModSuppress) |
| Malformed Service TLV: treat-as-withdraw | 3.4 | Implemented |
| Path ineligibility (no valid SID) | 5 | Implemented |
| SID resolvability before best-path selection | 5 | ∿ |
Limitations
-
SID reachability is a FIB guard, not a BGP selection filter. Losing the covering route withdraws the installed service route; restoring reachability permits installation again. The guard runs after BGP selects a path, so it cannot choose a reachable alternative over an unreachable selected SID.
-
No local SID allocation or endpoint installation. Ze can advertise an explicitly configured SID but does not provision its egress behavior. When re-advertising with a changed next-hop, PrefixSID is stripped.
-
No SRv6 capability negotiation. PrefixSID is optional-transitive, so it propagates without negotiation. Ze does not signal SRv6 support via capabilities.
-
No SRv6 policy. Ze programs single-SID encapsulation. SRv6 segment lists (multi-hop SR paths) are not supported.