From e994e72b4a0d1c927d949e51196e55bc6d29182d Mon Sep 17 00:00:00 2001 From: Shyam Sethuram Date: Thu, 2 Jul 2026 12:13:24 +0530 Subject: [PATCH] HLD for SRv6 full-length SID support --- doc/srv6/images/srv6_static_sid_flow.png | Bin 0 -> 80684 bytes doc/srv6/srv6_fullsid_hld.md | 780 +++++++++++++++++++++++ 2 files changed, 780 insertions(+) create mode 100644 doc/srv6/images/srv6_static_sid_flow.png create mode 100644 doc/srv6/srv6_fullsid_hld.md diff --git a/doc/srv6/images/srv6_static_sid_flow.png b/doc/srv6/images/srv6_static_sid_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..bdd4765b204b71583d5f841917de53666ea4d3a0 GIT binary patch literal 80684 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 W8~DeW?wJd&Y%$O^)p@Dq9QA)s>^iUj literal 0 HcmV?d00001 diff --git a/doc/srv6/srv6_fullsid_hld.md b/doc/srv6/srv6_fullsid_hld.md new file mode 100644 index 00000000000..dd162331647 --- /dev/null +++ b/doc/srv6/srv6_fullsid_hld.md @@ -0,0 +1,780 @@ +# SRv6 with Full-Length SIDs High-Level Design + +## Table of Contents + +- [1. Revision](#1-revision) +- [2. Scope](#2-scope) +- [3. Definitions/Abbreviations](#3-definitionsabbreviations) +- [4. Overview](#4-overview) +- [5. Requirements](#5-requirements) + - [5.1 Functional requirements](#51-functional-requirements) + - [5.2 Exemptions (not supported)](#52-exemptions-not-supported) +- [6. Architecture Design](#6-architecture-design) +- [7. High-Level Design](#7-high-level-design) + - [7.1 Modules modified](#71-modules-modified) + - [7.2 High level flow](#72-high-level-flow) +- [8. SAI API](#8-sai-api) +- [9. Configuration and Management](#9-configuration-and-management) + - [9.1 YANG Models](#91-yang-models) + - [9.1.1 Global settings](#911-global-settings) + - [9.1.2 Locators](#912-locators) + - [9.1.3 Static SIDs](#913-static-sids) + - [9.2 DB Tables](#92-db-tables) + - [9.2.1 Global settings](#921-global-settings) + - [9.2.2 Locators](#922-locators) + - [9.2.3 Static SIDs](#923-static-sids) + - [9.2.6 Segment Lists](#926-segment-lists) + - [9.3 CLI](#93-cli) + - [9.3.1 Configuration commands](#931-configuration-commands) + - [9.3.2 Show commands](#932-show-commands) +- [10. Detailed Design](#10-detailed-design) + - [10.1 bgpcfgd (SRv6Mgr / Srv6GlobalMgr)](#101-bgpcfgd-srv6mgr--srv6globalmgr) + - [10.2 frr-mgmt-framework (frrcfgd)](#102-frr-mgmt-framework-frrcfgd) + - [10.3 fpmsyncd (routesync)](#103-fpmsyncd-routesync) + - [10.4 orchagent (srv6orch)](#104-orchagent-srv6orch) + - [10.5 sonic-utilities CLI](#105-sonic-utilities-cli) + - [10.6 Example end-to-end sequence](#106-example-end-to-end-sequence) +- [11. Warmboot and Fastboot Design Impact](#11-warmboot-and-fastboot-design-impact) +- [12. Memory Consumption](#12-memory-consumption) +- [13. Restrictions/Limitations](#13-restrictionslimitations) +- [14. Testing Requirements/Design](#14-testing-requirementsdesign) + - [14.1 Yang model tests](#141-yang-model-tests) + - [14.2 CLI tests](#142-cli-tests) + - [14.3 DVS tests](#143-dvs-tests) + - [14.4 sonic-mgmt tests](#144-sonic-mgmt-tests) +- [15. Open/Action Items](#15-openaction-items) + +## 1. Revision + +| Rev | Date | Author | Change Description | +|:---:|:----------:|:---------------|:--------------------------------------------| +| 0.1 | 2026-06-26 | Shyam Sethuram, Manoharan Sundaramoorthy, Ravindra Bikkina | Initial version | + +## 2. Scope + +This document describes the incremental design that extends SONiC's existing +SRv6 implementation with support for **full-SIDs** (full-length SIDs). + +The base SRv6 design in SONiC is uSID (micro-segment) centric and is documented +in the existing HLDs: + +- [srv6_hld.md](srv6_hld.md) — base SRv6 architecture, CONFIG_DB/APPL_DB/ASIC_DB + pipeline and `srv6orch`. +- [srv6_static_config_hld.md](srv6_static_config_hld.md) — static + `SRV6_MY_LOCATORS` / `SRV6_MY_SIDS` configuration and `bgpcfgd` rendering to + FRR. +- [srv6_sid_l3adj.md](srv6_sid_l3adj.md) — adjacency (`End.X` / `uA`) SID + handling. + + +**In scope:** + +- A `full_sid` locator attribute that classifies a locator as either a uSID + (micro-segment) locator or a full-SID (non-micro-segment) locator. +- Full-SID endpoint behaviors `End` and `End.X`, together with their `PSP`, + `USP` and `USD` flavors. +- The YANG, CONFIG_DB, APPL_DB and ASIC_DB schema deltas required to carry + full-SID locators, SIDs and flavors end-to-end. +- The CONFIG_DB → `bgpcfgd`/`frrcfgd` → FRR → `fpmsyncd` → + APPL_DB → `srv6orch` → SAI programming pipeline. +- `config` / `show` CLI for the above + +**Out of scope:** + +- The internal FRR (`zebra`, `mgmtd`, `pathd`, `staticd`) implementation of + SRv6/SR-TE. FRR design and code changes will be posted separately. + +## 3. Definitions/Abbreviations + +| Term | Definition | +|:-------------|:---------------------------------------------------------------------------------| +| SRv6 | Segment Routing over the IPv6 dataplane (RFC 8986). | +| SID | Segment Identifier | +| Full-SID | Full-length (non-micro-segment) SID; one behavior per 128-bit IPv6 address. | +| uSID | Micro-segment SID; multiple short SIDs packed into one 128-bit address. | +| Locator | IPv6 prefix block from which SIDs are allocated. | +| Block / Node / Function / Argument | The four length fields that partition a locator/SID. | +| End | Endpoint behavior: decrement Segments-Left and forward via the SRH. | +| End.X | Endpoint behavior with L3 cross-connect to a specific adjacency (Adj-SID). | +| uN | uSID equivalent of `End` SID | +| uA | uSID equivalent of `End.X` SID | +| uDT4/6/46 | uSID decapsulation + IPv4/IPv6/IP table (VRF) lookup. | +| PSP/USP/USD | Penultimate-Segment-Pop / Ultimate-Segment-Pop / Ultimate-Segment-Decap flavors. | + +## 4. Overview + +SONiC's SRv6 support was introduced as a uSID-first design: a locator was +implicitly a micro-segment locator and only the compressed `uN`/`uA`/`uDT` +behaviors were exposed through the YANG model and CLI. The orchagent already +contained the SAI mappings for the full-length `End`/`End.X` behaviors, but +there was no way to configure them: there was no locator type attribute, the +YANG `action` enum did not include `End`/`End.X`, and the `config srv6` CLI did +not exist. + +This feature adds support for **full-length SIDs**, where each SID +is a dedicated `/128` IPv6 address carrying a single behavior (`End`, `End.X`) +and an optional `PSP`/`USP`/`USD` flavor. The end-to-end programming pipeline is unchanged. + + +## 5. Requirements + +### 5.1 Functional requirements + +1. A locator must be classifiable as either a uSID (micro-segment) locator or a + full-SID (non-micro-segment) locator, defaulting to uSID for backward compatibility. +2. Full-SID locators must support the `End` and `End.X` endpoint behaviors. +3. `End`/`End.X` SIDs must support the `PSP`, `USP` and `USD` flavors and the + compound `PSP.USD` flavor. +4. Full-SIDs must be `/128` prefixes. uSID actions retain their existing + (shorter) prefix-length rules. +5. The system must reject mixing full-SID behaviors on a uSID locator and + vice-versa, and must enforce this at the YANG, `bgpcfgd`, `frrcfgd` and CLI + layers. +6. `End.X` (and its flavor variants) and `uA` must take an egress interface and + MAY take an explicit adjacency (next-hop) address. +7. Existing uSID configuration and behavior must be unaffected. + +### 5.2 Exemptions (not supported) + +- Dynamic candidate-paths are not supported +- SR-TE segment types other than `ipv6-address` (Type B) — other NAI/MPLS + segment types are reserved in YANG but not implemented in the backend. +- `End.T` / `End.DT*` / `End.DX*` full-length behaviors are not surfaced through + the SONiC YANG/CLI. The SAI mappings exist in `srv6orch` but are not exposed as + configurable `behavior` values. + +## 6. Architecture Design + +The overall SONiC SRv6 architecture is not changed by this feature. +Full-SID support slots into the existing control-plane pipeline and reuses the +existing orchagent and SAI objects. The configuration-to-ASIC_DB pipeline below is +adapted from [srv6_hld.md](srv6_hld.md). + +![SRv6 CONFIG_DB to ASIC_DB pipeline (adapted from srv6_hld.md)](images/srv6_static_sid_flow.png) + + +## 7. High-Level Design + +### 7.1 Modules modified + +This feature touches the following repositories/modules: + +| Repository | Change | +|:---------------------------|:----------------------------------------------------------------------| +| `sonic-yang-models` | `sonic-srv6.yang` | +| `sonic-swss` | `End`/`End.X` behavior + `PSP`/`USP`/`USD` flavor programming; | +| `sonic-bgpcfgd` | Locator/SID rendering to FRR CLI; global encap source. | +| `sonic-frr-mgmt-framework` | Locator/SID rendering to FRR CLI; global encap source. | +| `sonic-utilities` | `config srv6`, `show srv6` | + +### 7.2 High level flow + +The control/data path for full-SIDs is: + +1. **CONFIG_DB** receives full-SID locators (`SRV6_MY_LOCATORS`), static SIDs + (`SRV6_MY_SIDS`), global settings (`SRV6_GLOBAL`) +2. **bgpcfgd** (`SRv6Mgr`, `Srv6GlobalMgr`) and/or **frrcfgd** subscribe to + these CONFIG_DB tables and render FRR `segment-routing srv6` / + `segment-routing traffic-eng` CLI, which they push to FRR via `vtysh`. +3. **FRR** `zebra` for locators, `mgmtd`/`staticd` for static SIDs, + owns SID allocation +4. **fpmsyncd** receives the resulting SIDs/routes from FRR and writes them into + **APPL_DB** `SRV6_MY_SID_TABLE` +5. **srv6orch** consumes APPL_DB, resolves behaviors/flavors and programs the + SAI `ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY`, `ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST` objects into **ASIC_DB**. + + +## 8. SAI API + +**No new SAI API is introduced.** Full-SID support uses the existing +`ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY` and `ASIC_STATE:SAI_OBJECT_TYPE_SRV6_SIDLIST` objects and +the already-standardized endpoint-behavior / flavor enumerations. + +Endpoint behaviors used (set via `SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR`), +mapped in `srv6orch`'s `end_behavior_map`: + +| SONiC action (APPL_DB, lowercased) | SAI endpoint behavior | +|:-----------------------------------|:-----------------------------------------| +| `end` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_E` | +| `end.x` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_X` | + +Flavors used (set via `SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR`), mapped +in `end_flavor_ops_map`: + +| SONiC flavor | SAI flavor | +|:-------------|:--------------------------------------------------------| +| `PSP` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP` | +| `USP` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_USP` | +| `USD` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_USD` | +| `PSP.USD` | `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_PSP_AND_USD` | + +`End.X` additionally programs a next-hop (`SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID`) resolved from the +configured interface/adjacency. + + +## 9. Configuration and Management + +### 9.1 YANG Models + +#### 9.1.1 Global settings + +Model `sonic-srv6.yang` + + +``` + container sonic-srv6 { + container SRV6_GLOBAL { + description "Global SRv6 configuration parameters"; + + list SRV6_GLOBAL_LIST { + max-elements 1; + key "name"; + + leaf name { + type string { + pattern "default"; + } + description "Global configuration key (must be 'default')"; + } + + leaf encap_source_address { + type inet:ipv6-address; + description "Global IPv6 source address for SRv6 encapsulation"; + } + + leaf device_encap_mode { + type enumeration { + enum regular { + description "Standard SRv6 encapsulation at head-end (H.Encaps)"; + } + enum reduced { + description "Reduced SRv6 encapsulation at head-end (H.Encaps.Red)"; + } + enum all { + description "All head-end SRv6 encapsulation types are allowed"; + } + } + default "all"; + description "SRv6 encapsulation mode. Boot-time only — requires config reload to change."; + } + + leaf device_srv6_enabled { + type boolean; + default false; + description "Whether SRv6 is enabled on this device. Boot-time only — requires swss restart to take effect."; + } + } + } + } +``` + +#### 9.1.2 Locators + +Model `sonic-srv6.yang` + + +``` + container sonic-srv6 { + container SRV6_MY_LOCATORS { + description "SRv6 locator definitions partitioning the SID address space."; + + list SRV6_MY_LOCATORS_LIST { + key "locator_name"; + + leaf locator_name { + description "SRv6 locator name."; + type string; + } + + leaf prefix { + description "IPv6 address prefix for this locator."; + type inet:ipv6-prefix; + mandatory true; + } + + leaf block_len { + description "Length in bits of the SRv6 locator block portion."; + type uint8 { + range "1..128"; + } + + default 32; + } + + leaf node_len { + description "Length in bits of the SRv6 locator node portion."; + type uint8 { + range "1..128"; + } + + default 16; + } + + leaf func_len { + description "Length in bits of the SRv6 SID function portion."; + type uint8 { + range "0..128"; + } + + default 16; + } + + leaf arg_len { + description "Length in bits of the SRv6 SID argument portion."; + type uint8 { + range "0..128"; + } + + default 0; + } + + must 'block_len + node_len + func_len + arg_len <= 128'; + + leaf vrf { + type union { + type leafref { + path "/vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name"; + } + type string { + pattern 'default'; + } + } + description "VRF name"; + + default "default"; + } + + leaf full_sid { + type boolean; + description "Mark this locator as a full-length SID (non-uSID) locator."; + default false; + } + } + } + } +``` + +#### 9.1.3 Static SIDs + +Model `sonic-srv6.yang` + + +``` + container sonic-srv6 { + container SRV6_MY_SIDS { + description "Local SRv6 SID entries with endpoint behavior and decapsulation settings."; + + list SRV6_MY_SIDS_LIST { + key "locator ip_prefix"; + + leaf ip_prefix { + description "IPv6 prefix representing this SID."; + type inet:ipv6-prefix; + } + + leaf locator { + description "Reference to the parent SRv6 locator."; + type leafref { + path "/srv6:sonic-srv6/srv6:SRV6_MY_LOCATORS/srv6:SRV6_MY_LOCATORS_LIST/srv6:locator_name"; + } + } + + leaf action { + description "SRv6 endpoint behavior (uN for prefix SID, uDT46 for decap with VRF lookup)."; + type enumeration { + enum uN; + enum uA; + enum uDT4; + enum uDT6; + enum uDT46; + enum End; + enum End.PSP; + enum End.USD; + enum End.PSP.USD; + enum End.X; + enum End.X.PSP; + enum End.X.PSP.USD; + } + } + + leaf decap_vrf { + type union { + type leafref { + path "/vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name"; + } + type string { + pattern 'default'; + } + } + description "VRF name used for decapsulation"; + + default "default"; + } + + leaf decap_dscp_mode { + description "DSCP handling mode for decapsulated packets."; + type enumeration { + enum uniform; + enum pipe; + } + } + + leaf interface { + type union { + type leafref { + path "/port:sonic-port/port:PORT/port:PORT_LIST/port:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + // Avoid VLAN leaf reference here until libyang back-links issue is resolved, and + // use VLAN string pattern instead + type string { + pattern 'Vlan([0-9]{1,3}|[1-3][0-9]{3}|[4][0][0-8][0-9]|[4][0][9][0-4])'; + } + } + description "Reference of interface used by uA/End.X SIDs"; + } + + // Constraint: Interface is mandatory for End.X-based and uA actions + must "(action = 'uA' or action = 'End.X' or action = 'End.X.PSP' or action = 'End.X.PSP.USD') = (boolean(interface))" { + error-message "interface is applicable and mandatory only for 'uA', 'End.X' related actions"; + } + + // Constraint: Prefix length must be /128 for regular SIDs + must "(starts-with(action, 'u')) or (substring-after(ip_prefix, '/') = '128')" { + error-message "Prefix length must be /128 for non-uSID actions"; + } + + // Constraint: Cannot configure full-SIDs with uSID locator, or vice-versa + must "(starts-with(action, 'End')) = (/srv6:sonic-srv6/srv6:SRV6_MY_LOCATORS/srv6:SRV6_MY_LOCATORS_LIST[srv6:locator_name=current()/locator]/srv6:full_sid = 'true')" { + error-message "Cannot configure full-SIDs with uSID locator, or vice-versa"; + } + + leaf adj { + type inet:ipv6-address; + description "IPv6 adjacency address"; + } + } + } + } +``` + +### 9.2 DB Tables + +#### 9.2.1 Global settings + +``` +DB Name: CONFIG_DB +Table Name: SRV6_GLOBAL + +key = SRV6_GLOBAL|default + +device_srv6_enabled : # global SRv6 enable/disable +encap_source_address : # source address for SRv6 encapsulation +device_encap_mode : # SRv6 encapsulation mode +``` + +#### 9.2.2 Locators + +``` +DB Name: CONFIG_DB +Table Name: SRV6_MY_LOCATORS + +key = SRV6_MY_LOCATORS| + +block_len : # block length in bits +node_len : # node length in bits +func_len : # function length in bits +arg_len : # argument length in bits +prefix : # Locator IPv6 prefix +full_sid : # Indicates full-length SIDs +``` + +#### 9.2.3 Static SIDs + +``` +DB Name: CONFIG_DB +Table Name: SRV6_MY_SIDS + +key = SRV6_MY_SIDS|| + +action : # SID behavior and flavor +adj : # SID adjacency (IPv6 nexthop, for End.X) +interface : # SID outgoing interface (for End.X) +``` + +``` +DB Name: APPL_DB +Table Name: SRV6_MY_SID_TABLE + +key = SRV6_MY_SID_TABLE::::: + +action : # behavior defined for the local SID +flavor : # flavor associated with the SID behavior +vrf : # optional VRF name, can be empty +adj : # nexthop for End.X format, can be empty +``` + +``` +DB Name: ASIC_DB +Table Name: ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY + +key = ASIC_STATE:SAI_OBJECT_TYPE_MY_SID_ENTRY:{} + # JSON object: args_len, function_len, locator_block_len, locator_node_len, + # sid, switch_id, vr_id + +SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID : # optional nexthop OID +SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR : # programmed behavior +SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR : # programmed flavor +``` + + +### 9.3 CLI + +The `config srv6` and `show srv6` command groups are newly introduced. + +#### 9.3.1 Configuration commands + +#### 9.3.1.1 Global settings + +``` +- config srv6 global device_srv6_enabled { true | false } +- config srv6 global encap_source_address +- config srv6 global device_encap_mode { regular | reduced | all } +``` + +> Note: Changing the global SRv6 Enable status or the encapsulation mode requires +> one or more container restarts, and can result in temporary traffic loss. + + +#### 9.3.1.2 Locators + + +``` +- config srv6 locator add --block-len [ --node-len --function-len --argument-len --full-sid ] +- config srv6 locator del +``` + +#### 9.3.1.3 Static SIDs + +``` +- config srv6 static-sid add [ --interface --adjacency ] +- config srv6 static-sid del +``` + +#### 9.3.2 Show commands + +#### 9.3.2.1 Global settings + +``` +- show srv6 global +``` + +#### 9.3.2.2 Locators + +``` +- show srv6 locators [ ] +- show srv6 rib locators [ ] +``` + +#### 9.3.2.3 Static SIDs + +``` +- show srv6 static-sids [ | ] +- show srv6 rib sids [ ] +``` + +## 10. Detailed Design + +### 10.1 bgpcfgd (SRv6Mgr / Srv6GlobalMgr) + +`managers_srv6.py` renders CONFIG_DB data into FRR CLI. + +**Global encap.** `Srv6GlobalMgr` renders `SRV6_GLOBAL`'s +`encap_source_address` into FRR (`segment-routing srv6 encapsulation +source-address ..`), and emits `no source-address` when the field is dropped +from the row (handling the SET-that-drops-a-field case explicitly, since +swsscommon delivers SET rather than DEL while the row still has sibling fields +such as `device_encap_mode`). + +**Locator type.** `Locator.is_usid` is computed from the `full_sid` field, with +uSID as the default: + +```python +self.is_usid = data.get('full_sid', 'false').lower() != 'true' +``` + +`locators_set_handler()` emits +`segment-routing srv6 locators locator prefix

block-len .. node-len .. +func-bits ..` and appends `behavior usid` **only** when `locator.is_usid` is +true. A full-SID locator (`full_sid=true`) is therefore rendered without +`behavior usid`. + +**SID validation and rendering.** `sids_set_handler()`: + +- Confirms the action is in `supported_SRv6_behaviors` (the `uN`/`uA`/`uDT*` and + `End`/`End.X` set). +- Computes the locator prefix to validate against: for uSID actions it uses the + locator block (`prefix/block_len`); for full-SIDs it uses the full locator + prefix, then checks `supernet_of(sid_prefix)`. +- Rejects mismatches between behavior class and locator type + (`is_usid_behavior` vs `is_usid_locator`), and enforces the `uN` prefix-length + rule. +- Translates the YANG behavior name to FRR form via `translate_behavior_to_frr` + (replacing `.` with `_`, e.g. `End.X.PSP.USD` → `End_X_PSP_USD`) and + emits `segment-routing srv6 static-sids sid

locator behavior `. +- Appends `vrf ` for `uDT*`, and `interface [nexthop ]` for + `End.X*`/`uA` (failing if no interface is present). + + +### 10.2 frr-mgmt-framework (frrcfgd) + +`frrcfgd.py` provides an alternate config path to render FRR configs. +Its table-to-daemon routing is: + +```python +'SRV6_MY_LOCATORS': ['zebra'], +'SRV6_MY_SOURCE': ['zebra'], +'SRV6_MY_SIDS': ['mgmtd'], +'SR_TE_SEGMENT_LIST': ['pathd'], +``` + +**Locators / SIDs.** Locator rendering mirrors `bgpcfgd`: it appends +`behavior usid` unless `full_sid == 'true'`. SID rendering re-validates +behavior/locator consistency and the `uN` prefix-length rule, translates the +behavior name with `translate_behavior_to_frr`, and branches by action group: +`uDT*` add `vrf`, `End.X*`/`uA` add `interface [nexthop]`, and +`uN`/`End`/`End.PSP`/`End.USD`/`End.PSP.USD` emit the bare +`sid .. locator .. behavior ..` form. + +### 10.3 fpmsyncd (routesync) + +`routesync.cpp` consumes the FRR FPM SRv6 localSID netlink attributes and writes +the APPL_DB `SRV6_MY_SID_TABLE` row. For each local SID it emits the +`action`, `flavor`, `vrf` and `adj` field/value tuples (the `flavor` field is +the new carrier for the full-SID `PSP`/`USP`/`USD` operation derived from the +FRR `FLV_OPS` attribute). This is the mechanism by which the resolved full-SID flavor +reaches `srv6orch`. + +### 10.4 orchagent (srv6orch) + +**Local SIDs:** +`srv6orch` translates the APPL_DB full-SID behavior and flavor into SAI. The +string→SAI maps are the key data structures: + +- `end_behavior_map` maps the lowercased APPL_DB action to a + `sai_my_sid_entry_endpoint_behavior_t` +- `end` → `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_E` and `end.x` → `SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_X` (alongside + the existing `un`, `ua`, `udt4`, `udt6`, `udt46`, etc.). +- `end_flavor_ops_map` maps an **explicit** flavor string (`PSP`, `USP`, `USD`, + `PSP.USD`) to the corresponding SAI flavor. +- `end_flavor_map` supplies the **default** flavor when none is configured + +`doTaskMySidTable()` parses the APPL_DB entry, reading the `action`, `flavor`, +`vrf` and `adj` fields, and calls `createUpdateMysidEntry()`. +`sidEntryEndpointBehavior(action, flv_str, end_behavior, end_flavor)` resolves +the behavior from `end_behavior_map` and, for `End`/`End.X`, +applies the explicit `flv_str` from `end_flavor_ops_map` when present; for other +behaviors it applies the per-action default from `end_flavor_map`. + +`createUpdateMysidEntry()` then: + +- Builds the `sai_my_sid_entry_t` key from the + `block_len:node_len:function_len:args_len:sid` tokens of the APPL_DB key. +- Adds `SAI_MY_SID_ENTRY_ATTR_VRF` when `mySidVrfRequired()` (the `*DT*`/`T` + behaviors). +- Adds `SAI_MY_SID_ENTRY_ATTR_NEXT_HOP_ID` when `mySidNextHopRequired()` (the + `X`/`uA`/`DX*`/`B6*` behaviors) — for `End.X` this resolves the adjacency + next-hop, queuing the entry in `m_pendingSRv6MySIDEntries` if the neighbor is + not yet resolved. +- Adds an IP-in-IP tunnel when `mySidTunnelRequired()` (the `uN`/`uDT46` decap + cases) — unchanged from the uSID path and not applicable to `End`/`End.X`. +- Pushes `SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR` and, when the resolved flavor + is not `..._FLAVOR_NONE`, `SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR`. + + +### 10.5 sonic-utilities CLI + +`config/srv6.py` implements the `config srv6 global`, `config srv6 locator` +and `config srv6 static-sid` groups. +The global parameters `device_srv6_enabled`/`device_encap_mode` may result in the +restart of `swss` container; an explicit user confirmation is required. +`encap_source_address` is applied without a restart. + +`show/srv6.py` implements `show srv6 locators`, `show srv6 static-sids` (with the `Offloaded` column computed from +ASIC_DB), `show srv6 global` and `show srv6 stats` commands. +In order to view Zebra/RIB's state, use the commands `show srv6 rib locators` and +`show srv6 rib sids`. + +### 10.6 Example end-to-end sequence + +``` +config srv6 locator add loc1 dd:dd:dd:1::/64 --block-len 48 --node-len 16 --full-sid +config srv6 static-sid add dd:dd:dd:1:6000::/128 loc1 End.PSP + | + v CONFIG_DB: SRV6_MY_LOCATORS|loc1 (full_sid=true), SRV6_MY_SIDS|loc1|... + bgpcfgd (SRv6Mgr) / frrcfgd --vtysh--> FRR (zebra / mgmtd) + | locator rendered WITHOUT 'behavior usid'; sid behavior End_PSP + v FRR allocates the SID and programs dataplane intent + fpmsyncd (routesync) --> APPL_DB: SRV6_MY_SID_TABLE:48:16:16:0:dd:dd:dd:1:6000:: + | action=end, flavor=PSP, vrf="", adj="" + v + srv6orch.doTaskMySidTable -> createUpdateMysidEntry + | sidEntryEndpointBehavior: end -> BEHAVIOR_E, flavor PSP -> FLAVOR_PSP + v SAI my_sid_entry (BEHAVIOR=E, FLAVOR=PSP) + ASIC_DB (show srv6 static-sids => Offloaded=True) +``` + +## 11. Warmboot and Fastboot Design Impact + +No new mechanism is introduced for handling of My-SID objects. + +## 12. Memory Consumption + +When the feature is unused there is no additional memory consumption. + +## 13. Restrictions/Limitations + +- Full-SIDs must be IPv6 *'/128'* prefixes +- A locator cannot mix uSID and full-SID behaviors +- Only `explicit` SR-TE candidate paths and `ipv6-address` (Type B) segments are + supported; dynamic/PCE paths and other segment types are not. +- `End.T` / `End.DT*` / `End.DX*` full-length behaviors are not exposed via the + YANG/CLI in this increment. +- `device_encap_mode` / `device_srv6_enabled` are boot-time-only and require a + `swss` restart to take effect. + +## 14. Testing Requirements/Design + +SRv6 full-SID functionality is validated across multiple test layers spanning the submodules and at sonic-mgmt level. + +### 14.1 Yang model tests + +- sonic-yang-models/tests/yang_model_tests/tests/srv6.json + + +### 14.2 CLI tests + +- sonic-utilities/tests/show_srv6_state_test.py +- sonic-utilities/tests/config_srv6_test.py +- sonic-utilities/tests/show_run_srv6_test.py +- sonic-utilities/tests/show_srv6_test.py + +### 14.3 DVS tests + +- sonic-swss/tests/test_srv6.py + +### 14.4 sonic-mgmt tests + +- sonic-mgmt/tests/srv6/test_srv6_fullsid_basic.py + - covers decap, midpoint and encap packet forwarding + - IPv4/IPv6 (UDP) inner payload + - SID behaviors: `End`, `End.X` + - SID flavors: `PSP`, `USD`, `PSP.USD` + - Encap mode: `H.Encaps`, `H.Encaps.Red` + + +## 15. Open/Action Items + +None