From ed6c1c2e1326b71548e00008ea9da2f1843a8296 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 28 Nov 2024 11:06:46 -0800 Subject: [PATCH 01/26] init draft of srv6_static_config_hld.md --- doc/srv6/srv6_static_config_hld.md | 187 +++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 doc/srv6/srv6_static_config_hld.md diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md new file mode 100644 index 0000000000..d6478d69a6 --- /dev/null +++ b/doc/srv6/srv6_static_config_hld.md @@ -0,0 +1,187 @@ +# Static Configuration of SRv6 in SONiC HLD + +# Table of Contents + +- [List of Tables](#list-of-tables) +- [Revision](#revision) +- [Definition/Abbreviation](#definitionabbreviation) +- [About This Manual](#about-this-manual) +- [1 Introuduction and Scope](#1-introuduction-and-scope) +- [2 Feature Requirements](#2-feature-requirements) +- [2.1 Functional Requirements](#21-functional-requirements) +- [2.2 Configuration and Managment Requirements](#22-configuration-and-management-requirements) +- [2.3 Warm Boot Requirements](#23-warm-boot-requirements) +- [3 Feature Design](#3-feature-design) +- [3.1 ConfigDB Changes](#31-configdb-changes) +- [3.2 AppDB Changes](#32-appdb-changes) +- [3.3 Orchestration Agent Changes](#33-orchestration-agent-changes) +- [3.4 SAI](#34-sai) +- [3.5 YANG Model](#35-yang-model) +- [4 Unit Test](#4-unit-test) +- [5 References ](#5-references) + +# Revision + +| Rev | Date | Author | Change Description | +| :--: | :-------: | :------------------------: | :---------------------: | +| 0.1 | 12/5/2024 | Changrong Wu | Initial version | + + +# Definition/Abbreviation + +### Table 1: Abbreviations + +| ****Term**** | ****Meaning**** | +| -------- | ----------------------------------------- | +| BGP | Border Gateway Protocol | +| SID | Segment Identifier | +| SRH | Segment Routing Header | +| SRv6 | Segment Routing IPv6 | +| SDN | Software Defined Network | +| uSID | Micro Segment | +| VNI | VXLAN Network Identifier | +| VRF | Virtual Routing and Forwarding | + +# About this Manual + +This document provides general information about the design of the enhancements in SONiC to support static configuration of Segmentation Routing over IPv6 protocol, which is crucial for SRv6 SDN deployment (without usage of BGP). + +# 1 Introuduction and Scope + +This document describes the high-level design of the new features in SONiC to support SRv6 SDN. +The new features include the addtion of a new table in CONFIG_DB to allow static configuration of SRv6 and the enhancement of bgpcfgd to program FRR with input from CONFIG_DB. +Besides, this document also define new YANG model specification and unit-test cases used to validate the aforementioned features. + + +# 2 Feature Requirements + +## 2.1 Functional Requirements + +Provide ability to statically configure SRv6 SIDs for block IDs, locators and local functions from CONFIG_DB. + +## 2.2 Configuration and Management Requirements + +1. User should be able to statically configure block length, locator length and function length for SRv6. + +2. User should be able to statically configure a number of SIDs/uSIDs for the local functions of the switch. + +## 2.3 Warm Boot Requirements + +Warm reboot is intended to be supported for planned system warm reboot. + + + +# 3 Feature Design + +At the time of writing this document, FRR has been able to program the SRv6 related tables in APPL_DB through fpmsyncd. +However, there is still one gap preventing SONiC being utilized for SRv6 SDN deployment. +Specifically, there is no interface in the configuration framework of SONiC allowing users to directly add configuration for SRv6 without involving BGP. + +In this document, we first define a new **SRV6_MY_SID_TABLE** table in CONFIG_DB that serves as the configuration source of SRv6 in SONiC. +Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile information in CONFIG_DB to configurations of FRR. +To verify the correctness of the aforementioned flow, we also define the relevant YANG model specification. + +## 3.1 ConfigDB Table Definition + + +**SRV6_MY_SID_TABLE** + +Description: New table to hold local SID definition and SID to behavior mapping. (A redefinition of SRV6_MY_SID_TABLE in [SRv6_HLD](./srv6_hld.md)) + +Schema: + +``` +; New table +; holds local SID to behavior mapping, allow 1:1 or n:1 mapping + +key = SRV6_MY_SID_TABLE|ipv6address +; field = value +block_len = blen ; bit length of block portion in address, default 32 +node_len = nlen ; bit length of node ID portion in address, default 16 +func_len = flen ; bit length of function portion in address, default 16 +action = behavior ; behaviors defined for local SID +vrf = VRF_TABLE.key ; VRF name for END.DT46, can be empty +adj = address, ; Optional, list of adjacencies for END.X +policy = SRV6_POLICY.key ; Optional, policy name for END.B6.ENCAP +source = address, ; Optional, list of src addrs for encap for END.B6.ENCAP + +For example: + "SRV6_MY_SID_TABLE" : { + "FCBB:BBBB:20::" : { + "action": "end" + }, + "FCBB:BBBB:20:F1::" : { + "action": "end.dt46", + "vrf": "VRF-1001" + }, + "FCBB:BBBB:20:F2::" : { + "action": "end.dt46", + "vrf": "VRF-1001" + }, + "FCBB:BBBB:20:F3::" : { + "action": "end.x", + "adj": [ + FCBB:BBBB:10::1, + FCBB:BBBB:10::2 + ], + } + } +``` + + +## 3.2 Bgpcfgd changes + + + + +## 3.3 YANG Model +``` +module: sonic-srv6 + +--rw sonic-srv6 + +--rw SRV6_SID_LIST + | +--rw SRV6_SID_LIST_LIST* [name] + | +--rw name string + | +--rw path* inet:ipv6-address + +--rw SRV6_MY_SID + | +--rw SRV6_MY_SID_LIST* [ip-address] + | +--rw ip-address inet:ipv6-address + | +--rw block_len? uint16 + | +--rw node_len? uint16 + | +--rw func_len? uint16 + | +--rw arg_len? uint16 + | +--rw action? enumeration + | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name + | +--rw adj* inet:ipv6-address + | +--rw policy? -> /sonic-srv6/SRV6_POLICY/SRV6_POLICY_LIST/name + | +--rw source? inet:ipv6-address + +--rw SRV6_POLICY + | +--rw SRV6_POLICY_LIST* [name] + | +--rw name string + | +--rw segment* -> /sonic-srv6/SRV6_SID_LIST/SRV6_SID_LIST_LIST/name + +--rw SRV6_STEER + +--rw SRV6_STEER_LIST* [vrf-name ip-prefix] + +--rw vrf-name -> /vrf:sonic-vrf/VRF/VRF_LIST/name + +--rw ip-prefix union + +--rw policy? -> /sonic-srv6/SRV6_POLICY/SRV6_POLICY_LIST/name + +--rw source? inet:ipv6-address +``` + +## 4 Unit Test + +TBD + +## 5 References + +- [SAI IPv6 Segment Routing Proposal for SAI 1.2.0](https://github.com/opencomputeproject/SAI/blob/1066c815ddd7b63cb9dbf4d76e06ee742bc0af9b/doc/SAI-Proposal-IPv6_Segment_Routing-1.md) + +- [RFC 8754](https://tools.ietf.org/html/rfc8754) +- [RFC 8986](https://www.rfc-editor.org/rfc/rfc8986.html) +- [draft-filsfils-spring-segment-routing-policy](https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-06) + +- [draft-ali-spring-bfd-sr-policy-06](https://tools.ietf.org/html/draft-ali-spring-bfd-sr-policy-06) + +- [draft-filsfils-spring-net-pgm-extension-srv6-usid](https://tools.ietf.org/html/draft-filsfils-spring-net-pgm-extension-srv6-usid-08) + +- [draft-cl-spring-generalized-srv6-for-cmpr](https://tools.ietf.org/html/draft-cl-spring-generalized-srv6-for-cmpr-02) + + From cb0a83dcb21b4c2674d36d1b8435b0ef79eed9fb Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 28 Nov 2024 21:27:26 -0800 Subject: [PATCH 02/26] add description for bgpcfgd changes and enrich the high-level picture --- doc/srv6/srv6_static_config_hld.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index d6478d69a6..a7ce29b6d3 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -75,13 +75,18 @@ Warm reboot is intended to be supported for planned system warm reboot. At the time of writing this document, FRR has been able to program the SRv6 related tables in APPL_DB through fpmsyncd. However, there is still one gap preventing SONiC being utilized for SRv6 SDN deployment. -Specifically, there is no interface in the configuration framework of SONiC allowing users to directly add configuration for SRv6 without involving BGP. +Specifically, there is no mechamism in SONiC allowing SDN controllers or users to directly add configuration for SRv6 without involving BGP. In this document, we first define a new **SRV6_MY_SID_TABLE** table in CONFIG_DB that serves as the configuration source of SRv6 in SONiC. -Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile information in CONFIG_DB to configurations of FRR. +Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile changes in CONFIG_DB to changes in the configurations of FRR. To verify the correctness of the aforementioned flow, we also define the relevant YANG model specification. +The workflow of the new mechanism is shown in the following diagram. -## 3.1 ConfigDB Table Definition +![Static SRv6 Config flow](images/SRv6_bgpcfgd.png) + +The design details of each step is described in the following subsections. + +## 3.1 New Table in ConfigDB **SRV6_MY_SID_TABLE** @@ -131,8 +136,8 @@ For example: ## 3.2 Bgpcfgd changes - - +To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_SID_TABLE** and compile the corresponding changes in FRR's configurations. +Following the naming convention of modules in bgpcfgd, we call this new module SRv6 Manager. ## 3.3 YANG Model ``` From 2301048d60e1e9f6a7f46206eae101d137333457 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 28 Nov 2024 21:27:48 -0800 Subject: [PATCH 03/26] add doc/srv6/images/SRv6_bgpcfgd.png --- doc/srv6/images/SRv6_bgpcfgd.png | Bin 0 -> 35592 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/srv6/images/SRv6_bgpcfgd.png diff --git a/doc/srv6/images/SRv6_bgpcfgd.png b/doc/srv6/images/SRv6_bgpcfgd.png new file mode 100644 index 0000000000000000000000000000000000000000..f92e6d597fdd0a08bd81517fb7b8ed895c7a40b5 GIT binary patch literal 35592 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'bJ4lg-TRu0pqFaEAxFJXy`40 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 P@zqp6b0X`HOMm_^!s?0x literal 0 HcmV?d00001 From 100b3fcfc104fdfa226d5aedecdd2972b5fee090 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Sat, 30 Nov 2024 14:07:08 -0800 Subject: [PATCH 04/26] refine YANG model definition and add UT test cases --- doc/srv6/srv6_static_config_hld.md | 52 ++++++++---------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index a7ce29b6d3..80c57d3277 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -91,7 +91,7 @@ The design details of each step is described in the following subsections. **SRV6_MY_SID_TABLE** -Description: New table to hold local SID definition and SID to behavior mapping. (A redefinition of SRV6_MY_SID_TABLE in [SRv6_HLD](./srv6_hld.md)) +Description: New table to hold local SID definition and SID to behavior mapping. (A simplified redefinition of SRV6_MY_SID_TABLE in [SRv6_HLD](./srv6_hld.md)) Schema: @@ -107,20 +107,18 @@ func_len = flen ; bit length of function portion in address, defaul action = behavior ; behaviors defined for local SID vrf = VRF_TABLE.key ; VRF name for END.DT46, can be empty adj = address, ; Optional, list of adjacencies for END.X -policy = SRV6_POLICY.key ; Optional, policy name for END.B6.ENCAP -source = address, ; Optional, list of src addrs for encap for END.B6.ENCAP For example: "SRV6_MY_SID_TABLE" : { "FCBB:BBBB:20::" : { - "action": "end" + "action": "uN" }, "FCBB:BBBB:20:F1::" : { - "action": "end.dt46", + "action": "uDT46", "vrf": "VRF-1001" }, "FCBB:BBBB:20:F2::" : { - "action": "end.dt46", + "action": "uDT46", "vrf": "VRF-1001" }, "FCBB:BBBB:20:F3::" : { @@ -141,52 +139,30 @@ Following the naming convention of modules in bgpcfgd, we call this new module S ## 3.3 YANG Model ``` -module: sonic-srv6 - +--rw sonic-srv6 - +--rw SRV6_SID_LIST - | +--rw SRV6_SID_LIST_LIST* [name] - | +--rw name string - | +--rw path* inet:ipv6-address +module: sonic-srv6-config + +--rw sonic-srv6-config +--rw SRV6_MY_SID | +--rw SRV6_MY_SID_LIST* [ip-address] | +--rw ip-address inet:ipv6-address | +--rw block_len? uint16 | +--rw node_len? uint16 | +--rw func_len? uint16 - | +--rw arg_len? uint16 | +--rw action? enumeration | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name | +--rw adj* inet:ipv6-address - | +--rw policy? -> /sonic-srv6/SRV6_POLICY/SRV6_POLICY_LIST/name - | +--rw source? inet:ipv6-address - +--rw SRV6_POLICY - | +--rw SRV6_POLICY_LIST* [name] - | +--rw name string - | +--rw segment* -> /sonic-srv6/SRV6_SID_LIST/SRV6_SID_LIST_LIST/name - +--rw SRV6_STEER - +--rw SRV6_STEER_LIST* [vrf-name ip-prefix] - +--rw vrf-name -> /vrf:sonic-vrf/VRF/VRF_LIST/name - +--rw ip-prefix union - +--rw policy? -> /sonic-srv6/SRV6_POLICY/SRV6_POLICY_LIST/name - +--rw source? inet:ipv6-address ``` ## 4 Unit Test -TBD +|Test Cases (done on default instance and VRF)| Test Result | +| :------ | :----- | +|add config for a SID with uN action in CONFIG_DB | verify the locator config entry is created in FRR config| +|add config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| +|add config for a SID with uA action associated with two neighbors in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| +|delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| +|delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| +|delete config for a SID with uA action in CONFIG_DB | verify the opcode config entry for the uA action is deleted in FRR config| ## 5 References -- [SAI IPv6 Segment Routing Proposal for SAI 1.2.0](https://github.com/opencomputeproject/SAI/blob/1066c815ddd7b63cb9dbf4d76e06ee742bc0af9b/doc/SAI-Proposal-IPv6_Segment_Routing-1.md) - -- [RFC 8754](https://tools.ietf.org/html/rfc8754) -- [RFC 8986](https://www.rfc-editor.org/rfc/rfc8986.html) -- [draft-filsfils-spring-segment-routing-policy](https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-06) - -- [draft-ali-spring-bfd-sr-policy-06](https://tools.ietf.org/html/draft-ali-spring-bfd-sr-policy-06) - -- [draft-filsfils-spring-net-pgm-extension-srv6-usid](https://tools.ietf.org/html/draft-filsfils-spring-net-pgm-extension-srv6-usid-08) - -- [draft-cl-spring-generalized-srv6-for-cmpr](https://tools.ietf.org/html/draft-cl-spring-generalized-srv6-for-cmpr-02) - From 775803463dc3d1e95cb4ccb4022edec52d51136b Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Sat, 30 Nov 2024 14:09:20 -0800 Subject: [PATCH 05/26] update contents --- doc/srv6/srv6_static_config_hld.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 80c57d3277..ba90004a9d 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -2,7 +2,6 @@ # Table of Contents -- [List of Tables](#list-of-tables) - [Revision](#revision) - [Definition/Abbreviation](#definitionabbreviation) - [About This Manual](#about-this-manual) @@ -12,11 +11,9 @@ - [2.2 Configuration and Managment Requirements](#22-configuration-and-management-requirements) - [2.3 Warm Boot Requirements](#23-warm-boot-requirements) - [3 Feature Design](#3-feature-design) -- [3.1 ConfigDB Changes](#31-configdb-changes) -- [3.2 AppDB Changes](#32-appdb-changes) -- [3.3 Orchestration Agent Changes](#33-orchestration-agent-changes) -- [3.4 SAI](#34-sai) -- [3.5 YANG Model](#35-yang-model) +- [3.1 New Table in ConfigDB](#31-new-table-in-configdb) +- [3.2 Bgpcfgd Changes](#32-bgpcfgd-changes) +- [3.3 YANG Model](#33-yang-model) - [4 Unit Test](#4-unit-test) - [5 References ](#5-references) From 906d87af48c462c23891f5044cdbb2d7ba42b777 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Mon, 2 Dec 2024 10:00:41 -0800 Subject: [PATCH 06/26] enrich UT cases and bgpcfgd changes' description --- doc/srv6/srv6_static_config_hld.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index ba90004a9d..a8933c1962 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -133,6 +133,8 @@ For example: To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_SID_TABLE** and compile the corresponding changes in FRR's configurations. Following the naming convention of modules in bgpcfgd, we call this new module SRv6 Manager. +The new SRv6 Manager are supposed to verify the validity of the configuration entries coming from the CONFIG_DB. +If it gets an invalid configuration input, it should log the event in the syslog and not compile the configuration into FRR. ## 3.3 YANG Model ``` @@ -154,12 +156,15 @@ module: sonic-srv6-config |Test Cases (done on default instance and VRF)| Test Result | | :------ | :----- | |add config for a SID with uN action in CONFIG_DB | verify the locator config entry is created in FRR config| -|add config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| +|add config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry is created in FRR config with correct VRF| +|add config for a SID with uDT46 action without VRF parameter in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| |add config for a SID with uA action associated with two neighbors in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| +|(Negative case) add config for a SID without action in CONFIG_DB | verify that the configuration did not get into FRR config | |delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| |delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| |delete config for a SID with uA action in CONFIG_DB | verify the opcode config entry for the uA action is deleted in FRR config| + ## 5 References From 793e255bf3afeb0d7f36880d37c7c65da18223df Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Mon, 2 Dec 2024 15:21:55 -0800 Subject: [PATCH 07/26] add arg_len back for completeness and add one more UT case --- doc/srv6/srv6_static_config_hld.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index a8933c1962..27f0b41a20 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -32,11 +32,9 @@ | -------- | ----------------------------------------- | | BGP | Border Gateway Protocol | | SID | Segment Identifier | -| SRH | Segment Routing Header | | SRv6 | Segment Routing IPv6 | | SDN | Software Defined Network | | uSID | Micro Segment | -| VNI | VXLAN Network Identifier | | VRF | Virtual Routing and Forwarding | # About this Manual @@ -101,9 +99,10 @@ key = SRV6_MY_SID_TABLE|ipv6address block_len = blen ; bit length of block portion in address, default 32 node_len = nlen ; bit length of node ID portion in address, default 16 func_len = flen ; bit length of function portion in address, default 16 -action = behavior ; behaviors defined for local SID -vrf = VRF_TABLE.key ; VRF name for END.DT46, can be empty -adj = address, ; Optional, list of adjacencies for END.X +arg_len = alen ; bit length of argument portion in address, default 0 +action = behavior ; behaviors defined for the SID +vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions +adj = address, ; Optional, list of adjacencies for cross-connect actions For example: "SRV6_MY_SID_TABLE" : { @@ -146,6 +145,7 @@ module: sonic-srv6-config | +--rw block_len? uint16 | +--rw node_len? uint16 | +--rw func_len? uint16 + | +--rw arg_len? uint16 | +--rw action? enumeration | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name | +--rw adj* inet:ipv6-address @@ -160,6 +160,7 @@ module: sonic-srv6-config |add config for a SID with uDT46 action without VRF parameter in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| |add config for a SID with uA action associated with two neighbors in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| |(Negative case) add config for a SID without action in CONFIG_DB | verify that the configuration did not get into FRR config | +|(Negative case) add config for a decap SID with an invalid VRF name in CONFIG_DB | verify that the configuration did not get into FRR config | |delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| |delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| |delete config for a SID with uA action in CONFIG_DB | verify the opcode config entry for the uA action is deleted in FRR config| From 633fae33e14d939655bc2df4bcdcf78e59fd314d Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Tue, 3 Dec 2024 17:29:06 -0800 Subject: [PATCH 08/26] add standard YANG model for srv6 --- doc/srv6/sonic-srv6.yang | 80 ++++++++++++++++++++++++++++++ doc/srv6/srv6_static_config_hld.md | 17 ++++--- 2 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 doc/srv6/sonic-srv6.yang diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang new file mode 100644 index 0000000000..77cd39d635 --- /dev/null +++ b/doc/srv6/sonic-srv6.yang @@ -0,0 +1,80 @@ +module sonic-srv6 { + revision 2024-12-05 { + description + "Initial revision."; + } + namespace "http://github.com/sonic-net/sonic-srv6"; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-common { + prefix scommon; + } + + container sonic-srv6 { + scommon:db-name "CONFIG_DB"; + + list SRV6_MY_SID_TABLE { + key "ip-address"; + scommon:key-delim "|"; + scommon:key-pattern "SRV6_MY_SID_TABLE|{ip-address}"; + + leaf ip-address { + type inet:ipv6-address; + } + + leaf block_len { + type uint16 { + range "1..128"; + } + + default 32; + } + + leaf node_len { + type uint16 { + range "1..128"; + } + + default 16; + } + + leaf func_len { + type uint16 { + range "1..128"; + } + + default 16; + } + + leaf arg_len { + type uint16 { + range "1..128"; + } + + default 0; + } + + leaf action { + type string; + } + + leaf vrf { + type leafref { + path "/vrf:sonic-vrf/VRF/VRF_LIST/name"; + } + } + + leaf-list adj { + type inet:ipv6-address; + ordered-by user; + } + } + } +} \ No newline at end of file diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 27f0b41a20..3264313b11 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -136,20 +136,22 @@ The new SRv6 Manager are supposed to verify the validity of the configuration en If it gets an invalid configuration input, it should log the event in the syslog and not compile the configuration into FRR. ## 3.3 YANG Model +The simplified version of the YANG model is defined below. ``` -module: sonic-srv6-config - +--rw sonic-srv6-config +module: sonic-srv6 + +--rw sonic-srv6 +--rw SRV6_MY_SID | +--rw SRV6_MY_SID_LIST* [ip-address] | +--rw ip-address inet:ipv6-address - | +--rw block_len? uint16 - | +--rw node_len? uint16 - | +--rw func_len? uint16 - | +--rw arg_len? uint16 - | +--rw action? enumeration + | +--rw block_len? uint8 + | +--rw node_len? uint8 + | +--rw func_len? uint8 + | +--rw arg_len? uint8 + | +--rw action? string | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name | +--rw adj* inet:ipv6-address ``` +Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with standard IETF syntax. ## 4 Unit Test @@ -160,6 +162,7 @@ module: sonic-srv6-config |add config for a SID with uDT46 action without VRF parameter in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| |add config for a SID with uA action associated with two neighbors in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| |(Negative case) add config for a SID without action in CONFIG_DB | verify that the configuration did not get into FRR config | +|(Negative case) add config for a SID with an unsupported action in CONFIG_DB | verify that the configuration did not get into FRR config | |(Negative case) add config for a decap SID with an invalid VRF name in CONFIG_DB | verify that the configuration did not get into FRR config | |delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| |delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| From c6f49cb852bfd7881ea6bf8becf26e27165f7d82 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Tue, 3 Dec 2024 17:38:26 -0800 Subject: [PATCH 09/26] change uint16 to uint8 in YANG model --- doc/srv6/sonic-srv6.yang | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang index 77cd39d635..dcd69f623d 100644 --- a/doc/srv6/sonic-srv6.yang +++ b/doc/srv6/sonic-srv6.yang @@ -30,7 +30,7 @@ module sonic-srv6 { } leaf block_len { - type uint16 { + type uint8 { range "1..128"; } @@ -38,7 +38,7 @@ module sonic-srv6 { } leaf node_len { - type uint16 { + type uint8 { range "1..128"; } @@ -46,7 +46,7 @@ module sonic-srv6 { } leaf func_len { - type uint16 { + type uint8 { range "1..128"; } @@ -54,7 +54,7 @@ module sonic-srv6 { } leaf arg_len { - type uint16 { + type uint8 { range "1..128"; } From 13720b931adedd06f118610ec856fcb82a6bbfa6 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 5 Dec 2024 15:23:22 -0800 Subject: [PATCH 10/26] remove uA; define enum for actions; set default vrf value --- doc/srv6/sonic-srv6.yang | 11 +++++------ doc/srv6/srv6_static_config_hld.md | 16 +++------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang index dcd69f623d..e668cb2543 100644 --- a/doc/srv6/sonic-srv6.yang +++ b/doc/srv6/sonic-srv6.yang @@ -62,7 +62,11 @@ module sonic-srv6 { } leaf action { - type string; + type enumeration { + enum uN; + enum uDT6; + enum uDT46; + } } leaf vrf { @@ -70,11 +74,6 @@ module sonic-srv6 { path "/vrf:sonic-vrf/VRF/VRF_LIST/name"; } } - - leaf-list adj { - type inet:ipv6-address; - ordered-by user; - } } } } \ No newline at end of file diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 3264313b11..76f3c0fa8e 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -100,9 +100,8 @@ block_len = blen ; bit length of block portion in address, default 3 node_len = nlen ; bit length of node ID portion in address, default 16 func_len = flen ; bit length of function portion in address, default 16 arg_len = alen ; bit length of argument portion in address, default 0 -action = behavior ; behaviors defined for the SID -vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions -adj = address, ; Optional, list of adjacencies for cross-connect actions +action = behavior ; behaviors defined for the SID, default uN +vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, only applicable to "uDT6" and "uDT46" by now, default "default" For example: "SRV6_MY_SID_TABLE" : { @@ -111,19 +110,11 @@ For example: }, "FCBB:BBBB:20:F1::" : { "action": "uDT46", - "vrf": "VRF-1001" }, "FCBB:BBBB:20:F2::" : { "action": "uDT46", "vrf": "VRF-1001" }, - "FCBB:BBBB:20:F3::" : { - "action": "end.x", - "adj": [ - FCBB:BBBB:10::1, - FCBB:BBBB:10::2 - ], - } } ``` @@ -147,9 +138,8 @@ module: sonic-srv6 | +--rw node_len? uint8 | +--rw func_len? uint8 | +--rw arg_len? uint8 - | +--rw action? string + | +--rw action? enum | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name - | +--rw adj* inet:ipv6-address ``` Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with standard IETF syntax. From bd92ca29a9baf9da67d88bd37aadf263a112fb05 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Fri, 6 Dec 2024 12:09:12 -0800 Subject: [PATCH 11/26] remove uA test cases --- doc/srv6/srv6_static_config_hld.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 76f3c0fa8e..2c81fe7ff2 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -150,13 +150,11 @@ Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with st |add config for a SID with uN action in CONFIG_DB | verify the locator config entry is created in FRR config| |add config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry is created in FRR config with correct VRF| |add config for a SID with uDT46 action without VRF parameter in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| -|add config for a SID with uA action associated with two neighbors in CONFIG_DB | verify the opcode config entry is created in FRR config with correct parameters| |(Negative case) add config for a SID without action in CONFIG_DB | verify that the configuration did not get into FRR config | |(Negative case) add config for a SID with an unsupported action in CONFIG_DB | verify that the configuration did not get into FRR config | |(Negative case) add config for a decap SID with an invalid VRF name in CONFIG_DB | verify that the configuration did not get into FRR config | |delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| |delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| -|delete config for a SID with uA action in CONFIG_DB | verify the opcode config entry for the uA action is deleted in FRR config| ## 5 References From 098a0387ca88ca38d0acd94aa69a600823a4e980 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Tue, 10 Dec 2024 11:48:22 -0800 Subject: [PATCH 12/26] add a note about the new FRR CLI --- doc/srv6/srv6_static_config_hld.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 2c81fe7ff2..c07e4d05ad 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -73,7 +73,7 @@ However, there is still one gap preventing SONiC being utilized for SRv6 SDN dep Specifically, there is no mechamism in SONiC allowing SDN controllers or users to directly add configuration for SRv6 without involving BGP. In this document, we first define a new **SRV6_MY_SID_TABLE** table in CONFIG_DB that serves as the configuration source of SRv6 in SONiC. -Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile changes in CONFIG_DB to changes in the configurations of FRR. +Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile changes in CONFIG_DB to changes in the configurations of FRR (Note: the new SRv6 Manager relies on the new configuration CLI brought in by [FRR PR#16894](https://github.com/FRRouting/frr/pull/16894)). To verify the correctness of the aforementioned flow, we also define the relevant YANG model specification. The workflow of the new mechanism is shown in the following diagram. From 5fb2d7550fec9580e44cdb24c6961a3078517178 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Wed, 11 Dec 2024 10:43:01 -0800 Subject: [PATCH 13/26] add a table for supported behaviors --- doc/srv6/srv6_static_config_hld.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index c07e4d05ad..bfa51247a3 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -118,6 +118,14 @@ For example: } ``` +Since SONiC and SAI do not have full support for every SRv6 behaviors, we plan to add supported SRv6 behaviors in the system gradually. +The current list of supported SRv6 behaviors allowed to be define in CONFIG_DB is as follows: + +| Alias | SRv6 Behaviors | +| :------ | :----- | +| uN | End with NEXT-CSID | +| uDT46 | End.DT46 with CSID | +| uDT6 | End.DT6 with CSID | ## 3.2 Bgpcfgd changes From 833483b254a45e803e2383da272dfd8528e4579b Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Wed, 11 Dec 2024 17:29:59 -0800 Subject: [PATCH 14/26] add dscp mode field in the SRV6_MY_SID_TABLE --- doc/srv6/sonic-srv6.yang | 7 +++++++ doc/srv6/srv6_static_config_hld.md | 2 ++ 2 files changed, 9 insertions(+) diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang index e668cb2543..42f5f0a73c 100644 --- a/doc/srv6/sonic-srv6.yang +++ b/doc/srv6/sonic-srv6.yang @@ -74,6 +74,13 @@ module sonic-srv6 { path "/vrf:sonic-vrf/VRF/VRF_LIST/name"; } } + + leaf dscp_mode { + type enumeration { + enum uniform; + enum pipe; + } + } } } } \ No newline at end of file diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index bfa51247a3..87c6b52a18 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -102,6 +102,7 @@ func_len = flen ; bit length of function portion in address, defaul arg_len = alen ; bit length of argument portion in address, default 0 action = behavior ; behaviors defined for the SID, default uN vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, only applicable to "uDT6" and "uDT46" by now, default "default" +dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform" For example: "SRV6_MY_SID_TABLE" : { @@ -148,6 +149,7 @@ module: sonic-srv6 | +--rw arg_len? uint8 | +--rw action? enum | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name + | +--rw dscp_mode enum ``` Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with standard IETF syntax. From 3a8f49b0bbd555d31b8df328e68f6136fc1e7d6b Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 12 Dec 2024 10:52:57 -0800 Subject: [PATCH 15/26] remove vrf field and add constraint for dscp_mode field --- doc/srv6/sonic-srv6.yang | 7 +------ doc/srv6/srv6_static_config_hld.md | 18 +++++------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang index 42f5f0a73c..396f96cff0 100644 --- a/doc/srv6/sonic-srv6.yang +++ b/doc/srv6/sonic-srv6.yang @@ -69,17 +69,12 @@ module sonic-srv6 { } } - leaf vrf { - type leafref { - path "/vrf:sonic-vrf/VRF/VRF_LIST/name"; - } - } - leaf dscp_mode { type enumeration { enum uniform; enum pipe; } + when "../action = uDT6 or ../action = uDT46]"; } } } diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 87c6b52a18..0ad79fa4fc 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -101,8 +101,7 @@ node_len = nlen ; bit length of node ID portion in address, default func_len = flen ; bit length of function portion in address, default 16 arg_len = alen ; bit length of argument portion in address, default 0 action = behavior ; behaviors defined for the SID, default uN -vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, only applicable to "uDT6" and "uDT46" by now, default "default" -dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform" +dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions For example: "SRV6_MY_SID_TABLE" : { @@ -111,11 +110,7 @@ For example: }, "FCBB:BBBB:20:F1::" : { "action": "uDT46", - }, - "FCBB:BBBB:20:F2::" : { - "action": "uDT46", - "vrf": "VRF-1001" - }, + } } ``` @@ -148,23 +143,20 @@ module: sonic-srv6 | +--rw func_len? uint8 | +--rw arg_len? uint8 | +--rw action? enum - | +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name | +--rw dscp_mode enum ``` Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with standard IETF syntax. ## 4 Unit Test -|Test Cases (done on default instance and VRF)| Test Result | +|Test Cases | Test Result | | :------ | :----- | |add config for a SID with uN action in CONFIG_DB | verify the locator config entry is created in FRR config| -|add config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry is created in FRR config with correct VRF| -|add config for a SID with uDT46 action without VRF parameter in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| +|add config for a SID with uDT46 action in CONFIG_DB | verify the opcode config entry is created in FRR config with default VRF| |(Negative case) add config for a SID without action in CONFIG_DB | verify that the configuration did not get into FRR config | |(Negative case) add config for a SID with an unsupported action in CONFIG_DB | verify that the configuration did not get into FRR config | -|(Negative case) add config for a decap SID with an invalid VRF name in CONFIG_DB | verify that the configuration did not get into FRR config | |delete config for a SID with uN action in CONFIG_DB | verify the locator config entry is deleted in FRR config| -|delete config for a SID with uDT46 action associated with VRF-1001 in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| +|delete config for a SID with uDT46 action in CONFIG_DB | verify the opcode config entry for the uDT46 action is deleted in FRR config| ## 5 References From d0fcc7496b3acb090d3858c621c7116b52bbda49 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Fri, 13 Dec 2024 11:58:03 -0800 Subject: [PATCH 16/26] move the complete definition of yang model to sonic-yang-models dir --- doc/srv6/sonic-srv6.yang | 81 ------------------------------ doc/srv6/srv6_static_config_hld.md | 2 +- 2 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 doc/srv6/sonic-srv6.yang diff --git a/doc/srv6/sonic-srv6.yang b/doc/srv6/sonic-srv6.yang deleted file mode 100644 index 396f96cff0..0000000000 --- a/doc/srv6/sonic-srv6.yang +++ /dev/null @@ -1,81 +0,0 @@ -module sonic-srv6 { - revision 2024-12-05 { - description - "Initial revision."; - } - namespace "http://github.com/sonic-net/sonic-srv6"; - - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; - } - - container sonic-srv6 { - scommon:db-name "CONFIG_DB"; - - list SRV6_MY_SID_TABLE { - key "ip-address"; - scommon:key-delim "|"; - scommon:key-pattern "SRV6_MY_SID_TABLE|{ip-address}"; - - leaf ip-address { - type inet:ipv6-address; - } - - leaf block_len { - type uint8 { - range "1..128"; - } - - default 32; - } - - leaf node_len { - type uint8 { - range "1..128"; - } - - default 16; - } - - leaf func_len { - type uint8 { - range "1..128"; - } - - default 16; - } - - leaf arg_len { - type uint8 { - range "1..128"; - } - - default 0; - } - - leaf action { - type enumeration { - enum uN; - enum uDT6; - enum uDT46; - } - } - - leaf dscp_mode { - type enumeration { - enum uniform; - enum pipe; - } - when "../action = uDT6 or ../action = uDT46]"; - } - } - } -} \ No newline at end of file diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 0ad79fa4fc..43b2c0df08 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -145,7 +145,7 @@ module: sonic-srv6 | +--rw action? enum | +--rw dscp_mode enum ``` -Refer to [sonic-srv6.yang](./sonic-srv6.yang) for the YANG model defined with standard IETF syntax. +Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. ## 4 Unit Test From 21420ccb42e90049e572082104c9191a70ebb3ac Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Mon, 16 Dec 2024 14:38:49 -0800 Subject: [PATCH 17/26] add vrf parameter back and remove uDT6 --- doc/srv6/srv6_static_config_hld.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 43b2c0df08..ca5949f535 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -101,6 +101,7 @@ node_len = nlen ; bit length of node ID portion in address, default func_len = flen ; bit length of function portion in address, default 16 arg_len = alen ; bit length of argument portion in address, default 0 action = behavior ; behaviors defined for the SID, default uN +vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, default "default", only applicable to uDT4/uDT46/uDT6 actions dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions For example: @@ -121,7 +122,6 @@ The current list of supported SRv6 behaviors allowed to be define in CONFIG_DB i | :------ | :----- | | uN | End with NEXT-CSID | | uDT46 | End.DT46 with CSID | -| uDT6 | End.DT6 with CSID | ## 3.2 Bgpcfgd changes @@ -143,6 +143,7 @@ module: sonic-srv6 | +--rw func_len? uint8 | +--rw arg_len? uint8 | +--rw action? enum + +--rw vrf -> /vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name | +--rw dscp_mode enum ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. From 078dd6e9140ab15a0d9b14cae169d04aa3513326 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Mon, 16 Dec 2024 14:51:18 -0800 Subject: [PATCH 18/26] fix the YANG model rep --- doc/srv6/srv6_static_config_hld.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index ca5949f535..a68ec0e3fa 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -135,16 +135,16 @@ The simplified version of the YANG model is defined below. ``` module: sonic-srv6 +--rw sonic-srv6 - +--rw SRV6_MY_SID - | +--rw SRV6_MY_SID_LIST* [ip-address] - | +--rw ip-address inet:ipv6-address - | +--rw block_len? uint8 - | +--rw node_len? uint8 - | +--rw func_len? uint8 - | +--rw arg_len? uint8 - | +--rw action? enum - +--rw vrf -> /vrf:sonic-vrf/vrf:VRF/vrf:VRF_LIST/vrf:name - | +--rw dscp_mode enum + +--rw SRV6_MY_SID_TABLE + +--rw SRV6_MY_SID_TABLE_LIST* [ip_address] + +--rw ip_address inet:ipv6-address + +--rw block_len? uint8 + +--rw node_len? uint8 + +--rw func_len? uint8 + +--rw arg_len? uint8 + +--rw action? enumeration + +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name + +--rw dscp_mode? enumeration ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. From 53c80e08a784529d604053757ebec313696c52a3 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Fri, 20 Dec 2024 10:29:59 -0800 Subject: [PATCH 19/26] update the CONFIG_DB to use two tables --- doc/srv6/images/SRv6_bgpcfgd.png | Bin 35592 -> 36416 bytes doc/srv6/srv6_static_config_hld.md | 62 +++++++++++++++++++---------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/doc/srv6/images/SRv6_bgpcfgd.png b/doc/srv6/images/SRv6_bgpcfgd.png index f92e6d597fdd0a08bd81517fb7b8ed895c7a40b5..5c192bca433c7e87a65a5052d06b3864c4681715 100644 GIT binary patch literal 36416 zcmeFZWmuKn_CER$0xG2_DWQ}iDFR9hA|fCn-AFe`!=e-^5fG7x(UB3_S`zUKUW6UwfxbJ(62ft@e#qlnXUw|M8PvY^z=MZ!b z{1Lqq2OT_wsh^;M2b#@uaS{tvCm zGEEPH0{SE#K9G0RTp4qJf6dr+Zm&REek=Q)+VF%AI>mK+teXZY5ma0TUhMLSiAUeE z2C*=B0ulqt%}MT9YvBZR@U>Z8$8n*$e;5Cp>dUs}Pm1E>ER+0s8$a?tEZe9V*$K8~ zF^(1}*;DAHM7~~V{FXu{eC3(2#yhG$&YyCr<%zofcXl-g`YU+Xr%Cy5EGppe$wDzYQs-qLY!Lo z=|My20ow(7K=Z!?{I3oE*AM>pF8u#19?a`@RM@?_tQw4s2GKo&gP*HZD(#P25+_1P zSO*SvolR0VoDUeQh0iB|Soiti>37~i*W|B57?1tnFu6~Pb}vl?!g_xh4whRS=vL3X zAY2-HIAqT2VotAI37jXfsbN7-o#LucY%Njy~hLGwXN?z!J!Y?JRcYt|Ae6l_x*X;Ztd8x zrFJhFyk?60BxBWzsc`4Mfrk_!FqEwzY?`_tb|U%aX_wc!3~3*lIWY8IgQG~;M1zg* z_68nmj_4ZagHWkJG8!V-_GfFNJsm1;BI108o^>k}Ndt_1wixOc@KAf0O;XS3Lv*pe zW5UNdhXEhpAr3rLJL5fgJ=Zve8Q}BdrG`)Jr}*hmf?qk{^+cfEc>oTqa}R=jLg*Vj z)cy`z5nHVAHqZus$Y118nirfzQK1(Z=3Y#)BoA{wnIc@M4DFl)@UO$ z+kl~={TDfAgbgc?S_YH}%M7NvZ0&Q(^giOEB zqmK*UHZ9sebaAzn?>C!DBc(tTyA`R9f00lOG)WaCN5r4r2^@Y%#(lPBHdv|Ycs%o8 z?cmJYS|3itXkk{ju~BGjZ@kcWqR7M}hEJg(#U+=cQ6XEVm`Q!#x<|+SNHx3KCRIJ1 zXK_mgT+>8{pvX5qZ*Dc{9Bs@*FKU%pPq{B`?++F7C|FFTb;^Cn;$hOx)i}LC9HeN2 z2Uq5EU8WAW>zy+r4f))UM!0yE7;^u`6c!PFZ1#?AlvyovmJexo>>}n9Z6pP?;-V|^ zNk)5r29hFt))HS!3w;E))_E&J!tHVC_(q7#k9DM0DLqUZei_N74QP|14P4P~mY(OUe&7&n-<&ZCjV^;p8cQ47i&D4#>TUPwzh_+r(?UcDYRb zsP>g%c-U;3Z`9>Nq)YYj?o_N-uJP%7m#iV~=KjjDk_Ca6|a-((P{dzOk}$qf{+ID=q3hIQSV?y zAK!v~a-JjP@VzhjZF~QFX2bWGwm#A=tyG=G@>YZg8qIwWc%ARI(%sr~Ihy!NF_5IX zPsuHfVdc`xak8Wtn&ByZa(cX|2nol>bmtQ%O{Td6F9^^#J0o(>g1djvhk<`Cn=?-< z9UE}L`K~#n)0At5%?O&ZP}F1Wvju?=?hcQ$j&`qEHX)Tx#d7UW{wQ&uym&I>Kb|qL zbkZ^IR+t=hq8xn-( z`-P8tl0;-A3XsU#XGvso_W$qzw+o!-{ZZ-d9BB7uuPYY^BAPStxsT-T+>e{D(S3C7 zvINzm&}qZq-P2JtH)|JzsfMdghuRl_8~^S@-?ZJh{X)zM&{qja9~hspRv z+M_Z_iGcw>T3YT5{=U(_hdIjhxyg{ecyU3Em&q2gA6OD_tYlMGUHXrlTt#Z|;R=y) zhQgl5c=|1O+b*8w=;@^SFSBvC9^N+TA6V(hip?|*Ch|c zFE|iHJZJ7_)2d!i7vRn+G_=h4J+@9&aZH%SoND;LBL;B!L-M4gdf7C}Z?!FkSC?bh z=G<0VEG&#o#cL3!L|lc>=ox%Q3%U%=*I!5qx+hg%Rj3I_y1@iR-{`NXJT#l`7uO~D z_#Y!Lu!}aA>skLVcKCl1@hzGB$(rTi;Y)>u+rbvu0wV?bl1IZu`(77c$~l8zA=uTY zo3f%)9cWTiZ5(p={UZ@$>{x_u)3oi6w*LTweHtf%|@FNB^+_UMd4Ae81*65Lefm;>>>>AMr@D5ic>y2o7{M zH0nvvy|*{_q4@lL)@WZd&9=EE8=DTdX@h|`rZSg3{2QWI zU1Hn7G&n!mu7T-Rj?>3#%pYn2PU4+~%7h^X7{J)m#lamb@ zV}(wZ-Q#%erf4}3*@{Al;+Y~Iyjla73dM?i`@);+Ho{Vp1+1|B4kMaBeeGiiUn3peDi_**CXkxlmNaKMw3BL3FE9kGqtgCt-i{r5fq@`BZ<=66Hxhg_L4jG zA|(Ja!y4MsuVoM!T;O$#(CMGod`3y+VRvW*kF9J-CHD}KsM`GsP9jY~ky1~3s)p}E zbJiW2wUwp2qdYU&A-^tex8DvM5BYB=Jd9Jz`!(vuWlMReUxJnaS{hPQMYurROEEFo z;VnE@Z5;A7#N;J;Pea!(M~K9F%Ciz*+8+Fo_Kuc=sxg(}W04T%8b--~CuMg0t$L&$ z4fILKh^{hdSp(4nU85CbvrGAV_$HA3+7UNX=>FCh!?2suHJvFfYXBzw8%v`k;FO?x z%_Vre%s%`$iHt?;S=Dsxg<9vT@`pvAF#vD!3#8_Z{K$=-cdKEtP$umT!BZk13kEHt z)(u3#e_W`hx_9R>IPxFVVBKPR{Z{?bRZiY39#y86NRyc;k$-oVuVh6@-g52t3jb7cf`mMBx;5$&smz`bcTG7qmq(3Lb z69`VImoygu96^3{YDshVg!AG5Ytow?`?3dI_61(HW0I|pu>4NLOoqGXXqX^Hh?BX%5xS@kTxkp)9`w1vB z+?RE?CBymqfWHv2)}a0)J=<}$N=c30Ti^k~z_3FQwR~IlZ3Bg6I0rGwOp9(MM;(QS zP1!yM!6*)sbX-EH)rv(%$;B?YO8?6p#{rfSDX=HxP;oB!51p(|g>NfqKS}tttel@+ zR(Uu|K<504L(+dAo*9_x-{gaBm57ATa0LB-M?iRUpZwN?t7i(*?$|E&qnPdISip7v zN%#ppvNSWPn){1!&I_5_TZC`y6|0+c2|3_J1 zuR9YRI*Yx$yhiOVUc9)$2?^i*BUpUHJ<~FTM;aR&r62=BQb<(<@;+5MBqDyEi6BNn zl*jt;M`Hi=BQ8=*ERSiR=bUOM=Q+=0708^ht_I7q7J5(kM{;@LeWu35I~)a>2!4eIUS21+3(L%{_lO(%yl-V z;~zok4cVF2tdpC%JI@8gb#^$Lv!>p!+flkn#E)(JiT<0#%glsx+k zh=0EYpuflT-##N6=8#j6JC&87C==b^W~&5SyvWk(TM*R}^Na|)RPVCEYhD9I>$0}8 zQBM=+dvLrLmNUmaUAzYgSm5k3cm2l3z~QuaKv~>jx;iULj?J~`&^8{(ZmOS2?$ypP z_Gj~?MhLBsAE7!Bd#1Kt!mzXHWvu+v@_e8Tb%H5@V27dQwy56_r+$(+Ds%W*z;4&i zZpp3)jrCN;n}`pKbNQJP-Ok~@k?OWcpWE3da&vxL&I2wLkp45 zlA@xbp7|T|moHx$89k=DSvDFgfXL{}$ijnGp4|WK1fZ~#7RT@OJoe7r<&hGZ{ztVL zeT)6sYBRFk?7X~8hLDGS^0m`*hd?cg-_+4jIhISE=kDEl8uqM%wHhs|8-bjL?cd2D z8q)trwrHM~Lcb+$ zi_z~@G0GYmW2G;X`0tTl@IuEv@3H!x@|kBAHuNi@0@LE2%WfWjv=RKs3aA}LtW|B~ z8Ih8cPjYZV<&SnA;1y6owLYttOA}PHAK|TY;9M)6Y6@!6{q}W@7Alwc=L?QcTWNkR zFK1;1ursr;IE^FpeoY%f8VnT)SSke2gs8)LenUGuE~Z6X0)m!d9MM)pP=Bsghv+vn z+sI`3VjG4tQNE|#fVjFsCdxv=XXOLD#3UYaE| z$Yq`tt%j1%{(Ff3lDD_F<7S&S1tn$ZxO3h9_ELCQ*fefi1oWx-@!Ijx0jJ7SA6p@a zar}C-DLxkZFDQgk?vHC6K8@wSCBsU-vogYHs{5?I1~tFCK4tBViBlUB;^IS>d!H1i z7DLKj>W|TV@AC6Acd+H?5;{K9sC495q*pdZB0kbVh^e<_qJ2`MHSRS=L8UfD&(qDu ztH<1UIXHf5u9_wpXDdcWM&^@jRxHItM~~#a@QfLw_%u5=H&*1kR6>L`v75qRrqGIi ziI3AsI>~rbDrRB9cqC6Gft`nkaZy=nDY z)Y~&hztMn;KJI>URKUHjUZl!$<-$g^#bBk==Hg<;C&ox1TKara%`Uc?d&)O3I;vi# zPDMu6JYzjIH8o@H1T4-i7@78|W3Ej+BqU^VU6ldE$O8!XW0Oiw)zw*F2EVyQu@&L`MmoI5)dXD*dZ<6H^y;1u0d-g^ zDIWYN>MGHBbYOSET;WhIp4xf-x?0b4bACPtr$1HtX39NEAKa1xKT+O<1zW=iGXo#{ zq=Lxr8c5z8I%)HC1tjHUjDSSjo3>5(xc!{t9S++E(iPTfQ_z%oYAc8;4+vewcb@(A zCb?`y9*fbN9d}@d($31tdg$5$ZqQPH_N^Kt3XiHSQcKow3No@TV`)YXhsm#=*fQg0 z&d$S+V$$wi;TogJ|DuRt^&zFWmkC^w_Snw`l5Lzk>zd`Z%^LCHB?8Fx!8FR7-24(4 ziHaGh>-&NK+`-O=tu$7M4$Mcneokv$ot@7p)&wqJ2Ha@yi`i<|)yi8>g{GTBUqCs1 zCP2rUJyys}hL+oJZizr)=GLW2DI~1wc|oCfNWwtm@75@28Hv4%cJFi^60d6A8izk& zOgan1CIK=>5cK;W)%fkbqRkw?r+T4wmdWVIk*+R!vXaOP-it=lXOkimw_7)f{l$Z* zs%#g!LvJe)laP#%q6J!-NM>)acJd)UL?L-Om_mOfi25vdpp}31E)lqek$0)bBQ5k1 z%LUizGO9&`0?iA^CB;^ZUt6MG1NFhQ;*}-+C11D74`rdB-wP@*vHGfA59*yfu5vDW zB1`h}2)CEK9eHKRn=$gL5_fIl4nCEjA>R<&DH&!fR#?xx-CO&;JUW5oD#`e0?xJKx zCkJ1L9Xc)|ZkbGZCI*&yr)|}&EwsUIJYQAg936n4vRP=v|gD z0oP0A<2{WX)^T=I4y_#X4@UuY8i9iHCPl-*@~s@krVPd&4vdbczL!m|S9N78!RX-; zcWNXpi$oi@qkBj9<>CZG46AQD7)Au;o~K{2)6nTjDIQ>Q@NqPhQRbA`TqaRv3Js(Z*#Ax&1R}M-tmeZ)P`=To zS~U;5W_OU-oWEnlVJ--Q*N8VAUT3tyysK|DEngNe?m5e#D?}cqMZ*9IR6QzxcGGMy z@8>IQDt4J$4nd7&W%t$0b#%TRFv_LNwI$p)PdUbQE#elU1tV-)!YvRb5t`ADe8q z;Q4Bf93B0XhOy<(Tp_8Q7Z4CIBWakZ6G_rTvF}=Gl1grN#OsuQNf2 z)Dd}p4vv@mTMHmFL_QVP3i@@7su@2n*P}wF3xl}W$fXEVg zrXej9z%#A-3|=B%SBciIj<`28HZ@VZZgq+J;72+o*^_rp!5;p#k>*#e?;eY;k&)5M zm$L29XTngiS3BP=GQkDC&NLtOneMo`N2oJmXobV_7;|e)$Kc+8Mih!0le3}}@4=UB zV~S<#`gevMv0Ml?rWSh3%51Q@mG?ysGEu4hWkew*;}wT?OZ{asbKH`f?MqL;Ao$`s zDugx{qM5e{4DG8VR2TGF?Q{Z+k8dEVL(6ka20q z_zm6YilAFTv5re!X&G4P9l0o`(U~){JSN7;$+@p;8qcOTq=AmHHr*Vu@h<85NX4VB z>;C@!vIJZ0GuC|e%kMd%bSD{sSH;b-rv{mA3;?*UQL?uBbbm4zSe;VffqgYKatc z)wR!rYjKHlO<+dsXY`fe7$wiF@Ykqs8k-b}W#YZk;=IDnY_Iy=(RoFkHzQJ} zbb7e!nbkX%{>=0)VNg`Y2l-a{{(x zjcRsO9NpW7$*v@EP%f~Y`4I}pkeRqgHt^l~&g;=%w$Wczzt?v-kEydc+qO|TRUSaW zV{ovgtv5efX0vh8W_hSkyd8oBBzCm$Kr-T;DSv2EU^$ad`)0DgGi@uG^D|G7F%r5q z?j7NkD*+LQhI|>Xa9JBGi_}8Tj+}E`a5@`*^4HJ0j+mFD%ivkS?OeOKXaWcY;5Rku z&^$@OMbr1&&wbC=?l(&`1yc5O_*zG9B`?j(6K{WF3huFmEQY}Z2+q%;mFvz=q#~~L zoX%5q`wl@Z?;^$e0p7g6ihZ~+4M-94Q6LfVjKRbx(*!0)TBreX0Tf5_UGxP~S9qkND35C8=Hi+OkO_UF571lA z7kMVXgswE`S`U`mCh!;T=I|%UE#Yj8mDr`mQ%NEz4*vBmZ$5kxGTGbQ+%)(;Aoytr z_n9H72dK9L%GTQYPI|#hI`*nw`u7*|@eE5u~<7^#c;gUK+AgmU>dYKfuefzeos6Q?`$`=D0|NC0w z*R?Cqe(-V&aDp86y=MRpQl_rhdP{X*MEr%j+0->xDD_jS-0DPFvBG4)C~&{ z=W}QrI`2B5y>)9S2A=)}HMRmXF##37<9_+UYDI^-0Y4X4pBHZAXFT&I+bO;=H)wbm zFn?`jW##vbGn<+%0CG)1yo%h@NplkOh1(g~{-}G-)(Nra^k-s~p=kvu<$yEcOWT?=v#C*g+?L)`h7&3*A z>`pb9S!9ZD7|a}H2WBRvpeQ_1KaY!^n*i@)EeSB?`N;-DMsVr zb<;DU;W51d;Vu%f7FyJGb$v}>(e1EM*V94|+(d?}6~WC1jgL1mWo=%mODYjZ%v7x9 z+`TT%=H8a<)G3**$mf3SLQywmK9$3t#WIu*?0Tw)&}74Oxaa*T9sX{GVqsy))~eBT zBf~S@K+=Y++WzW)sU(xHTJ^18PeWt;UD0A=R(3IMvTLRx;%AwFc?t3NH_HQm82bDE z<`Bji%L~ss17&_a<@4U6Ko4cof|HziKh;t7Hk} zt|ICH`Z1Yph_xqvnQ5OcZ;dLnFh9J_%Q+VamC=}nP@`>GLeNP4!(J*+;zh65qX&54@@Q&kgl^gfm)Z|RL_`ou+?&1C3HY;?|5Bqo zYTqzAzEzT|b?L4dZXlVeEy?8NV781X(y0FH{ha{=!OuG~m*)Lg&S|e-eC?o#GCarE zHFCLYqSfJ&cG;M(MC8KJU>PYoqY16piBHs(LVbC1W!*`p0sF z4bT^&qYLfo9~XqNJBTR|y<}w?TQ~@@``o*^$m^WQQ@_Zy=p}B<2N_oTLy|lAf5`Lq zMnjdvp;Dd>${$-d|hH^kaEpR&gKoL?o(AIBKL@OTXs1>2-8CgntZt8zVoEsvR*nG~Tf z+aIe<**meyC22T8tlQ@&1=^en%$tGAiP#&!CJHgr-o(;&c&Mb#ZI(K3HIHY^;n(8( z)?7rssJJJ_B0E-zAJf#{zQ10+gv=P-sz{YfCXwmim~J5@ngs&PygUo1U7egqFWuky zXBbd1&k5QIIZ4+Y3JyBBql*V#dr7S`u(-6;uRhL2Y9s@&C1Gh_UtgLJJ07e$et!%= z0?@>^oD{+%-w@deUT@S*LeHyqkZ;YTRgr)F_KEr zWa71(Pslv%GHo@vY)!ZCaE^<4&?Cy>{1&Y=Hg`#RClJ??3xVc!VECajMNQ?zcZOJ=84hoUN5j{MXv!rR}7 zsZII0&3C@sZYkDz@zzUvt5&CX_}w{aGGd?n%L7%Vf-FTd(RK&(b!BU4m7Q5>C7^!u z$3!0gtjQ~)`ukOdY`{sExT5SW%2Qsrt#rGSS1~Ud=F+vA{;b&Z&n}_HKo5pjqOb4u zU?N9FS=o1ZWZ%{VFOr=WnJbq&0957Mnw%7Nfu!5PD%NG{JKppN*CGK=vwcElih(h4 z!-eG)bE#fFx2;=QPaXErdW)rZ8BGe|p)YAvRr}X?7o-(qmijN=q+`L>cf; zdwUr4Au*Kw(-~M(q&0ikg??>6<%xZ>+I0Dj`&zluLRzufMO+VngP?WKT2SsO;2yqu zf=mJ^GG_%5q`r#qXv_2~23ab1%1-oY>;1$w4GUMIxUF+hvL^Me%m%6QJW+TR&Hlj9uMIkBA+x$jW?n)0YCLO|w8rHL6X>cK%rp zWY+$zt-3(%E(Zq(Krv6-%-gKXDnU3aB&=#R1NV7si)R7`mTUf55hjy9h0|Qpab@l& zZVpe9pGU^V77GX`JhO8Dym_Z^Fh-6kw31DGppR9fd|J`!tQo~9&foY&MwA9*= zJg`H@R!1c6P>vMy&=0x^6T)h?0-cOVAzp+TW3F*ZsZ*b3~huaN@ zuYBX;%*d~ZW;MGfgA1Hu!wwo6irZ{#Y-X&7M!U`29{87IEAzLm^`^@i#)_f+(|uZ0mM*wC)>vEj zZLpRF!Z$SEBbD0d z_pZwbu3*b%A|Oq?)35qQ zMpSA4BOhhaldY748v?mGNsN!|9FP#R+qqxuOGj0;XL+KN7BE9JWteo%F%010;bmuK zeIGUw>#gRhaDb_~$FX591v9ZfHo%9jW3H$%!>93WUhcv)dQAf~OUc@s8M7%Vz$1@4 zz#8~!?{RQkx47}^Nkj#RWcNryS8bX9q$wm}=0F+=Rq_h-X^$1%`5}mq&=O36srRs0 zJEe8)?G;y_H39MF6PjnDVrGm0qMv`@$M?BSSrj7%#&U{g$MvP;iK-oiO~t|>O$Q>` zjVR5Xr}DJNFR^}Sk4c>k+f>@*Se{MEc)L22q9~{7H?D03!7m^OUI9P$p2XK6^bW#Apoo&bnICTzL()09dz{6&FV@ltp4Kh4b zFy%YVPge=P!kjfa$x_LJ4I1$|A@OfW5)T3b@4}DJ+hE|KK&Yh3--8N{bG27FaSkUu z34RP4rGP@#QHnMaQQvU^5}~Q60b$%Lt&*u;o~Xo+Avf~jVNzkDPBfuH_R10h&a}fy z#6xK2u8cNOP?lQqW=4WqW_aXZ>%D-PF76D>bT{Ht6vse~!CHtH_Eu2bdqDSl_=w8I zx9J8V!FU?YrWa%hhyu?m$@;0*m!&cC`zNikYV;&)xZesXgWm6k`Bh ze*5INpLISnWKZhAL*M)%pTp{>QO`gD#15zmY6~}0<-ymJA-7y7!wKt-qP0AHsr@^fEb|I4veE)cq;xxAUB=J2BWa##g4%OsCq1iJxSJKecO+wye6D4 zHTK~nxO$i1s|Q*q$hW^yVZ91b)6fVQ4wy|QUzUJ=zK_v{6$+j`qxHVgiKxmH0}S(Y zd0ywOdDKJcC{ssPIOMAMY8n*( zS>2b22NS#F9xs5#*X%mLe)le1$OHENN`LSbKF-}rlLjRlHnFFgJ*G}hP6h^zkD5dh ztbR>=P1`aBj29G;Dr^#CNpmy(cv$FV9Gc-8+f5!RAd{|GV`PwR6pirx=B(?O##L6j zZf;22z2PSP=$7x>$pavw>GUD>4NA|POBgnhv(@^qUwK)0GjNft>3->lYr;l)LW49* z2~81NXtvMZmD7+3`+(vlB_QR3PO;q+M-RyRyStzFc3^|DhOMnU5Jo(o+Is;E=lqWB z);7NFQkO0i0}7|Mqp%?Ub_DR&tN?FNX0%&UENl5gU@;%>c%S|o*Yj5S%KVPMCKi@f zE7k-znI_WHZ{5f6XpgVJEPnwK`i6Y+D>db$Yxk^#SDBk8@M6Ws9(gIks;eP#aOB(= zb}LSis&p$LfNjzai7Bq6GQAq+`;uP@9UFwq`?}Sp%{432!pugBSxinG4gH4i&y%kQ zD1+t70P2O<$#TjG4epprT9v`-ylxvV%)`vgJZc*|`AZYeYZpbef~-<&?>w=!CpQBI z1p0IvxA+i=+hA&HIb#&Emt4r7G$j8OJ5%~1TUWad$!b(YgfBtudfTRj>=jGNWjXte zy+cs~f!=OrmTXG00&I`7V&^MXKc|lXdVX76T%2u-p0O~2>w3b~sKT=JQH?QueD zlvi7y%%UoXz7*@X5C>-hTbSxZe>dYOZ0+cXRvC>;8@(iZ^jKjnoHW$zoMlnOteCkh z?iy38g8(O|F87ZL_bukxpE*bY57yFjQQI?G87~Q{%-GiaoB=Q$cI^djXbUO^_v?f^ zhm5l$9D5eTKNwJXwCTz>H8xiAbyhxjs8_tJ(#kWriVc8=0Ahaw?}+}9{^PG|ZQN@q z8F)yRw?8$!^tCQz5S7L@Ab$*Y(PGN#l>i?)t?Is7%@4nGK~z+fzoYrB`=dX8q2 zR`Sipt5(gavTfaw*$d43+n*T-bJR*!^P8xM zh6ca0Lpv*QM@-Qvf97<1+}hRA=2X0HQ@eiK$x zQ&S5pQR($QdjU#*)YR@CFQ1+YEO$_neYJO{1+Y-1*WS4vg}FW>(^Bt-|;sJ8oVi>mw|fc;D1+xMPgGm zQR(`;ZZ{vSTv$&(F8+CqB{)X+PyM}|2?!xyv8g{6VGscf40m0S?Y}u6$;;x4nN}E* zox(PHRkFvJ^JjPEt=^clkn9{H1#<&~M_SS5PD+$Txl#B&#g|AzT5sfRUp-Jc`I6vJ zk)0HWzOs6ak}KqHE@Q7s`xDZTcaynJLxvs-iowK~SgD~nI>p16X@+QY+%ntwZCXf4}wU>A_4fIunq z&MKSNH_#QyZt9)C~&Pxngv2tKtS zvy2)!{4n(a0#+la0@~RrwD$-lip0bhh9qEEWh-(Le7#fBrD~2jkrFN(-6(#k7SQ9}IXDqZ2jyfcRFNiDH39fl8EHr|`ELXGl|Hg%yny zM8kDY1B_d<)kXs7{XxKLgm%MpH!`URcd!cINCHU-)Ifk1jE{UMr7NK+l-VwSNuuDb&Yb>53^z`tZY>mzEb|+o-{Nz zUitohnVv$g>Z!>-V`OMqSy>eVwTQ||?k(Fftk45Z-dCXPMH7I)lz}WzK5hpWyQz!- zwuW&Z$Yc<%pE%x(-yvAx$LSmm%GS%QD}dbcwwEO~l8!Yl`AAYAvn-r==uGTndo;Lf zoI3cbFcf(=%31|&YiO(DSPE}$63+0os09IB)7}@Y1;Gs8FqCgQWO$Jm4Bd!FWYWK?zV>A<=M%zNf z=>UL6j13~YH}+gwuNzXV<;cznui<5ur?al5BI`q^xgJ}{jqwPPfl63k?vubceSj8P z6U84^MfR{V?J3l=S{Bi@`R}_v*v$FnnjNgE+M`lgfgWQoC%*808w(vR0>ag^V6Tvj zM}Zy{%dv8WeyV32pbE5&2)cXVkp?8WI1RduN4>@&sC<%&Mxg^S!V|Q+1nt{lQ0fyv z5Bg0dd(Tl$io8psYUGdW;J&peW+c(C<3?+f4Kl_;YFuFXR;{__Z(i)<0P|w^D=V;? z#WfDHl;cTxwpqA(y8P%E7ho%Hi`_thMeEEkE0=`K2MY~@jzB3IDBVTa?cctM^vXaS z;jTMuHp6;6d7wV(1B^nJf`hvpB(gs zsSpH}OiBCR2TJvhQK0P9x|_s2JLQ( zV{5B@J<@+Dq&oVffOw6*vpg^&&HZj~VMLMt!9|_MR8`xpG`mP*Cu4>QPw{ z9;oueTN8W^kYB98lAzM9xDJHnx)__9re^i!HiSFd{(y8$ifF&&1572?iZ?v7Ln8|- zA>HrNpix^ESu|z-ZQ%~1xMaf!L;6z5U&UHY@+_J3OX4nNIJLs!r!&{V1ppyeJdFFq z<+@GyWifaFlmWsC+Auvt?PEZ2=3S+)SUuP19q80&(svlE#!MVUCE&c!oqSsQIuXB ze$B4%J42PLI7u27;JeL2Lwo0{Q@xf z74T|CQ!c$p{;ExAN1RX%Xmq5&+1?Dp3l_3FsOnQ6VpSP$H1pNYn#zHlg3KWt8YZ$+ zTW$=Xz@Ca71Z0w{)12F;wy_*7UQ`cz7%bf2j#`;|f8?_!eu2*_pdCc43%nQT#)526 zWe|-LCoR3&%Dn&FgpxVBQT}=z{fOZ}8OuNo$$av{El4%g)!}^nX-nGN9XwACoJv5c z%3hpRwjsd+409mUajLZNQ^?>V7D){zjRfPUsj1n*TR{KbtZ_5wepyGmXTY+m1Ary6 z3NhAe$oW~hI!5zv)C7GmRaJa;US{EDajE*Kh&`>6KvzX~z;yw^0)3%dSJcRaMTX#g zKFe0r#d@W`;%2itdcRB|5Y6o;5v2EYCjmHu3AgFOMT;s9OOO+)2Wt7LRQPj-ZX2*P zf+i0MZ|D04TM8Yem6iN}W>61+2=-8Mt9YD34onMTBM_@`*NApkgv&KjfK};FXCvao z$vP2RriE*NL0xQ$#$sFSjQ0&E$b(B{=$=;8VN3QXr7z!`fv6TN+W^jD5KxVafh zQbE1W=*5c%fM@zLAiA+sEIY*liqM5CC(0$`!y86#j--0lHU&|Kt4)%=8;M4XkJgg` z2Zfh*T0%5ki_qUC5zZ7@V0~3h$ce)b6jD=EB_MX&Q^aVsQ6VwLo>@Hc%K~+KF2@Nz zR3E4@ggFxc4XlB~Ie)tGd~T*!=I`cb?z>r9HL)lvG+_!ocQD0odV?&0yKzm(w>()9 zL$5Hfr?KwsZ@smElx+%xz~)XnpM^X8oJ{0vaM7CpCPb}{fr}t~r$F*wJ|@Fl^;eqB z$;q)mR;qAU!SYNc3I`fyK=l3T;N7~h8Hg|k2_Iz{GX|Q6%^d1FJ3HZKVqD0hUa#rz ziZtO~ASaWaJm6j`72$9TZ0#!yc+T7Z@+~SZxbM{>X9@HoCnqOwFAcO1^ZY{6LXTy3 zvj0?M=4AmWJME!Fh#n$>06UrnlMy$s7X9f4tTF|7djoS0R+4rmY(7tpBWw?MU*5-n z;_V6$e|NaX3wLaPHJ&eeFyT+ahL4BWtjG<|_WkYh3kp2}+ZLdGJAOacDL&8o3aN1B zn?<0Ta%vp$rM#SJ4h{MuW?ujnRt{SDw@AR@rvl&scd7Sl(gIZWW5yb8E$4)wVS2tH zV6-vtTR-+Mj?s7afMA=*%0dNK{0Br@>&ow4hdf%F-HIRdiN>E5hh?m!d;jBL_#3_4kZ*OI!WZYZRHnYM^Qn-oh;m0QilRVbBzjKAZA@h|RwtagQ-co=F<$LuH`3D)8EUof|r! z<@YLp5O`_Evs{6cd(P(`&Hj@;=xphU+HW z-xfZWf(G(TrQGtqhqGDoOgf2?vTr0R-ns~`X|{aLnI2eD>y8W@G2d zP4l@xGajfyZ+rW$0Ld_G=)}H?fesP^ikrhjVi)bMZRa#Fm{btw zYlJjZcE^v8p!P0BI4Y1gB^HWh2_A9_V5}v(ZF&Zp=NxLS1?tvfdY60ts zIBv2)s^*Vm*Cdw!NZu(4aLXG%oRu=DU+Xu8fJT)1l}^a{0Z^+w+Wp8dktLRKSz|9a z!u2-63C`afnuF2HLwbSh8BvcTWY@d-5VL5dikXo<+5zw0l~!chpbb`W4TJt!)8o!3 zkRm)z;9KX(UU2Py{CJx+#$nk0DVW8|Rww{N_?cb_?4*RDTW``#s)#%?`!e=Y3zeBc z0^jORmIR7|in{vpJWifMx;#E5ubyX#rr_C5lXQ@!BSnK{XJBOC`{&OWNCYNCNsmCD zs?47mA1W-xNXA!{Oxf>WHfrN1ZRKP0SZx8-olawbTsA(=l_w-5td81Oz`$bF8~mlA zK@7wI8o7c^_%wW-heIBF@LD;iiZ@7F#A*JEByhV%Kxv)hWGYj-wr9=w#8 z-oM55*dY1F(qb5-d>cl2Ira^GB-`bc0eP0nk(gT+XWE1f2$;l~VXu5YQ{8qXi z*cTE9FPVW(e|gq$Mn*=vqBO^awl_mq+MM*it8}x{Qc~{%1B)+ttb9~wH6*@w=MK;v zLBUR~?bzkn-!vRil^RZBP)9=cLyUs`6a^v>$6Tq#7OS8&k+m<24m zr>Dn$4{)1GA{)n3*rn+S}$yhc5E`5eZM=&h@cCK9D0!Q(+-TB%!m5A_xt7z3dCZ_32wL zo#8q;67BYcj%H?3Ir0Cb>3O;#lD`A7f#_wpD?AGeLCJi)s8$w8_{zV0uC)T1>tc`Z z>fK?d0Mm4J$-=2)Q_o@aPl9zTf)lJedA%e}R$re24@J{xwOY1fiNzRG_(-1Hku&V8 zrXoAv|0XS64xah9r&$dIbr3Mi*qE5FTmYN3$y9+~&5^X#Lqu~xH1~&S|E@C#jq z9sNTfwZ-gg{x8+<^eTNd3FEV{U*aWM0E9pu8_9-%#BU zbUQ4KTnFt%_LIMU{hFLijI1s%FL&CUjh=mJhOE3l`^^{MGQGYk*L z$*Wrl3D-B}=Rn`yK+GyRIeEF`dZHN`6z{J$@ORQ`9yoJ*CJsR^Cr7B3jvRt>EfV;s z;}=kE)O!t^KT6!brle;rH?)+QGzDjj`Evyhz~_GB5qC9^#(fUTBi5t-JDs2n zFdn$AKZxS$TM_T5Tz);+dyoad37qJ`mpknWJpb~?@0Y5=EY9aBX2OwK zjtC@-DYyz&js}gz z>)HyN0Kc^c;JEu--$2v{y<3jpUD7T5A-O+$(~bxA3gB5PvBdWmxA#Ft2k(9XWj_}b zW3NI`|HtL5ze5@+Dk%Z&WhS!A4$PZ7u(W>ues~M0MzOH6{+L0BoIREc{(d>4a^Sut zva$>ucX}YWmYSOvp(-i+(LcA0RCzxPjx=n{%%yT!KY#v&U-%P)Am?|>)qe;1UeEG% zmZh2}hGX4C3!1;3NKkSXJlH2j)n4;hB3-~+Xo%waOjoq{HGUE&ONKL8O*0BglC#9) z;3kAC9iR)JeE3@O$CCtBy2ssqZUzawXsL@kUKSTR&SR$wi)D`hL&N#$+pGjp2mK@#5$I$UOhj(5Rs*B!J}KOhL930hCf zKi96iK(~x~SIZ66R`Ej!wU4k}v}w7hRoM5r301kN6)mrV+-9Y?C$t$%aM-nWEaR#w zh{`vvxPFkjT9m(Mmt;xiHZ{gZv3IVDXLRFmM9Y$`oO`M~M zGLGZU1owmVj+n_XT_|dm=O%{MH28(AewRF6F&wW-O2+MvrXSU89?0^{E@ zX=IIKi>4RF?&O_Lyh%_898sE=yvYfhf2h~IlsJi|%7 zSL@lc7F~&oK~-*N=Q@r>*AJ|}W=X0!q(HeI?z+?9Vtl>v&#(UL*sEY;aow6C2wJ}8 zK-&*2y-l(XqBN19 zAYh@WG!X=)3yM-gR7#`;Tx@`VB2uLY5|9=IsiCbj1wxTdfFROB3oX@3nc>R+D3HN=Kxn|~?ne&{2;mGVlh5)YM4;I0er!#jMhmYdl`sm3|cEZLa z>f%zoJZ=c)go$lbaA~r3pNJeSnmkc~G8_t1Z@g|GSYqvP{e}m#pO(VnOiBF8ncG{Bo*G*FrN_p+(X> zI?8=<*q#2W!f9SyeEcWj;l`FBNviWyYWjTq^ew)kH1{Fn`*hPl>Qd%xq3yIte|P~a z(qw5;FDi&C=fQUF=bNK-qvnHhTV@{<+ZHHAGsZkIhgrt^-{7O1rp8lZWxo^`qkd8+ z@?GYYnZ}YS&Q8|#sNh;RoA#~i>Fv^d{*XgPr~+468=s%)l*yZN%Jy@eUdtgPrN#cf z+HFp{npHfx5hZ^3Z(|Oe=dz#d!VP^^-1lx0d3jBc#~%naV_h7={`mY%sQcL{-0%gb z7LvVH%vR<3@kJafLyvX(wra5{GOEF^2xp{nv<(X1mBN=@fS-n)qs=MOsFPpZr-rc) zrsT%5kNr8ix2hWuBEyHrmw)%8&Id4v`3=n3qsFrYmiFwVS~6a2O!h_OvNvh$Na6Dg z0n;>uK+>Lu@FMbE?l-CPXEHUZ%k2ytb>cp^CyeX!urhTryl65qcgOOR?RtS-$D-yx zZS-wqlPMP2J)c9V@ux$||TX|_-1-}%3%3uvUH$s6Jyd9xHTytw}nh3pc z>b41ENRP6YnQx$CjGo+r9GS&Y6Bn_PPjc7b#M5>ZxwptJF>3Vk$JEENXEKO+-$#i~ zG#1eaTXg-Ot42fFRKjnTYh>NWW+=u|)83?xYm5L=*EozT3XV#LNdA+)&sf$FcB#^3 z%xTy_Y0wSUkLb)uqArC6aURx9H6~HpD?g&lV3>2$wji+ceB=Q zMI*FWqC5y8Qc;lPR zroA@(SVJL!$}@ZN>=B;JorkBy61J;aRuZX<7_V=>$RbI1PKena>2Os2hK?AvpGV~A z;%6AlB4&9ABgosna#A>WT=>zH!`7853gQQUWk%wbtVyTDT*sHR6HdK#xs-tX;fx&mcH>^SPB~Bn2--TdD_`PM6f5!z>!|~y{~9GO#KzE z;N(;^_f<9S-km7Z%OOSgR*6Y}oYU%}XqjUv7w5YfTN2fC=g&Im@pXa83TbStExokP3d)5A?fq%?ePPLr+B*<($Y(w`flXR5I9NVFk zgrAG$U2f7Nx()6qiW$Zgy)m3CpS4m*Z5cLk>EA$SQJ0PNE*Sry^IV>%V2AwkwEtAu zKbAOBz>`kiRo>mTshFChYp~S6LrvnL9VR2@NYoN>`OX?()o~lB?!)f#U|Z)07U8e) zC>uu+Byv>NjPG!t{_f8jAm%lwPcoNwxHFTY76Kww193I@iMI;Zm%4dR$0=O8zEs6k zbd}iR&nnVmsKoGFt_9lQB0kXUtNVYZHsFS|zS`EYHWag_O$f@mB)lzJ!O8qCb$vJTx(xSu&6!_mSi>YYpd?jTB;DT5 ztk1}BAKy{PENJ&9lk=7b%uTYJmWGmA^7X_JI#8}CW>zP+$$a_jsBeYENXsocfU7-4 zo-W(>y?0+Id_Tp&w#d&!6@pk-deuDEsqgf5-tEy#XVeQjHi)b$i(L;H?n;V zfV){fAU1J3AkjHDOvKZ$I*sV6G$HRizcONkO}t)d+w znoDK#Kt)A8P2W?-i8aSxW~E+l_s3szVJhSgEYYkZ;uqcw=D_rgI*SMdSV@FLVqskEmW2zhCvhanfS6i{h>fG z%d2{iWR?5r%jk^Lnd8f}1%`9M3~T6HM79@NalL7Tjnag!kELjK6dQ-dQ-}2BLyp;9v_@YR>=CiDCMT*)+{bp#w5pBq-7?=;~##6cnQRd zW=90-5JF#h`*gFhaEA&l2ajpvHJ$aSj*r_UwzNz+=Kk=0qra{*eRbMFCqwCW79pec ztp@j5^#jRnMGK+JPQmcfoREPG|)Ik&q$Ie%O+Ek2M-~q4i5{HNS6^B>xqAFBYyLr)q!p9Rn z7vDMtHnDe?$YQ6q7hCN0P@1WEH<RkTMuJyyqo9 z_0(b+a{U?Fu^f%~MmhK^&aQ#0_iHa+>wlnNAfgq+9WLlz9fK&o6xCvPo;y z0x-S4h_lGV?tEWqlOQ*|g9})_=-XdHhB-Lgd?U9N&!}Hmh*Ml1D`I*Y`yH8)y5OF{ zGzxdXyl9plgRFb5j|o@Cuv8w#x}Dt^2ogMyITdaxUbv_u0bIVG34VmGey89dSAJch zKp|30g};48b@d%-E*XUSmcf^(W5%90#}cJ>{N7Bb?G7LJwazSZ9g+pU=6IXOpdneH zmBtY%{h_5EP`BEMUO@A@u_&2;>Zj|`+?O2yHOsDDZHg^0md1#WI)Oq%w6GLt;U-VE zR_=|l`vrjC&;0mp9VzUTJglqxRJ{9xzS`x|K%(13(JgL|SB7g?FQb-e-|5Q&Q;t2o zNqbg@`kC@VeBoD!wXcllhav0H&6=O_iZ3*;Jl7ZI6>HJjY&^s){BCj_Hx$On3f6Q} zd1s9i=g; zm{f~@FyxP)b$5QyqyFXg1p7G%LW|RQd6zCf0czayY1MOft~}WwegWeLuTAg@Al`+exQ-EO&ZYS56Y0LC)g0^o&fx{ps!KgrPdhRXxLMVzd*aQ6#Q&;Vpc( zc6q!yQTu$CkUQ5)W1qvDOgwvaH3}UO-+MYa5OydQW%DTopB^ZyL7}1EyxX=A+jZp6 z+m7X$H14i^zPzsNJ+z9Gq%y_J(%+TVo01Z+?rs7}s5fa&UFC|q>H0Pjq|dAqgu zZ{xt1smr(mLhKLlzO{ZG;SF#oAkvKH&;b9Ap%jlPn{6eyB|escI^EdYzN5 z-yzNIwH}>9@7#S6Jh(Hpm-e~&%5N?fbl*RpK@@SHD)-IoUoxI8@6_1P&5s%E`_tEb zeH`W9JK(PiS^lf*J6O28}?W#Dth}WG?FS zal9+o;W*Q5VuY`3#$xA!QCqj>FKsRk4E*aBX#B36VDt5L$u&i%hNzQoVb)-RQT0+t<68Z zMIBwXkgtpXht4Y|IKldLN=Q{!%e#N~MBfm8bDOpHXALd?a&?+jU~TaK(t-V#+y4KD z9`=jB__(J3eqlxYd0KzlS01FJsjO8qr1Y;1fk~pM}@S2NaXfy zX`5ElAOL3}>{drl*{ns9lehg?i?ajwbAgTP5ywU`!<-jYeE?s?F@~2TA^J51FPC+boe32(SH4h$4I?i}DnoLE;nO#a?Qu2~smVk&A;;GCn@O zes{4FM_cX&5$yY#39pR)^Od-oppovkvZat6n?9L% zQAK7DDgc2X3e6L;yLu7|&_^bL9-}I|12wYEB~zdLkw5WM7^Gu?0S9aTF<&;O(CpP| z4nJ|6EjL+$gF$(E^dk4h;y}^hF;GS95UYHMT(R=(vTmMx?8hdvg?2|agW6&-+n+yQX0t<0Jc_V)NFyfY-3x?}{gAzD3i(cER|Zsz<{I2yBS zzRficlHe8lU8=b~%G_!o;fHzWvU>vRX$r=0z%9f5?t3tSei!n2KMLMg0Cc_?SIgv{4$6;Ou1mSRT9}XubO(-ltx3}&qz@CAG$es2 zFk5CeF;T%Q^xus>pn!OMiA_g>_W6mytBciZ95n2RChB;Rq$-Suu}|oIpaF|u?wJ%UC(*1EgHP3IM6oeuYGl18YQ|z(5Zn>tj@{n_=Ua_ zq7gMBLtwV>`qcP9!T`%z`^CN-$?X2H#%~4rZQE;&3!Iyh>yK6NsE`MyCN$Caxw}Ob z`OieKkG6NJ+npyF{T^zT((n+o#<4~-Zs`^gD`^UgWnB`*wC$g&-Ni84L_MR;&Ik-vJgyQQ-<)O<7l`O z3>6|emv}-Cd+K!AR}?*f|G++Iv2|K!?~(JYu?}1K;fRvL`gTKYE9)UPW5927mmrYQ z``Gt7=@KXB=iY^%>b%4Gnq3LcF|S>FYY=lW{RB@Fc;dswjI6B*KzoN&%_d5}{oJpC(!Q%=j|Shq&YVo~_t0;r7xye^-BVGbfRc*uPJ>aB6c-XS< zH(;JydG3Ga=ie7(92*%Uq%30SzaPi@vt`dW8JDG6b$0yHQFD4bmB^QN3(SjW{d9mq4XL$m8aP0x%*v&Fy zXyg{a$nRA78T78xOM*XsG zB_v0Mtnrpf1G>yTqJ@skr2L^)bsibZL4I>ZCBYI3Dq?W@9I$VG!NN%$td9+bbAP|D zvZu$)g|GNxkl_BB6SA__G3l*JT@l^hREzSr&A8znF_rRKU$3GfbjEoT;a{$8NJqnCLC@gr?w2Q!waJ7 z=bu*$ZM;dN9P4y)u=Vo3q4o01GfNLuu~L$Zgj&kL@#%bLZ{sjG>z4%?`b9!VghK$I z14W@B%YHwGls%!#+`ng=ZJw_d<}(^qk$uqO8-&n;x2$$o>VEP%X?e~i>a={iUB{Dz zflisp9=$y#uud?XUe8D0jD=^599amNyx+%%~^$ix-Re)-;6TOi7@ zwp7)v+QqDtgfaj6a+WWnHz7NveK-lT+3NejYsNArG>Kva$!HExP*9~_Rue?snWcpn z;z3)Gvoc7&r!;!QB|bYG9c~+I={XmKd9g?Db-2+tc~13#+bi@qK+^Ns`o-Z+xN0H+ z;fE*vMVJh_+vFUGr~4RV_E{YRk^&HaMT3-%L6{ZUf0)2=kT zY%Tc)m zWp&;A_G!H~S+tT#G&0gjT4$ubqQ7i@X~O0m4}PW-UQW6Jbk>JcQb+68Oz z_Wbe;Xq(I|zJiHrNncD50x*VnTV>S3Ic@F~MpOKg+=mURfU7Rw(N_j=8H=L%d8hCX zWbYBB_7wK+URB^c>SO1&EfXNUz64wvpTS~}X*~NOoH)B<+#Zk5y^Z#N3NxpSS4-Bm zKJ^}$ng={2y}y+19rADNLbEk;#eva((o@$JR_s|?K$JEzbZ6@jdYE(ed24f>XI?|K9&+X9k42RWXbn^+!4WE%Fex%4|ckSdd>{j>xx)*o|A zTdhZdr>5>+{MP}GK%{bAi$=v#>T)mZ+8f^m9N|hQ7BVW2v~JZLh(R&;2`0a z0g{SPtFiTSn@XJ&TP}CAb-_cjwX=DqhVQ-j-k*F$^gG~%ED)Lto9($}d4Rx?4dwCh z?Egf6Pepw|3^>kMaSFg+gKkGUSpeON=v_0j za|0g8GN9vh143BN9tD$lyH>Kg}Fg(?rZwpvlLfIzGTpwK(*FjL^cW7JCuu3p7{ z0*qVlAx^nqTnU-I1~BGirz(T47b=;o|nq4!45;NV}C`*4$5m{7W? z>kP_H@&kalt8Q^8bi7o?`Q{pmM%5xLjQNdMDAiLzHW9!vHdUk*OM)eE)UpTy;8PgG zTV32|SNQwP58nucP}Qwl!s&kgJ0<KX#5WMOD7pEN;E<~L;^?NNQ6kozd% z@q>)G7pGA^aWqUL$E%TI0<|zm93|A|3Vk9u;hd!3z{*GgQy?H^IyZ+x2d1Oyp=%lT za%FWu8+Fmg(trC?t?=ln_@h>$2d(Vv*Cek}>5AS;@H7qS!4I?mg>Ba`>lt&J_RD-{yee-T=XxQ z4q2>=KSy@lG{Ecg)5=><>%z|<6S0}^iPOCP?J8cPqS#?UT}Qas>tXS1HiEcW*o zk&$VbuIyiEr3ti0$vAyg;#n(fi34g+O5#d2?@Ulo?Z9_zvwHg4aQx!0Nc&D`+Ih2B zFzCvA`{}`YmHkdP0SvkDMD3L(Q2hYgcoxP$G`MPD3IVaP-a-fMy6dEm8Ebf2lPW@V0hNeCPMR+eOhF-e zI0n7}*B_;i;^zyqYJe94Km%pw57m$D1424!pRj2uDXBP5^?=uaYoA*94eIorcr{Zz zUqp6Yp@gNjfaa~S@e3DW#02Eesnou{TjH?hO;nWh`NEkSRTdqj735&$Hgt#gw+X_i z=Hw{phuEP8cd^R(jxG(|LZP5-C$u>=GJ9Irw_&G$JM_wKL;9E23Cuja0rw4H8;mEC z=!J{b2Cnf00zf;UU>li7Ui=Rdl{IAWaTb=0q0{Onjy*8Y@k9QF;}oXq#Gsd8O0zB z0CzcMaEy`#NWuBgl8@xnb|$v**hG}GRHrW?0)Rab0>Q-C^WGLHd4=^mgI4=0 z`4ICnOx6Qt6eAUGtR_{Wn?);Iw@I3sXLBy&Vyu3OpPygY<3Na&6$iyU3r~(of3wXc z3uECejVp8I6!>D>c%+`BH;QFjMIYr^N__wy0b(u2ei7*y3L3W@!pmn?NSy1>rM~P! zMgt+CvTBMYY{nUX=<9HXz1nFR@W>r(1^Ow1?5gIwG=P#Ww0Ucg@>NN-Gz3&Ze&iV4 zl$zi>PGdL42H8DT?%b?ZlCNIz;qfDq7X3H5vKm=Q$yhrJ)gJffX-U8!U%%}ahthb# zQzWXnj=Elej5PpmP=oj2m7mY(d~LX{r1`;yDS7X(RVeyoTk-p;Gy^heotSi$)9n)? zzwz=?({7w^(BW-L+^ZFSEQqKVAD^R^5i5@omPdtaLP*bS#!+W#WXER5)29*%M=wTX zg3UlppG3~~0pVP@Sc3NuCGRF9fArTw63Ts|5n*OAda5=QK%650zL!Sicwkd^8TnA5 zh-wZsG;E%5bG5(7hF3KE{_uyEO-{Z`>M8oa{JbP zU29L0^3FS>Xk`Jpmwi3w%>$9e+b5@VhbX69oj;@U5CAS=a^0Bo@Jf3*CDkhxRb$ZA z5~0*r*VG)ojSCgazIH6^rU61+nw~REG5P_qfq6#S2LQ-6PqBD7HfJm!)lwVnH;|=XdP;iQd2JduXOvU_K8du@%Ri<+XtFK9XH)Ua z!fnXu>8&lHxb3@0|H*H}u6c@U<0sw2~$3Sg(M1r5} zVe>5emwj6F+zEMzLMaaEHfw2{oUktW0%t~T45&HK>@Ma8oG+6*>=DoocCRB4Z%T^P zpAz@tCus?tfu+zt_(a3&$&zS{S=Ov-c6h%i`l4)sYDP>X4%04J$Qka9@r*4ry!ZO7 zPGjwm6&PKaM<7}IK%^0d0XluBQ!#-{ooca9YO>$AbTztEGt6_vFTNqzOYTtJ5c--U zQ(XR&z|IVA2U!N^Tg%6L0s2~D#N*`~B4(5ybL66|c~G;}oZ5a5rF7rCp-5<0iIVe! zmqeuJ=i5;K;8+gibCI%X=zgoxYJVZCbbX#WEvxNJI6vP$%l*=QakyC9_{c+pX<>#s zs2RWCorRR8un4_^jPgNZy?(6ARp0t}DY7eN`DFkE!JLFyEDFnP{Lua5C#vSQ%%3fm$>`b{y^~@x(wc z?TyHhEq*iWgR2hVDtV@tQvNPD!Cy`A%fJ-k^=g;&ON1L72a0Ds9p&Tge-72GH9U!8 z8z7BRNf8~=mMcpmXY4$IC;}dJ|2D9Nc3SojI^6%tmixiBU8v~U)uXY+W>o#{%&zOw zJ4)lZu+H{esjs|l(8qyQ7@A%57cpXb%CgDcl^34iICfpi0qG!fPFNg}jeYR-ev&<^ zS$o|Fj(l>4W=!S4RL|_oIlbS?T8_NF)J3e_?g{LB!Bu^T@7+C7UtbR(qKJU1zUnn( zq9pKgjAD6F9-_$dSyb~mc6RJ$?C(x^vCrYw`-@@|CAljXkMh)lYsVr1prGr$n~FXv z48pV~t==A1vt8{l5D$%lp;d*Dhe&|~gcCcJB~*2$Hb4Fy*Ko6dJ)?Y1M#6*&oB*s_ zrN8a(=XyG`CJmUJBnowejS5{u|B_&^y&It~4}740SqCe>wQ$bIg5hEfA?|H=89L@* znx&Do+KBMS#Kh&RqP?WB9!c@P!aXbR3CI!r`s`sb8R)Db=&6_ z1r1nV1-p=}wyWXGzF`7O+JBrlu$pw5%m|0L?T2iLF|B%0x0=G8iug#7=SPh8SI9rL zdci(G>c#P(aSVR4S@86^p3L@hbc?+Flu28q0I_<+ih~pL71>9`dWXUt@y{gJs`Yjm z!Y1y^N|$34-Tn6a=WJ1Ktj#&VaX{?K;vi&eM8yTqS=%1-+I$Xuq%AA-NLSsish4^I zBRa&Eqp!U?uaUUP%l-FrAyjj!#9_itY4q^adC#Sk8^8^Xcbie!AbSg5=(wSrsF#iY zwsRLTZjUmCP(=|YUBl4@=68XX1Tx0zd=%;(1OdPXzAUYCz#$K5rfj!?;uoO zH}eD}><~h{>NtueMe_LZT@8sLCP&ShxtrP(A`bYy2rB(3{>?%;vy%Vz?B(Z)v`beu zpgc5?g<_8hh?K8y(LNR)qaO53pP}dE*E1pUT$t5>MMzfQY9;>`V#Sx4u-)=Lvg$y@-}fyz1PdglO@#fc-!&Xln(_;eJ4LuIodYeMb3=Gw!DNV zN*J2}#?ZsX=}+=Opg6>R*e6PVOW89E0egSRP5~?e6cyn zASr%t7a#xIggt^(HEhyqdyW8qQ-hzceez(-%bkpXy>v-Dq;fy6m9ZK+s)4y8Rl5h8 zmw-%{n_~OD4w-p{ht1Hb^lc?$BUu=NfQ+J4(+MsCuRv!mfl$@DE%oO!b#?O9(v1sZ zg8W`QiqTJK*`FEOrQ7D&VPw-FCShgS4E$#Nw?UimAui&zxGSfi$A%l$_t}}5MiY*+ z=bn#+9g%Tu-}Zou| zcpPQrALR)Ux#wW5orgi!1@ZDnb06S`Ngce{zbjvFjf+ruX%+u)Q%aL| zkN*q)82!P{Lv%%K5Wy-wZ-thH-QL-U-0bg7QJu9WdMFkSGAL;` zS-AUr;J#xWhIEpGEW`cWmR!3w`sbQk+{qa+(bD4hAYB9QWs$*5p|=JJ@f*#Qx`^fS zLqG&H9Dl9C)oa25uKYL(8|s2TEMRD8R1}cHk;nz}uJS{2#aa`BLov5F^m?A!0XQ8P z`;A;6IP5g}E}8RaAx4*LO+6IokgoKKqC@4s%2#Tb{ltxlo8tIZQNof=X0RaJNY3UZJNlJ)FN=<4` zK)NPMN_w6bWAAUT{hj~LIKST*-x^~%SqpgL?(4em$DsR)(j+ITPC^hwB6Ckd1%gh1 zFL8T`aKVQtoh%Ocz;RNM7K4hqFE4`sz&F3Ea2J9~!%rO;!9PmuaPNT=1f6My|HWyu z&oPCd;3OG|yK0a1SJA$&b~SGb2?_qkQ}pExfeFQgUl&j7=^+e9aXZsUU6f{=o=& z%KJ#=KAaN>HV4F6;!qrAQJiw=y*yfxJ>i}@mwfChHqQf7ym4SO;eo9K|7ZWp;eeCx z%n~>+xB-1O)A1L*Aw-Sv7k>0)e(*h^yYvtq{P|QAB7i^fpFpSKPa<5Li|{8IJ}w9R zNl%1t2!D!_{oexrCxid9ga7k||ChxB5ly@W2SU4iiK z1;HT`c@gJMju=Gn>Kq(6ojGwG?mvf4(_jC!GX7-hNt}zKvary4TZtO)Uclw>dku%u z)R41&{>=Xm+%O>J08gAaZ^1uR5{r9N$N&h=2A_`#{Z?YJU2Gl?zS+Szm!517r8n98 zPkQvnqVx-;m(ECheM9KMf)@nD6fm*nYv{-)OLRSIgE%ZcRhF^s^ebXmHr<4fH(EaI5;!t`Q`K*elVbK8etOH7(;Y3e`R;bQ3I8DM;nqvlDWg91zo>8_ z9y$oURX%HfBpThYw{+ox->TKmZ-sQ96n{*G`y7=1JQ$2S;bHA+^1qo!-C4iHxxO4L z@|4|m%AaZ4#i*ZVyETPFDN%i#38$bo;Yi4^F388*bO``E`MCU&{3 zjNj2_RIR~l1T(YDriava?;UYf{rTzaVZ`eiY@R{2itnCfUAo;3;6TosoKZ8cIIgFl zwyewd4!pcA?xAd^b1u@>Yd2^Y+N1MsNtgEvQ3<3T`vj37q~tZ%vHmIl+RwFFjenCI z4UO5?j#3j;rIGutRf3*2@~9#DGf70V1Z6Jc?C0p^Xs~*kID%zppm=a;2c50C6v~fQ zz0H@hFmA#)b>&K?R)In7WAQ_|*rK2Ib^0RSdjX$qFJHjEW>^kAIZUm2?BttL(6;c2 zy;~DM>WND+R_iwN#lAIW=I9xon$q8n)zD4C^}Y3U@rb|6?!gw3Y4({QHaola`DG_3 z)Xvi+{*|*PYv1(LN)`ivLrVnGaa!u}a5O@0M@TJc=5M*xif7Z`B+gKjjsZc4e=|-i-C z*M%Tz?PEpZ)A~(-jOex3aAZ=a|1)uRtwQ@>Zo1sd(f>ZK^!5h6-cEa+N&>-TT+VbD zsi(if&g;LokO;jnCP~Bld->Jc-=VzI(+`K952O$vd4`)nA|88tTR8#yXA-k;?g%e^ z`Z=nZiTse|2}k)P&rSwGhDdy67am7y>E{C1+dTw|f5-Ox@JQ6Z{D&XW$-v%feE4l@ ze!_j)JI`qhXV{xNg4za|ZR#lebyHp7Er!4i)W ze^+}rX9n4kHolJeljD}_Ii>^1)fsvjNgFYZD{SMs>&)y;LE)T9KyN7vEhbr+;$qBg zm(Ot)-<9=ItHP;T^l&FRM;7vLDKzP#SptRUOxNK6wO+bPApXVu{+t|>^!4?3XLx^k z^zkxHhlAo5Wb&}jH(6;e*g+MjWueEl>{_D>|H#Q;!N~JL+=F>OjcY%uM37ZDcT$Q) z)<134O$u{&P>acbw(_`Qo&7HZA2yinS6bf7$UrTReXk15XrlHr8CteACw%>%IsMqu zhS|Lf2bW^m^jPN(5q7E3ocy_FsDiS(l57`Q#EcUeu zBbnY@q-L&sr1luEM7!8Bd#b`IL+(Fo5EqL$87(R4WlFa3S7zwg`cXXR3c1*&va;lC zl2&ONrwjSOfYM+C`qCyJDc&V0VTAmNJw4@polRi{a>&4?(BW?0u&b`1P-i`#n z`G2*;{|_rZ9TW!_zjlMe)UFFVJIdUA*?+lw+onU$ZLnB3H${LFk+}hfk!6q0_j)tS zIU374l}q7oFAKQ3n1o&a(ti^X^Pl#nlg**ZGQ_T5TmN}>b}v&-Go*Cr%1m0|5|iRU zV8G@kcWY=3_I39y;Qa;toKf${{J8#6HCECZne}Jw&30&NZg2MUKMxBxP`GKGBpybS zkFwg@$M*O4pGRPks{A073768g$?u6l-8uhRvQBtByCg$3-#u7q^M!8KacgQSKjkBS z^yYJD98UWMZJbf{|8@5{BPqvw@<*NX%SyuTLfmj&EBVh%R@ zHJ!G^N%iPtKswvl=wY%Y=HrceA+O&Br&&#rcV*U1(@?p-rpR+dn zsQLBO)H0vZqf(!B(?g}B84st`s;e>?D%C!2r30_4JC|rZ7M5BvGxN!NlI!*+m=tw? z-s{rOA5==Qb6-`!D|u;;vO=NQLR3TuTi!D)gA$-6fsQNwwFX{E_5GhKBYSwH1Eh5I zKBsf8e9bbj7^sYQ*iHIXd;A-~ug(L*V^Wv5y8fHEY936*N7(?Tr zm2S-O!3*46EA-hW?$2P2%Yt)a3hn|tW!x1WFE6V`#v@4+Z#LuVqd&1`+tauC|Lp?p z98kWTR7T`SsuPB5qlpBQ7x5=~SPKaZ_c8X$xdTj$f@Kmxq>VB$6A}NwRYQWE4DLij zpFRy5z5gJ^r5&7#jTB&pYL;E({>PO=A(l+7+P!DY?hXn3&QV@z3JqOxvu>vUiMSeg zNVy^jjg9^Hsov%g<)uri^=V~5D|(*&;14xn-)7a~4DELWaD~GoVs`r`CNMt!E3J!N z1XId&zT2zp+`E;FZ2wJ9(s2>P4%jy$=RS#NuS6ho+V1BrD$87Z2-#V#e#g0ErOYfX zS#C;l97!H^nyRFKe2o5XwAS2=Ho4hOxpc@&{=Y2CX)jtnp~>*j>%dC;zP}-+v?ho0 zY<2Y)k_(t8H8~?=`ZWTrHdQq)u9I%&x@E8}dtByHoya_DN0hrCJS-zwa@F0v!%mQ(=DbZ6{dShLn;EezvDPwvxI|f`H`6 z@&=38mRf?Si;P^&m8x8wNLIgo9c;t3ANd+@%)YcTvK$imQ{mke>-(^uX9GXKO6dP8 zqgyaQcGZF04ulRauB~wI0-vd;+1kM8mtdadb7hf{ne*nJOoNtwQHt>4L0Pfd zO^V_MJt-EprPwwJ_$c#^TYXk?wJ7M$>dqc8x-tYVWACeaflajqJNrw-; zx(H|r)Xyi6x;<_R!3g3nA>q)kOh22gf0U5ov1>iPc;&n|86;{9xDdUcgdh2qGdF?F z|7AVsL#M1a)gVz8P%0l&6iugpvlpUc6ciMWC>9o$g&qj{@`w2#=K4*FK(^Ghv@uX8 zJqPsu*&n8Yqxm<9(M!v9&;frd_`iPZ)wZY)Ezy zO87$+F?9ZBkstnJVsznQ6j+wM!>ucM@s{U(dfnf>OGphyeLUq?~?*HO}FxYW&Mk0~foRom0Yl4%Tq zPB-*6y=2a>9_KVSCXJN`%u-vYEL$aOtmkk%ts)!;d)26a$?6-pvr@O6I18d~o2hbh z-e*1Av3gvo?to{nKbdWh-Xfx=k(N!Q)Uxc2@llKK&P2mx77BR*_vRiw^eVUF*DWW( zB0WO=tGnx}#W#*-=3-}jzA|;?HY?eTu4pVzrIS9Ts6MqaxE{rh@o46oQ#u+@s#}S+ zD<=yEl&NXn>Mwaz5jBc>KYH}2Cs}B(Whx;$`hp&{k&dqJ%JOnQAvnI<8pf(T&l*p( zM&*|chyu!VYq~9bSv4S_yPf2`6TB`wq3+xsdR2O5ob{3SC$nO0dD8j7ay z==P&fZS)*33F*A<(_M{G%~o8z1kqa~mo0m@AV}Cbwo&~wZbmMbdG~^U^Eo{*6xr zJT`NL8Ced5aSeqQg>&wr@Sq>Pdbm9ym++I5k_OAq24rSlU-JydSMnh!>2^l^U1Gkl zs7OjO>B$ouAhZ|mYhUKN65a3J@pH-YOefGIg(k(_h{p{b9aU0Pxi5?O=%S>G1so>* zgwL>CJ_ik@V1xdi+8+p>;K`Nl6p><5+>T@+&&|_N$+olkpRI6M&B%Tn>~0`=JqDJR ztOgQGfx%SRjy-0h@*_#x&-k;O#i>)L_THx(J$|f(k_sO!GY>!7qu$%w`*HJaGb=m0 zLA9f#(w2-q`2rbI&g!@9{o1~LD-kZUm<%nxa>sQg?&vEk;hD?5TrGJT`8t($gL0Oi z<~Njtci$#w3kV%<_UlyGjC`92>P`}f?U?1Y9d+Jae|R_&3V=NSy56`8O0Q)flOYiC z=SYt^h%Ud&%*^acL@cw{r-km&#zVR{&b!``%~V;31QCcz`-%DxO7XeNBiTXg>K04(_*6ng8|+ z5>yv2_RdqHIEcpcfokZs&J}R43CW)Gt9vAgy&oO4zq6*fs_a&z!5p0=;Fh2yEiJv; z;jO@3IB2D+syb)v<5}nA6c+wQ&Nb5(F7q~&vzKzm`{<0#+q?$E*Xc_IV@=l0STe``(jZQR{S z*q=~RvA_eLi{16@CmE}-)zQ-%++c`efNHK}YviNdCcMpxs;jFVs|D}eiR+k^l9Kv7 zyI$|TFYgtZ^QLEhHlwtZbL%l{ka(-HGTXQA`Hku6Y3!y-t{PkHb(U)Xz`iCgVG(|Q zkFPDn@zh6Z$;sXx{zi3l~ES z2PDT6^?-=m;ZXNi*bUOjAK?GMY9ctleHJGOJ>MdF{+2 z%D57a%PSCC=YKz=KTD}D@K|zcV-y55oqFeGcyYWb7JoJY@vx< z-$0D^Ecyy&Bx*o@SkS&aH#awj(4%e53sH^~D6xcGsVC9I81ENF8J;YfuLY< z<^H;}9fMYo;=k=|lk4tCzV`eS<;n>U_pxc3@X*mGR?Sh|^j4WzVF}ciqmhG=zXVpe{1!wN|ql{c7opmLvuf|O3!YpUtF zTr3+a8(Re@F7ON>S-n)ZZ3dn?7h^T%==k_c8%};>hEujmpCJ}wDzfsv9Lcm0!3lBn zJ(S!BPjs*#)Z=|)FW`>z!mFL3J>Gl89dswi!dPnLQZ*G674tTrYi7fQN%lrYSC&vD zTh8g+k%Wd$lHccrclhk_YKd8win_H6T^IYV@2=(CInRR*mBGH=W_w~c`ahJcnW+-- zezJSHsP!J5A4w(fN?YU&XJNED&w|Iz$0@poZ2ZIDrlrqJdkGt`#b#$`6E{NIkq_O7 zH}j&SqjTa~=pA-~ebT_Uc6pwhJ?0nL|iB8a_k`h!z|3J+NJ+T<*#(6@r_+;_I&+_buKe zCUOl*NlVxH-j0@)q^)C<&5W%6K78=x;v9Xry+5ajh&`>B77Im+*LwR8=uPc+6{p9K zt2FWz6ck3X39%H_J@)paM{%^Bvk zcZ7w7vE5h2>$evdTSF+(&~a+mbf8hS~D^-n3R$QAANo1 zjEmhOTJ!z6-&HKP{*8CX%4*}9TCN&%YzHH%y$@WXv-aI(zV*b4yK$WA52^-${y2Tl zw^Ot8gtVr!XdHb+vql<_4pK$E7qQxXr@a2+9XXR?TpSgbeXiQ=1}q6FX~#px=VBjL z$hR&e`nG}uM(ca<9fXB=gjF^U4O<8H+=A_C+?|(k6SqNiKtV~lbz1bK@`Ljh;n)f) z_{2|(7_M(ACGX>fcG`ux?~*(CQbtYbdRk(}$V^>bsGnNt^z+8e=3G)r5oYydXYROe zUz_`Yg`(?Kxtr2w)#a6-_OUg+qb!BQm29VuzS@mZ@-7TWl-oUCSOp3!skvF543>b9 zUm*s4y?4WPbu_c*PSN7>vd)7CU&_Bkn3h)qPMruN`va-gl3!fCdf_=OeF3Y*X0&Lc(TB#oB>b~?ybz_SiE4PkK#<|z! zxkUV4VMiAZ8Jq~anT=gI-xZB>*Ge7|SGl>j2+DWQ6@5wis`yg7N?^}Q4)fT)DX#%<|DxEZJ574KB+A&c<^2)V^mVbKHNLoZ0h@E2vDB1_6<5rru(cI4p*uq_ zwR1n`*inyfd&aV}Mg$tRC$&oj;0)JCJ@{lozj9KPvi)5Rz8D!7(ZQrYDX88UNQHl- z9(A*1D<<`EL89}&b`w*Bwte2xPI3zf+>+_^CW=WMe|NG`VT`QI0pT?oiNNS^S!FUq zOqLC9yMtEhK9M&lLIMHP=rGlkDHjV&r;G-NmpS@#XXi_qQ7rB+x#AmxvTCn(I^pQ( z$R>sM<>@3oCn;Z}m^#m$rAtuiwZ)_SyC4%ORP#nBbn3Ww5~U$|xS74HFZCt1>0&^! z7ZCT{{vMq#%m2-9dCfU8ae;CdIMMQ3b0a;05RPM=D;p-y#bwB$6Zg9V(bL5PJ zo3N=&pfAJ|8X}fLejE}wzXREjo(!mnS%H&iJRaNd)8|l~XLD=oJC!-4C$VFEoJeqn zYl+*>Xhwc8#u7zuUXTBb&q4kcO>N**Jw87ECIPLNfv(81<>*l6V)P|Z>Hp{{p5>;5 z1T89z4+6@^x7PodtPb%G4zR6vpK^Wat_48gX-PAN}T zZs2cyZic71`yF5vjG7C0EzXE zI7`DyFvJa4xp5xEe9&63(BwT^I?e&MdZc(ePR5`|Xy?uNB6Ga0m)AIT3b3J;mS+zv zbJbMDGn8@eWRYaeE%s+CM6yTAQnKsIKPGkP|0w-jevKkGmiW4*@4))}{QSdDD8V-m z2y(biH*R@&ySuwvS$%%HDVD||B(!RGv-bk*a;X5kB=~l|{*fP7VwX3#w7ojEh3YSH z-!Q{?;-@Yz)EC@E=}=zVkOS4Tep{~7=;r2)`;gA z|NY00AN;1D7;G)Zv=KgqW2BAcoFH0K0}gDH_@4hxwr)WpF#8-7&%9$b!1^cFOR(aB zXGTb^BLr#^>TNQdoDKa^Q#Kc0WP82`JJbzWmG@^Wtqqqpzh_A48AD);nhg~CdEeX8 zP&H)1S1kcoC24MMo=ds){O%;ldvMr8Z*E}nNg}@bJ-s0_?%C@vRo%7Q_ujOZo7>sh zff@r7xa_RvFHj;w6p9`A0~lV(cG7=4+?go0HqmQo*txN!oKnZs)vsz*J~~onzKRMg zD7UK~EX=_Dw&$y`fR9wQ{)5o8Yg||Rvag_EKYKN`Rr&t?d!VPohurvEn2d^RneOUl zo>SFAww10)E{YK5RWWhWWPoB<`fq~beHfick&-wSBNLO0Z2{*7zXS^4U4%nHr#IvPevt@;`JpEX8AJ^28pbv@xMym82kq=gy-vFAQDHa7YRlUE1aopho2iOI;2 z4qv)7)KTp;&*1nP_DGwn!BjP>gC9SBe4F4sQX!FLTzW&7cqr@$fc1N9*c?q3((t-k7x~AmEXUyP&ZKmEPrrNU8u(+V)HA(y$ieP zc`_E9{b;gVvf$(UDKEL<50uo9F~;+C$87f-z6^6M>F?DYFY>Z( ztEibemW3uJjJu=xu@d$%PN)So!QezZbo9yc&Q7-oR;wvl&r_6GaK8k%`JABj2G9v* zvS+B|?r?2ino+TG+2BCFz)t>kpHSc^6BETf(nUsOj|*FMpJKS93jCk7Gv_79DiB|b zqJCAo!B}0v`w%J`v|4AmQQd+1!~s>-h1e*c(u`ymZ2v7u@0hqQo7n1}2j@dtL7|h_ zntp5i+n~0ykh9}*y8vFqz1YmQz5q#QjLNIMEWd0#33@&cLE7MM!2ulK#Ug7m!d zB<%RT#qRv%BDhAd?6Q+efOHErW*;fE8h-~Mfs#$P%6YNx>sRB7YmK&RS9J!OqMw~o zs+uB>jhV4t$2Q)GmVIbu_L0G<5@*2_nFyR+g`={?GaipIFF_Em$7jiBJwYs)fo=;m zT6%_t-&CYU(FeJd?zvJ^^g+}U4&jY3Ybf;05-_7EDJh_X0TgOJS+lU=SSFwE0hu7q zR&OL|Qp79Y-Er;Z#u>JaPSkuprtKCV|K~(IMIGpG&tQ9(EN{@r*F!qXC~(i5HO5@} zQfjv_#{#N6#$t+-&uPwVB(T}@Y%~WSQYO`A>5UxrFPN^IC-%&n(AG}yf#3l$2<1is z!jr$(1e^{B2Y_jW#GSA>`t_jJCX9lWG&pi=sf6ljhx!-4Js_&{#Wh&lcauKMN?uM!F zSSY9GsWV@wHv4e-RlD`c-PShvWXd99*OiZfY)x{*u*d!ldNKeNAq@?Ui}?BoKyE5~ zjtM1=ikfko*x7ZAPpr*)HDS%4O|8_l>PQ~hu;X&XWm8iwO8N=Zq+}vQwIwB~)){&Ll`XBU zO*HP%R(D1P2Dchl>td>%vfrypo>eUbOh(5npxP?6n?B75H9VS+zKK|=u}0m*0SZ8--A!lm1-W%tkx zz70Z|D!DM<*zi;=&G6^_+3RI-Nvh1z1GDwYg9CVdt0H}Xh3qGAqNzfQQ>jes6N1J) zz%Z+}Bkvw|h?5GL4&8F9o|+hAJxxlQsKe07vi?J;|DsFVvoY!7Ul zJ1r;tv-or9xNlEyMI0R!??IikK9=v9n`loVg;So9l3TytI?M!rCSl~s-B8|epyVs8 ze*8V%gS)iG0fx`m{uuK!9m8Rs3dMX*pTF63CS$QzV{06?c&-~fjwDg4dJjx3a+{r< zT?t@nrU}QgbUi|vZm)*mqF6C`{qk0|sG|>;$J(twpBE@jptJiIblmC)lRH!~>r16F zRygw4F4cN1VxD``DW12dt1G(WVRhyMAD>_(p_WiDwk3%ComPzz>j}et4)-^4xgZ&V zT&wivj*-tDj(i85#CH3z?=?gVH()z$`S$JGMm7V&nCuQYj7&U-Zu9Zwn)`*n(eO~Z zU&T`4^o{547d?GoUGM=V)t%^yVrsKG4qaqo=8j&N`7S9$Z?j++CDAHZ9(0>JuF-7C z_&CY0%a#E~?w~%)hh_M^Wt7nP>QT$2ZQ|&v2yVfThMj^;uqg1M>6em{l&}*S0>wIQNf)=6)<_zcG@-Rx%*3hRsRxJVDy->JYZRNe zouh(*!Nlj!!9}4O6015Rbs-@k9t08`l+*vC6x3kW>^Exu4#YrX06STGKAQkftD5SL zFF3|+yqADjSn?q(epY=eFCo}Td9gcm*6ywIyvuSGdEJ#Ey^NY~H*5+2b@7XB;dH2< zpAZgD?5N7h$~*$KVZ43%1z^Jz0i5qCKey|Jse5#uI;5DG*XiO75En7l26`B)xtrfz zugdE8cZ>%y&t!S%Io9*esVblu6Kc)QeGl&r z4z`t5E3YVCbGeo&Q0)FN;!>~cnyDgyks8(R>Q#j)aN{RGh> zD(~_Io;#Klpko2ow-N|5PZaf5SPBEMhu3h3pCd4{Z|>~slff++Wd-~jTd*r$Ne$lM zZFJ1r@!xt%Rm&gDq1@&mdNU69%{H;|dFBXJ-qGdnXK4%K&&Ct5l-+%EmSJN1a7L zoj)f0j6fJ&_D1!hP?aE!03*U=?tcJA^!!JyRf}dByQHFizx6LHDA9I|1!P+m(GLoikbejv0fDpa9T={=y?K7C9p{D}rzGJQKB(7PH& zi>D<3`nw5$4GWTe1UHJyzuYg>08PIlw+C zgfr@mpc@4iwf4uJ(<1fU!476KlZ-b}%{D&4^DuvaODC9;l7a|#`HnejPD`CJv*Eth zuVHN0AGu$((ydP6HIdBUjEU(+HJ=3#NXT=0;S&ECAWi^vJxjrC}9zsR8ae%`;2Fn?d{gY8e`$$ zNH2s3UP+xvmp#s|*HMHtZM6|kDYzRT7-}waJ!}i3**=P(yOv&G{G%e5{S%ry*6oQ@ zu3B(BrL}bZ{n+0lfHzRxbE)KpQYgX1{B~{ zCEUyyHRcP%@8@D;a}va!W*+{y&()ikY)w^;&n^IYmc0?;w$gk-HD}8oR`|Y-8hz6Y zlbd_f(qY}~#&;2^ICau9XOJW>EE8MIwoVV{e6C<{DLG1BBe8$`8`ip<<02Y&nU1%% z1v3X8bTA9`3zC1oeY#OuM(JU6+=B7Dl+W+6x6!DmD)-@{IlZT`Nwc+Fve%@gqz1-# zYR4`N=3P`y9Ct<_Rc+=56EI4N!K97ri{HLE3}C{n5_fq%(8`D9*~qC7E-Sf(00TaT zsahg)P0E?Y#o_aOmq4-RsI({Wrn-CRK40PDEsE%z8I9w@({p{MJts}BIW$DMx`RYf z`Afcfmb-aRG8*ZU@8;kL1f?YS{n@^UOmsUsA}FS_3+W zjL|utaL#C3nI*$RbZ?s0@9BgRpJPm~b&Tm(=~-D>Z85bE){+A3yw<*qkLyKj?w|`3Z_a65S)IIS~^PvT;g91gj2$OEo9}LAE|1nJp?_;(`K61{&i9p zEV_85t_xk5AMcV$Uqvq{Dvw%+zlcX2+;9LL`Vl-k>h#gMBy3U+L$3c;w&%w`jmd(1 z(6ICFb|mp{ylVAI7vPblYpw!;JLfFykvVG2Scyb$rvkz9;e8v{wWh9hG}$uE*{!hh z&$n0SndUd#x4z9}t<2@#F%Q(YhbsKPI`s(6huJcI*|u}ezJV2TUXE@x7ENF(CoH#6!) zk5du%i;)ovU%gK{mufk0yrkwqFPkZ-M7uryG$tT_di!I=4dw?UA9^sFcKOdN6W=qK z8MNN3r`7@V@2!>>CmXSDQ=uamcC?LV({iRQ<^&b1&>GdHci~!ze-5DI>)Rk~TbQ+r!|o)8x(T zy9azJSDfQ~Mmz<%$ol!utdteYQYSBLtzEN2t)2?*_!6{~ zABULo1l0q(cRNSO=zQ7k+Hmv2bxw@99_9KG_(_uZ;|Fb$1`B^_Qkt2t~|U zX(5cONvj-F+-3tzuUT;m1dj=lTdb0V6F1(ZL(E2-0>eCyC}5<#;8#a^qKZ6Yw4$o& z27;0y_t-Jk0*=0sSp><6J^^X%iY65jN#4 ze5K(#?>hSOGZI5$nV_bJnX8Tv@F~UY$MlCxfR@E|<`%}OBoyuA%3@JhUv>}x_9FyZ zqu-tZb1qk@o$JaO+N`M2YJo4-boxHIw!h=v&%Wh$(odt%+KpJWo{c{ z#dkCD$4(|{P#B+YFrD7}KqHg%5CO*j!02@n~!3WEp779Q>gh(gxZpSETezv(^mfy`3Z)gIS&yK$Fn$YKx)m+WvO z{;&woy~j^)BN0_BX)olP6aN`$K+R{nzH|_Mini zp9uP$Ozb3gNpRb0cXEo0i#;bi-##YvtXoW9w0^~~VKe$(h9u~Xu($R{;tV@|9%JE1 z)qGH1+_|$*XgJU5H652MoZTW0m-=i{4u*o1SDP9y>F@Zu)pFNN{$+i zLW}k9?xL27@eOe~UR7fN4be@>MO5p(@2XcL-Ku*MvkIEhosEV7vsT)t@Nx3HVc)bA z9*=>vef(%TW^(TJA+C;-YEHET@7(v+ikt-tcEKh5BJIM@Jru`eeapeKDK=IquZ@>K zRNHe3?|~3>Lv^|;y^U2VHrfCW!GLu=1hln9GpIAWL_9w?H9ajtI|0f$ z-3Rvta37*7=jzAQ!cVY3Ir{ z`-@4fC49+2!C8~ON4PIbu{M#_dBazlN%0NG-7jPD+ZN|?Cl|#&GBi9N}Gat_(Tq za$64-z{C;78bCWVJYT$@JrM{g&>J zGNSVEB)em_S%Uyg2gq7tCk`&Cu_mVmns*~5%5&n(x%EPTGj!hgG7y>zdKsXRQBON& z+u#su)8WvLk*pqD#;PCd2Q;@W;K&bD`WG=omJMHT1%)JyAnX@fDs}eC4nfc)tBk9%> z_h#j{8Nl0!5172#-`fND*m)IO`R-jGU?nRnj0_D^!8Ojm10+sELv~CJ}wS+FV|MU<|D%O$(6x_EN##T*HymEmEm5W>X4#3Y1=@ps`r3( z#JeRn6gpjy3nMn$J78euD7!d~sZGocK*Y+jwBlm>M~{@j#Ba$$Q5m4Z+UiYF^^ICp zoIQec_5XqXUS7hnL&oGl1?z9!q}*F3;jZMg0$we(YQ|dw#{t)yzaz;<^mRX8(25;* zpy==Q^lyZ5@HJNWPXeeh)ENcTo@ruWwvxqzm~+oCIk?`dfI7#c%tN0SHdUWLZrkw9 zPV!|%>}8j-M}-+S&?I!|G_c9JqkP0_OMv zx@HHRTs>8qj5VA+iDKY&!H;qY)*+vwbj+ z`P(FQoJ4|vj6rld0wV+SrH#^VslaTlBFi1C-w3QMe&h(s_|tU^4-IYaj|>b5_=@My zslC$ri+>x*?J>Pq?!{H7#!LfHdTAT&ShbV6r`rBL0V4a}K-l&=rOG|y1UU`TC*R7e6&AhrMbS_gxMo4v( z_8y|c8Duq?ZD0=DAfwj&yy_YOH`Q#|%}MJXg(9E=QgkTqf(OovYEddE{n@Y{Zj$B0 zhu4=bDIcf5or|=zLu37ap(rHLFJ$Qt9v7v5)W)ILcK{8$c4NEOt9^GT;SLXL>E_4P zE*TbfcBfzhdU7O_ZSR(c+OKIDx6a!Kr&86^oMS~b!SER^7}qQp&_4i#)T5BmYow1J zt?764f`LfE5Xn!rmU41(NDL2fufd-A4L|^a4(Wh;VPL%k`uzNvrnm>SZ?guz3vYa^ z;ZyDkp&X0^YL{50TVvteC)Dy?`oZm7NBaMm>(+TfTILAnEQ;TAb_i} zIt}c@t@W0Z<}Wmuh=E&Ay%^6KDGASD_tuAOu~8lVTL))Nuh^+^shL@8PrP&*J*$R0 z1*Twj*^;_dAXx@{<~O@74H&#yrn(7^e4R_Gji)C4n&5l{UQm`MV&7&8q~1F-=k83l}x zLA}?A0Ku}Io?5{BYM1eqq~sb3$%-2?(-~QK0Nxe+fp-fMFc+B3OA-|og>+>K0>gH4 z2#4*{h^q-9p{t2{4_|V+w?uyFn5p5G@kY#z;0z0xF4-m3kj3gS$!uuP7D)!3Jg|xZ z@P45;t#gB~mlj?6_a@>bVAQ27(VE|#?6IY#B`_moD+#cqdylTA3rOB0l7Adwn;*m} z7Hi}SfoA<|0GMSqqxK`$$JHxFQBqRQ2CU9l6M}H8PyHLl_EsMw6$dJQ z+vBNppj2cu$&&`yudwI8s6dMA_w&mDW)^f;`G|=c2tWCZ8A>$jGieK}9y=F(#nvu~ z0SuacnE%1g>&7a(9%$I=i(kNmZU*AkV(*J$SV7|0+(F8vIsqCt?yjMp=QN=5e(cbK z&e@W?*jFhDw_td#RLpo?tD^X>iv0u+rC7&u#5uEj&4p2K-C5DsR`o)@3isdgiP4~j z3QnNgk5|SwOsxTf{WS0}{g3a{$ZY~p?JKjz3OLQZOuoVar_&dJXiu7`^+#fLLdI*& zqcn2;0DkJ~JNaCU5$BH4MlEa5SG|xc`_kT2Tp^zR+$C3>nZ{C=jq1q!o?yk?h@IcV z)1Gq2MA~X7*+vPQBGEHyH}uW)LCA(pvce#n0r1i^(Pnj9VB#aQ{&Na=Nyx&wtKJe& zsTetTeS%Nfy41jWhOK0g1*3;kkWJ11Afza83;fkI$WtHyFM?@+Elb7b08-rIf`XRX z9gF?#Rhl0qMO*XmUwvS~1EH3;Kw2O*kNhCNUoM1^9NFqh^pQXO{{4}<2qTo(UtfUh zKn;Q#gVlbL)Va4A$xACq4;>tOJDa|-^S;>)xes#g@9`BMFuu|tFR5PRF!faL!{%c! z<1!8ywOwlNVv0mSy!rlUHU5I7=KkWG;m-yVfb73q>dI_ID7PKr7Jgl#9+ zFj@yvD+hdNuGx-BALv3z?lNVlF^7hR#>*+rj0TIP-DiuKtGtYu%y@p423@wXL>nX^Wg>pf5oCp)(t-+-UV{40+Gq_^*OM|mZee6} z7p2cmDsoU_7kYhWhZd)C^h=#BTs;Ok*vUGloGZRA@9BSE52p=JK3FC4Gg$iN^oOo=o0`h!u^&nJdAs_ z!QAW%s#r{;299V?KaCyOMQq?!+xFUoeOp70)sp)<##%o;nK?Tq-b|m%vtOF}G3u-E z545*py^s(iY#*SK*y*!|sNv>KX*gSh$h}`T6tg0ttGF;f7Q} z5}>!?_d%Yat-6t2p5Z0JU{Hu%asxDvHVM%4z#nf)To<|yh5+J}zxN4v&fyFTZZ!&a zDHiBK751SNt;Ua<>9mO(;f6~|R(kTCLBNo|dzWrq91lMqqR<)=3B?n=?_3GIFOw{K z6ZBP*$l)%^K|h$?{2z1WMT`!EmcnYalOjn>R&)WbAp3| zqtP=QGE`Vht^|eo73M|I4&t9bXR)?gW$jJ;UXJ$kToPsDUI%=jAp!z|&6_>6AjV zI)qbFdMvJTATEDGFxmJ(;PJOq{rrcnt{R}o{*-|A0!8roPA5{482LC`CqPlaUh& z*<{T)@;#WGoHP_pVUO)_<=NP{o2$m}_2ZjKxDcafkDjm}NyHo+j)(B`Q;=9z%_L}Tl*?w`=HxVrF<_3a4ZrQ0pX>HhqP2tJ3U61fv5yZ%P)sHH zBa7xu&=i9w;!t^N%zCwtztj;v{?!H%BtqW5A+Mwq<@4lB1SqZz6+o8AxjP9en8ndc z@C5m-vN!xLvOs)V)W}nIf2MtQf-d229|@-P#dDc&TCu?01TF{~dWn7hH?Mia%~QKJ z8u09=ydN$g((Y^ZQ-|X~!Ppmne<<3xNT%DB>@j#_Rh$X~I^g{9UUEqGzk6v0U&8PH z_M{W0G36=?&|H-er0i@k{$~)!t{gma^WN)!)!t|WQuD7dL%;Iun(05RtaJYJ=O@5V zr0U}u6%-YXj@+5sMq8C50b^4)9suURHZa$qVKSuj-#sZqs_$x&;Igx_g6_=r*479+ zGt2pt0B@A$UxFWW$-OuAOyq><`Ow!8f9k-H*3-C3V4{%Ub9;repU&rpQG7iT$*fB2 z_3bXt`OCi=8N<;y(6Wr%=fAau9ccCJF)Sp2$_`HH;w|8s(U*EsMC=*QoIcIM#`bv= z;0~YEBqDw}`8_vhiZvkvGY?{3Vy zoPwa`dv0BSH}wD*Wl!)%0&(N<=4Vi$DE8m+1e_3c$fQlPw|~EfA?erj};3sHTm~I z)mJfQ3s4?M!Rsjbp5cu~k z3knKsChGN4_8G4Ayt7(6xdeJmz(SUWfH6m46aL;I8jOd+5NJ^e_nhBYcMo_X_VE=C zL@l<{@%MDbfF&ptKB0~K4RqqR2n#12Eui5W|7KKf)>|=?;PoCjwGa=W;wk|4l1Jb| zCHl?{f33L))yMi_&}wTSSJlG`7Zjc_*f&~ROg?ah#?3Fvw3f(9NK zz%IT3m0+Fe(0|+l^9aysS(W%8N5LErj~K9pnHdJ~?$WP2&2#CGZ*0DP{`@)Y?)_Kg z>hvez0rw@i+ysZL!-X0H`jTA!h}NTPX=w?(OBLoqngM}sc?bz#0VAeUQ&T`+b^o9C z&NHgXtb6o99g$(wv0y{26lo$VpdtiE5fKn+Dj=XV1tdXQs0j>~K?M{9q$@}fqzFQU zK(K-|L5h?l1ccB-=ph8i-4E#KJMX*hy6e8{e!1(PwfrK<^PIEKKKtym&)&at5v9go zXXgI*m&4dcdf~Z78Ad8i`wt#`?||of9M&I9`tGNzRF#N%fI>qe($spZOP4y396c^Uvq$YO2Tm-msSGegKzCR)*vzfTv8270?kVoB^s+WSow=JL~mOR+_ihu-v= zFEkeZwqz+sn&s*7)z`rU&uwmZ$Q~8p&8U)8h~'bJ4lg-TRu0pqFaEAxFJXy`40 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 P@zqp6b0X`HOMm_^!s?0x diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index a68ec0e3fa..1d1eef7c4b 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -22,6 +22,7 @@ | Rev | Date | Author | Change Description | | :--: | :-------: | :------------------------: | :---------------------: | | 0.1 | 12/5/2024 | Changrong Wu | Initial version | +| 0.2 | 12/20/2024 | Changrong Wu | Update to use two tables per SONiC Routing WG discussion | # Definition/Abbreviation @@ -44,9 +45,11 @@ This document provides general information about the design of the enhancements # 1 Introuduction and Scope This document describes the high-level design of the new features in SONiC to support SRv6 SDN. -The new features include the addtion of a new table in CONFIG_DB to allow static configuration of SRv6 and the enhancement of bgpcfgd to program FRR with input from CONFIG_DB. +The new features include the addtion of a new table in CONFIG_DB to enable configuration of SRv6 and the enhancement of bgpcfgd to program FRR with input from CONFIG_DB. Besides, this document also define new YANG model specification and unit-test cases used to validate the aforementioned features. +Note: frrcfgd in SONiC is also able to program SRv6 configurations to FRR but it is designed for scenarios where BGP is used to propagate SRv6 SIDs. SONiC users can choose either bgpcfgd or frrcfgd to program FRR configurations according to their own use cases freely. + # 2 Feature Requirements @@ -72,9 +75,9 @@ At the time of writing this document, FRR has been able to program the SRv6 rela However, there is still one gap preventing SONiC being utilized for SRv6 SDN deployment. Specifically, there is no mechamism in SONiC allowing SDN controllers or users to directly add configuration for SRv6 without involving BGP. -In this document, we first define a new **SRV6_MY_SID_TABLE** table in CONFIG_DB that serves as the configuration source of SRv6 in SONiC. -Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the **SRV6_MY_SID_TABLE** table and compile changes in CONFIG_DB to changes in the configurations of FRR (Note: the new SRv6 Manager relies on the new configuration CLI brought in by [FRR PR#16894](https://github.com/FRRouting/frr/pull/16894)). -To verify the correctness of the aforementioned flow, we also define the relevant YANG model specification. +In this document, we define two new tables in CONFIG_DB, i.e. **SRV6_MY_LOCATOR_TABLE** and **SRV6_MY_SID_TABLE**, which serves as the configuration source of SRv6 in SONiC. +Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the two tables and compile changes in CONFIG_DB to changes in the configurations of FRR (Note: the new SRv6 Manager relies on the new configuration CLI brought in by [FRR PR#16894](https://github.com/FRRouting/frr/pull/16894)). +To verify the correctness of the aforementioned flow, we also define the corresponding YANG model specification. The workflow of the new mechanism is shown in the following diagram. ![Static SRv6 Config flow](images/SRv6_bgpcfgd.png) @@ -83,23 +86,39 @@ The design details of each step is described in the following subsections. ## 3.1 New Table in ConfigDB +**SRV6_MY_LOCATOR_TABLE** -**SRV6_MY_SID_TABLE** - -Description: New table to hold local SID definition and SID to behavior mapping. (A simplified redefinition of SRV6_MY_SID_TABLE in [SRv6_HLD](./srv6_hld.md)) +Description: New table to hold the locators configured to the node. Schema: ``` ; New table -; holds local SID to behavior mapping, allow 1:1 or n:1 mapping +; holds SRv6 locators configured to the local node. -key = SRV6_MY_SID_TABLE|ipv6address +key = SRV6_MY_LOCATOR_TABLE|locator_name ; field = value block_len = blen ; bit length of block portion in address, default 32 node_len = nlen ; bit length of node ID portion in address, default 16 func_len = flen ; bit length of function portion in address, default 16 arg_len = alen ; bit length of argument portion in address, default 0 +vrf = VRF_TABLE.key ; the VRF that the locator belongs to, default "default" +``` + + +**SRV6_MY_SID_TABLE** + +Description: New table to hold local SID definition and SID to behavior mapping. + +Schema: + +``` +; New table +; holds local SID to behavior mapping, allow 1:1 or n:1 mapping + +key = SRV6_MY_SID_TABLE|ipv6address +; field = value +locator = locator_name ; the name of the locator that the SID belongs to action = behavior ; behaviors defined for the SID, default uN vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, default "default", only applicable to uDT4/uDT46/uDT6 actions dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions @@ -125,7 +144,7 @@ The current list of supported SRv6 behaviors allowed to be define in CONFIG_DB i ## 3.2 Bgpcfgd changes -To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_SID_TABLE** and compile the corresponding changes in FRR's configurations. +To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_LOCATOR_TABLE** and **SRV6_MY_SID_TABLE** and compile the corresponding changes in FRR's configurations. Following the naming convention of modules in bgpcfgd, we call this new module SRv6 Manager. The new SRv6 Manager are supposed to verify the validity of the configuration entries coming from the CONFIG_DB. If it gets an invalid configuration input, it should log the event in the syslog and not compile the configuration into FRR. @@ -134,17 +153,20 @@ If it gets an invalid configuration input, it should log the event in the syslog The simplified version of the YANG model is defined below. ``` module: sonic-srv6 - +--rw sonic-srv6 - +--rw SRV6_MY_SID_TABLE + +--rw sonic-srv6 + +--rw SRV6_MY_SID_TABLE_LIST* [locator_name] + +--rw locator_name string + +--rw block_len? uint8 + +--rw node_len? uint8 + +--rw func_len? uint8 + +--rw arg_len? uint8 + +--rw vrf? union +--rw SRV6_MY_SID_TABLE_LIST* [ip_address] - +--rw ip_address inet:ipv6-address - +--rw block_len? uint8 - +--rw node_len? uint8 - +--rw func_len? uint8 - +--rw arg_len? uint8 - +--rw action? enumeration - +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name - +--rw dscp_mode? enumeration + +--rw ip_address inet:ipv6-address + +--rw locator -> /srv6:sonic-srv6/SRV6_MY_SID_TABLE/SRV6_MY_SID_TABLE_LIST/locator_name + +--rw action? enumeration + +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name + +--rw dscp_mode? enumeration ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. From 41d0cf28c9b43fd03831067b5774131af17a57ec Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Sat, 21 Dec 2024 22:05:00 -0800 Subject: [PATCH 20/26] remove the _TABLE suffix of the table names --- doc/srv6/srv6_static_config_hld.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 1d1eef7c4b..e33e54967b 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -75,7 +75,7 @@ At the time of writing this document, FRR has been able to program the SRv6 rela However, there is still one gap preventing SONiC being utilized for SRv6 SDN deployment. Specifically, there is no mechamism in SONiC allowing SDN controllers or users to directly add configuration for SRv6 without involving BGP. -In this document, we define two new tables in CONFIG_DB, i.e. **SRV6_MY_LOCATOR_TABLE** and **SRV6_MY_SID_TABLE**, which serves as the configuration source of SRv6 in SONiC. +In this document, we define two new tables in CONFIG_DB, i.e. **SRV6_MY_LOCATORS** and **SRV6_MY_SIDS**, which serves as the configuration source of SRv6 in SONiC. Then, we design a new SRv6 Manager module in bgpcfgd to subscribe to the two tables and compile changes in CONFIG_DB to changes in the configurations of FRR (Note: the new SRv6 Manager relies on the new configuration CLI brought in by [FRR PR#16894](https://github.com/FRRouting/frr/pull/16894)). To verify the correctness of the aforementioned flow, we also define the corresponding YANG model specification. The workflow of the new mechanism is shown in the following diagram. @@ -86,7 +86,7 @@ The design details of each step is described in the following subsections. ## 3.1 New Table in ConfigDB -**SRV6_MY_LOCATOR_TABLE** +**SRV6_MY_LOCATORS** Description: New table to hold the locators configured to the node. @@ -96,7 +96,7 @@ Schema: ; New table ; holds SRv6 locators configured to the local node. -key = SRV6_MY_LOCATOR_TABLE|locator_name +key = SRV6_MY_LOCATORS|locator_name ; field = value block_len = blen ; bit length of block portion in address, default 32 node_len = nlen ; bit length of node ID portion in address, default 16 @@ -106,7 +106,7 @@ vrf = VRF_TABLE.key ; the VRF that the locator belongs to, default "def ``` -**SRV6_MY_SID_TABLE** +**SRV6_MY_SIDS** Description: New table to hold local SID definition and SID to behavior mapping. @@ -116,7 +116,7 @@ Schema: ; New table ; holds local SID to behavior mapping, allow 1:1 or n:1 mapping -key = SRV6_MY_SID_TABLE|ipv6address +key = SRV6_MY_SIDS|ipv6address ; field = value locator = locator_name ; the name of the locator that the SID belongs to action = behavior ; behaviors defined for the SID, default uN @@ -124,7 +124,7 @@ vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, def dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions For example: - "SRV6_MY_SID_TABLE" : { + "SRV6_MY_SIDS" : { "FCBB:BBBB:20::" : { "action": "uN" }, @@ -144,7 +144,7 @@ The current list of supported SRv6 behaviors allowed to be define in CONFIG_DB i ## 3.2 Bgpcfgd changes -To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_LOCATOR_TABLE** and **SRV6_MY_SID_TABLE** and compile the corresponding changes in FRR's configurations. +To enable automatic programming SRv6 configurations from CONFIG_DB to FRR, we need to add a new module in bgpcfgd to watch changes in **SRV6_MY_LOCATORS** and **SRV6_MY_SIDS** and compile the corresponding changes in FRR's configurations. Following the naming convention of modules in bgpcfgd, we call this new module SRv6 Manager. The new SRv6 Manager are supposed to verify the validity of the configuration entries coming from the CONFIG_DB. If it gets an invalid configuration input, it should log the event in the syslog and not compile the configuration into FRR. @@ -154,18 +154,18 @@ The simplified version of the YANG model is defined below. ``` module: sonic-srv6 +--rw sonic-srv6 - +--rw SRV6_MY_SID_TABLE_LIST* [locator_name] + +--rw SRV6_MY_LOCATORS_LIST* [locator_name] +--rw locator_name string +--rw block_len? uint8 +--rw node_len? uint8 +--rw func_len? uint8 +--rw arg_len? uint8 +--rw vrf? union - +--rw SRV6_MY_SID_TABLE_LIST* [ip_address] + +--rw SRV6_MY_SIDS_LIST* [ip_address] +--rw ip_address inet:ipv6-address - +--rw locator -> /srv6:sonic-srv6/SRV6_MY_SID_TABLE/SRV6_MY_SID_TABLE_LIST/locator_name + +--rw locator -> /srv6:sonic-srv6/SRV6_MY_SIDS/SRV6_MY_SIDS_LIST/locator_name +--rw action? enumeration - +--rw vrf? -> /vrf:sonic-vrf/VRF/VRF_LIST/name + +--rw vrf? union +--rw dscp_mode? enumeration ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. From 81cc67d13a9bf4f0121940a1c32b8bf443c5cdc3 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Sat, 21 Dec 2024 22:14:59 -0800 Subject: [PATCH 21/26] supplement the missing prefix attribute of the SRV6_MY_LOCATORS table --- doc/srv6/srv6_static_config_hld.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index e33e54967b..3e49759d0f 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -98,6 +98,7 @@ Schema: key = SRV6_MY_LOCATORS|locator_name ; field = value +prefix = locator_prefix ; ipv6 address that represents the locator, which is also the IPv6 prefix for all SIDs under the locator block_len = blen ; bit length of block portion in address, default 32 node_len = nlen ; bit length of node ID portion in address, default 16 func_len = flen ; bit length of function portion in address, default 16 From fb20b3506ec4aba66e308e47e80fb2a43e7c09d4 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 26 Dec 2024 12:00:45 -0800 Subject: [PATCH 22/26] Optimize the text --- doc/srv6/srv6_static_config_hld.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 3e49759d0f..51817631b1 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -115,7 +115,7 @@ Schema: ``` ; New table -; holds local SID to behavior mapping, allow 1:1 or n:1 mapping +; holds local SID to behavior mapping, the keys are full IPv6 addresses of the SIDs key = SRV6_MY_SIDS|ipv6address ; field = value @@ -135,7 +135,7 @@ For example: } ``` -Since SONiC and SAI do not have full support for every SRv6 behaviors, we plan to add supported SRv6 behaviors in the system gradually. +We plan to support the staic configurations of the SRv6 behaviors in the system gradually. The current list of supported SRv6 behaviors allowed to be define in CONFIG_DB is as follows: | Alias | SRv6 Behaviors | @@ -157,6 +157,7 @@ module: sonic-srv6 +--rw sonic-srv6 +--rw SRV6_MY_LOCATORS_LIST* [locator_name] +--rw locator_name string + +--rw prefix inet:ipv6-address +--rw block_len? uint8 +--rw node_len? uint8 +--rw func_len? uint8 From 3c5f54bab463079328f97755bf6478d3b3fd580f Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Thu, 2 Jan 2025 14:52:18 -0800 Subject: [PATCH 23/26] update the HLD to use VRF as part of the key for SRV6_MY_SIDS table --- doc/srv6/srv6_static_config_hld.md | 41 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 51817631b1..aebc481cb2 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -117,19 +117,19 @@ Schema: ; New table ; holds local SID to behavior mapping, the keys are full IPv6 addresses of the SIDs -key = SRV6_MY_SIDS|ipv6address +key = SRV6_MY_SIDS|vrf|ip_address ; field = value locator = locator_name ; the name of the locator that the SID belongs to action = behavior ; behaviors defined for the SID, default uN -vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, default "default", only applicable to uDT4/uDT46/uDT6 actions +decap_vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, default "default", only applicable to uDT4/uDT46/uDT6 actions dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions For example: "SRV6_MY_SIDS" : { - "FCBB:BBBB:20::" : { + "default|FCBB:BBBB:20::" : { "action": "uN" }, - "FCBB:BBBB:20:F1::" : { + "default|FCBB:BBBB:20:F1::" : { "action": "uDT46", } } @@ -154,21 +154,24 @@ If it gets an invalid configuration input, it should log the event in the syslog The simplified version of the YANG model is defined below. ``` module: sonic-srv6 - +--rw sonic-srv6 - +--rw SRV6_MY_LOCATORS_LIST* [locator_name] - +--rw locator_name string - +--rw prefix inet:ipv6-address - +--rw block_len? uint8 - +--rw node_len? uint8 - +--rw func_len? uint8 - +--rw arg_len? uint8 - +--rw vrf? union - +--rw SRV6_MY_SIDS_LIST* [ip_address] - +--rw ip_address inet:ipv6-address - +--rw locator -> /srv6:sonic-srv6/SRV6_MY_SIDS/SRV6_MY_SIDS_LIST/locator_name - +--rw action? enumeration - +--rw vrf? union - +--rw dscp_mode? enumeration + +--rw sonic-srv6 + +--rw SRV6_MY_LOCATORS + | +--rw SRV6_MY_LOCATORS_LIST* [locator_name] + | +--rw locator_name string + | +--rw prefix? inet:ipv6-address + | +--rw block_len? uint8 + | +--rw node_len? uint8 + | +--rw func_len? uint8 + | +--rw arg_len? uint8 + | +--rw vrf? union + +--rw SRV6_MY_SIDS + +--rw SRV6_MY_SIDS_LIST* [vrf ip_address] + +--rw vrf union + +--rw ip_address inet:ipv6-address + +--rw locator? -> /sonic-srv6/SRV6_MY_LOCATORS/SRV6_MY_LOCATORS_LIST/locator_name + +--rw action? enumeration + +--rw decap_vrf? union + +--rw dscp_mode? enumeration ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax. From 49a62fc8f7c7efa57d3521b6413ebe78d3c5896d Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Fri, 3 Jan 2025 10:15:36 -0800 Subject: [PATCH 24/26] fix typos --- doc/srv6/images/SRv6_bgpcfgd.png | Bin 36416 -> 35771 bytes doc/srv6/srv6_static_config_hld.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/srv6/images/SRv6_bgpcfgd.png b/doc/srv6/images/SRv6_bgpcfgd.png index 5c192bca433c7e87a65a5052d06b3864c4681715..e50954da24d3a1afe186500a8fd3938cbfe9b89c 100644 GIT binary patch literal 35771 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

fec9`yYdo^4cnVUd)qNtjrprgg{G zj(-%9LZ?jw8@H$11l6jlb!zRWhYibwpNV{v*z3#Q{#KNflu`M3FtG;&p|zLC>3Odl zBeO6SE%RdY@#TZtuoipP zy1~TaeULD`-(NXQF~*0|$V(R4(z#7dy(sMB7QH(a(KWMhn4yw89Hg_^*<{&~Q}$LY zC*!K)y9Q@xlJ=TA3rGi(m>}vPLCltjcwxYYuiD|}up2Bl$+4tAhuHNIH(rB6MMcG} zfKUI?$7vVMf5`tnAntZRl5TK=DqiKv^IM)xAqg3;UZI;wgMv1CGZ(#ASq0-Qo6fwX zjcN@>2Bl}To2cRIh`JPXwA`G(Y^`HizCXkFgqn}=nk+>$KLVwGvX zUqRLOq$GaOowO_trCeoBY%6aWN>NvGIqJi^_`M(rRoM~X-N}!3xFe)BEum0ZBmfCKnHeBmJ)Nf6}%Ry{FYwW;96n*4j2J*x0z`V~jDMFwESur|T+h!&#b%e4% zTmVkTBVO&s%JJC#41()1?wf=&jg7N4S8NlX>1Vmnma>VyY(%HNU0X8N9yH}16U(efZ6o{pmB-Rhe0 z(WLZgF20skB&cuxC%n=ht(WsB(9q>s2&P>=RyS5INM6VNWlh-~hHBR0raV_H$?G;z zUY7B`iYfRs3D7NGigjNW+z3 zR@D~2-oCd9E!1aA|NUy09-e0rs4To07?{GQey8!3z##+NNCJrgE_HP)A<2#Y?{`^E z!OPnyx`4i@C?;!f{C@K};@@crIO!=mPMvSF1g>+DqRP}8G;I8$Y^LwX>MXU~J)jV+ z$W|pK4)fcvkx>GxXSR4XNYA(_CW01?*4n>C$ys~#pcMN%UUa(H9xIqKg1Z{d!@Xjq zdf(4rtQeU^eX^?RGx?b@Uu4#>wjNTr(W(;ZYL{)x;MiaxKJ zD~ilg$+SWE4=0LFj&$&s1qF49Q9bEp={oJMG}|?<5xHv{PX6Gi_*ey?FvUr8C)%XHe&G%+p`t- z8s0nl?)1^FkTVJKZEan9uO~ULnVKv8hw#F1j5pHp{~U0CofdXV_48o@i0LlmKOXFD z@TOExMjx(l{_qcI$J6(=vSVttGxfGDT-=WQW}v(T_kACCx?SbZ)0+m+J-0|Qe>i^)YPj@^tzl~aMdUzCk#^tJuYn8W{^t=$na}+^ z0@*)AkvL^}_UC7(|37^u_ozv(Kkn24<w|i?i zx6f-_a`E-l@iMHxd!upp@YmZtvAhuLb5pyWHpZ*Kb1SRX8XPbWN`!1&nD{vWTm4 zG7sOm>vj@@ck6Qc7dDqiHVnvCbjpWpKJBbG3mJDzoOkO=zTtxG6)PRv6iS)LDm z4Bj=sqVRg28hm7AWZz9_Mt3~$)1c^Du)XA%+XgM76LtKrm`p4VNojNZGCMHOw`R$EvF ztw+kRwUoM*b{AsWtcQvw7y5IzOB0w2haIMnL+`EWR%(9CDZKlw5C$^B04sBI^RJ(R zw}WgSO`@b&AnK#f=|hyWBSoODj*jK=+8?XaZQFiWz!oiGE{rY3RGWIweUPEY&Cn7TU1wr1Y8zP^52+jgk(@zeT#J}4lb$8ATcr;N zYn+Gh+!${DUp7{U11i{_N}U7>0h*B9bq@_;6fZEl=L4a|T3qg}#_#z;=qAUe-xuS1 z4`_CK_lppT?@m9s{4~9%Q8OqhX~H7Gf@b<0o|TCYemSBGo&7TDB@VL+Yx6@xv7S|h zFEh%utSu~Bb=qwUU2JS@dNbrroo(&nlanh3QwzowXnejV#1}o_7QVCGKE*HDJ0qRg z(jwhkbnERkLBY%g8fk&1f_ZG6QBz2ELRW&od5d&g*Ea2Kod0Y$`Z^!|FHOHV&3nY- z#~yxhWbSdlMfv^9bGC?wiv#(&xw&ph#^J;Uf>V7K}- zj+nL`JWg;$I@Mk*IVSW|Q&a!fa;D>Ff+VZzgp<1z<>V@RWz&_bbfSxNq#RGrJ>a1K9!Pc&=jNus{_T% z<_qy!)4)=PBl_fqL~P5mv$L}fyEWlF1j`Y^Mdpw*-2{eo4Bps1>(9p7YPsOJ17@^? z+(*!Yz~NJCrgb-y5IMu=KLGw>Q&P;KmK}R0Y*@f$`X2 zje>HL2_|`6mE3CK24VN`cuR{Ubc6eR53{?k-q_}oCZjaxl#y>teT6I@vMw^NTE_LQL0a-XQY*?G;X?N3mtmfLc>Xlnm~ zkvzdrlG40Cls9TzEG5sSQ)$3(m6poSg5k5uO`AP^biMN!r3~u^~&9jhB~qW)`aW@NqOLl0c(@5BP&p z&@Bqrf&fHZLCjM;;*2Ylv~z#m>G4$aNnHL0$7{V9@uTO@X*$P9)C$>6_y|#4GxYcD z-UFdA)eCc9kyYlBDGl+(-;6-~l^DNp?zn~BUJ(d9aXi#XOUd3e!lxB20luGzNf)%A5g z0-Cyb<6&LGJqr^PW;Pa}b>x?E_cGVDndou%cT5y@EI!hF_C!&Fjd46BGd^KSJn75Jlbd+izRE3wlO#sVm5^3bJBV|)U8_5XutDh(h-sO6+rJz!SzxPro zN>z1xm4pUoo=lrtoavsHO&5@wf#hz{bxKzb3rbBWXao)xJI!SNpbzK+csjdGBBy%{ zmodlcbUaJk`1Pgf$^aR#t^L%Ca}gP);UrI7p1Lrm&d!bH+#HnsAbMJ|&(?wSMo)O3 zl`kI8uKrQL(Hc@1@`5a*Ok7CUi$N7U+sR`y6GHuVC-H{EUGK1HqQl4MXqCU|$vtY$ zwXDueuu%)6`(uBPWi(dmVsJ=EblddG%Hyr^jIX{*y+&%*Y8MnQFfcF(Om@FH z7bBCNwRkE)puAjd7zbV-28+y`m?5fdhID0#}(T zPrlBMjyMY=Bcn0#IGOZ|p?cKm$}Q+8R{IiU4zHUkKEx&`3sQ)&Qw4>J??3T?6vm!p z-{9d<&h5|0$XMznatT7uRtQ>qx35mGJlkAND{yw5i8EU&kIlDp2@*vP6C+(692|0v zcV8`8;`H4Y;NdaccTxgY>}c&+{2k9ge*Acb2QJL;OJK|!LpP(Bctdpul8k~|j*3M~ zbbV=G?)N#`y7$rcv_!C`KX;aGFDgRHU8>2pw2ngFPBm53C^cUL^!V!PYF}TZCnwFB z@BP`CZ{D}!#kjdAJ1^d@*_@xBZi~TCu4j;cv(f4kyJK7R_>qt!>U1h$kqbh)5ga^I zFCFgFeCcM8H%l$yJ zvhPYv8@KoA7CJ8epvF{owf#>Rj&Oa7{<9Hf;uc#aN~$<;Ix=@5Z}QQjDJKpX1_a;{+`-33NHzu&3s1$q4bmvEw`-x=~S6Z;(kG zRnk2DC>Zh%bFsBC+g4|5vQu@uE_YFERasnm*)odL-S;P_Tgr53>#1HFq3jszoL$@O^1#Yd zVJXZ^QPNnF!wC6k40AW$d3hwg>pEQXYG`VHF8>^5YG$^9H;YS51XbPq37;?yj5X}H zv5$<$D}h&Y?KyqTil1ZAm{bULJ&}ky>Jp4S?UMTLy33>uqO>abRXkSV zr#?&0G;+Rg^q8b>H}?H7G6)zG+A`la={4+7s0dcY1>O*UE8JPh1Q1d0igpXfv@MU6 z%XUHUW<)oLwKCibK)iY$3o6yET{z{b+ngOs-6uvPMGP5O%p3;i6dtqQY=6pP`UJ{O-RpLw`<-RSDUy3Q=5B1VPr?P1Yy0%4#tiEhnw7$Z9Ijtc z{Ap@AJUOEz6?A03z$>lnqjl0FI9;!D zt*B(Cz{W41)1gkrFAaa0K@qLOA7$;VNy`W;%w& zL}_S+T(EEUKeF#^F86{$UA<>d-4EoV1bb^X{A+h{Ji^?yVn2Jx?G~_^6EErmD8yYpJuU@LP|*>BDvlc`%69tb zu027D`W$B-h^7|+*Qlr<PG7*}*N8sJHZRK)MQXru4=GqPV_#KOb%P&?yonu=tZV4VsRbYTAH zEow6d@C+4o}8Q{BPzPVAd}t$l+Nfnb#hA&eTY!>0tg{Tnidu;`bHgrMLSvNC8wvS zXW4=fMovMoNDHMP=R;s6d?02>zkm5vaIkKT$8dqwMZ>CxV5={0jITx1B)QJeR`ovM z8Et5ICMfoREee$Nr9H~o@BHtk5!%Vo$#s;Pb;UF3vqf?0*Sz`0Fp&`)dNgi~Lz#W0f4Lr#y_<&1HXg`Pin?+!5Zf4m zHeCyP5J&)2_tky^)s!}NF0KmPD_#dwzt%b*CJ`u?{vpHR2kcatnVE|EF5{l~7L!ku zl$7+%ucb%2Oa3kj1x$evzx%MG!YO3x?2{>^AYNUju&*wwfGh9UWt-1y`j|QrYW`hNX_+J?k;C{Ttp{T`vHs{ z-#L-OX~nS}zIy@ri@A6$1AsdUKbC8mb_o=JeOuqn{0}epspj@Gof*w;+4*$O^=X#Q z`HGCI$Bef&kyn{BtJ?HkIK=1D)p8TXy=$HquS7qVWf(}r_WcG3*?87pX)CFY&w&wKlmw_PWXoEqdSKTXi*}b+m5{_4TQVJ z_SSomF1XEsV*RmLmN`UWo~rt;+u{>_%PU_;L7_4uHdS2Ay(9F{;c?}K(n{(xxjS)x z)k~#gS*+PPx(|W=_+4`|MS~Czkg9BPdrJc4^E)?6M`V4Lt8RZY{RM8D>i~ohqpS+K zIdMG58}}I|XvpXv+SpldUyq1|*eBJ(!`Zv#-8P>$aOkUgOnyA{@?pAiwhm_k-y<%W zep*Jx7$N7e=tt`8RMV`a+2-OiGC3U`9Z_v2RpPFWj(iIY25XUhARhFB3P#9DhRU+S z0ze)6W zJWg*MII3DvZVfK0GTXBB7p-xgPKgUMTE5ELRJ% zBC|^{1Vh%b>TLv-^zNi55H62?+o%BG7-u>XHny5Up;4jT&OE1^a4|Y2W|~yaS#DKN zP&>CjH({KnS*w&sXE1n_{7AhR~CYoOrQd_+*PI= z!{R3Ze8|Rd>Q>pCJbuhQdUApfK41cHLgg1#XB+pqIdkGgv^%{PyjJ6Hc`+_kiThrX z3K^m()?Qp(9MJ9Jr+Ea|mM1D<@-N^TDE${kn(zGt^XRpl;}Op&oy6XLG6KCrcU)Hd zpuC9^DI444mp|_y`ds-%+j{gSl0ZY@MTckK=CQyfO|9c~WB!jx`4F$M^KkB$(<@Jw zGKdxCsqSw-bb3=?W;Nc~1h1Hu(2{H|mK^F9@2MV_kT6>7UF&vSQc#el`92WH2cR{y zqnM%j_R(`?=S}-O>BrrTdClx?sO*ibm)w&SE_I>Y3%MoSF9*g$ zrUEnPxEC&I+E?jp`ZGItmf!HR+CITfIk+rkmc6uWE!}s_3%#apTjrqH*tev7VPBo8 z;^EBZ{4)ZLWf1c^v&39y0bB~WLrBA%>>%@q!PBcm`gq5$(v^D} zw^s33XLjp;drMz2xFkRCb>hjxhc^fB=KjL|8=knZ4ljzL>i9=ZA@noKdcso;Z!X2p znGD8!pVE`K+%BKL<>BS%*r#)qfiag8P%nBB+MF>RZ4paVa*4{>s+=)RO-&df%Rpyr zc5FPxDm(xFq ziGd#XCi_Z)in4}_$1sO^YqDKiWxL()FvW-p@Y<=Vck{#m9q(OAjA=J?R>)Ret?|L+ zI|HH#`E*Z8NKnvh#6Uc5d|kx955Mo5Tk+-0(dY6B0;1pQh)hvDF?9PV>e5%QUd0OE zX=mSD9LLbzMGt%uk2)WrOY9g0s0fIMeG6U7Cg|`(^mdz}*Q2={JOi!$UBgbY)h&-c zcOTU3i?PKB`LYn9vZ;pVyfO{;PZX&~@s3T2ZTXZAGRBJdyU1q*mG>`4(gF6;1li|W z>Ut#DwYS9WmWFEmlrWDtWpfSBVBDyY$_yFTejfK4iuj1boht~vqbr_aCspM4vF*i) z)fsZdYdKXsCVx?v;&rj&CpOk1r2Q;j@NX5WHX14k9nQYu5GMd=YB+hMYkJ)bLLAl* z?ZWkCtCS2yC(oLlWeKI^?Vn1Hg)uAR@pd+F*xl%ueojJ!4Db+$n}=r=%oTLd5O+4f zjgO>qxNp+sqsNk2J4Sg0cc?|eyH{5a;D=kl1tlLi;NIWU>z&?bV3G}TTDc-cH70{ zK$b$pQr~G6dCZTv>WntBYazkG*$GFgPt6o$S+I3VrV9&3Bg1+Q_Fwnc066($TG=_D zKW8?013FVbE{)e6LYTLAb}rCc9Dwc=Eu|BhHPe(Vj|Ix4|UGzg{-N7Q2~ z;$629i7&zj*Lhr01HU)X-f0wI&WR5UYUxd+yMl3r!J4&3zFLHoLhK-W5E+qO8}i89 zDS&PuE6^d>tQ95ktK-nt(Rt;H`wZ7+WKg$@;Evv*}&^fpf94G(J$pTj#(4*&@E-Md&r#BF^pT{fmbr>dl~GIsgM z-}dD8tD_M64k%VrP)+sO9tCB;ml||}5VLo{22MX<&WK0I^SO2~ePK*Ib7nL$%Ys9H zd=cJgt@R>r%JNvt8-OMA?bmYbv==#f*MMKXg#EG=?y}Lg9(37m%3C_Y?S;KZHymbO zB@sZ|Vc2~*PZ+M|aAd?kyGV%$A5=|cU^z!wkb0^-&_PM@iE?j5rm&zgVvRxAncYH` z+=VlY2|`-mqx?%lDF^Mjx4+tRWpKw&^wDsIZ8E$=B$j~g&koy{UFBnl)uYl4CQKEu1NDUlblsA5Y?Y>vG^B-b4E?06_S9?2{d*u;G=$e(1 zlIoxe4h{w=5&&Zhz+CR_;M;DYO-zwNKAdposyoAbueixyz)XmzSQuN5|KaX&!rg&muteZz>LpzGnROGn;s z;RGlYw-|mabY&Qxf#Aq%EcwCDteu)LEWR!(>bZ^B!6Fs)4vBDczcqup860CISeHgC z6q9rK?2cJR!tgcGWWM&pTGnV*5zE@z+KjK@jNZ+ic^*JZtCUWyxmJBu=;u@X@)D8W zu}9LuuD24Z#gFD#6)4Qk`UGl^OBU3wW-mv?=V&&9X%GwuMZjjeZ{~>%%1o_oW$i=| zl#v45OA27BU}C05wfgM~`zWb{2JO0-px8zQ;6;E&&0^EqN5$IHRF+HSY%PM5CCQs( z`Dmh4F}B_9hEz6mbaX)!bt@ffHcDi+M(rwKXdLF=$}%(uMj+$Hb40&8C_+p#N}tFG zuLAx@yTYa)nGLt}Jh#R!35w;XY2`cb@4Di$4Ae?cvmJNJtw-Ny-}l^H(rmF}D{5@# z5f|qw9ja9vu78VNQ$>v%sFpma?l+95E|*-XwhY6$Sy;%tZ$k#5HK!&E#u9ywS7zTX z`voFWZi8&GV=uxRjB>{>c=lbpcFk_(i=^mneY>x{ZedS)u~OltbUxFxIhQV78bh%b zQYiUycu{Q$EhQTCq@ast^^lWZeo6$&D{8zQ$ZQKgm!L1MgNCs&PZ1Z;iH+#ip@B=p zN{$u4pbvV^zMb6aylgOl?P_@e0A9R*H6n0_O_D#)tci8a?UN2CKDwg1k^II2Ox?e` zDAU)|Zc=eKUo9aqv0T5X%Dgw@FvF8NuU?~c4cECru zEx)@+w>ZOBPi`e|_IO;L&D^fupFC7_Gq&~9#d-)`=8C1_pDvJme95JcogWZ^>!n1q6oXmr*|?A3NiWEvNb>BB*Ws%;*s~{ z<7CN?$zF>vJDDit)Y{NV6>S>c4qB)40AwZ#F>fqO#ub0~{Q0wem57)a1HWo)+w>nM zJ1!QGrEr_J6Y`o-H9#0(nnoYZ~ws(C%O5Sbe09uN4fP2 zLkSNd(B+`SYMma=VpP}WU*SDcczt+X{G<#CLU1?y#p zj(pFqOk!1G^H>_w&<}{u%#%IFcZIcES36Rd`pgz8r4UY!Eab&VSV8dLt9z2|uuL0TzG;Z<>3Km@5q*Sw1(BGNR zkWOwt%y!e|f4&9TxRI9ei3K7a42ck2jcGd*)CdUuctu^yqjfgl%Ur)2Rx_1mNz7UM zu}djuA-gd5=BL%x1Pax1F@R;8CaH=LsfXTtJ2mHqs;R8J>~fV!Uzo?Sm+`ISpk?Xw zv*ZaK%(|ahxgwp_td+0E?0!0^F-aR(03eGvL~k5{$eTI6Lh0M|&Nq1fL^>HDj61 z7fQ*{oVSJzH)up%30;19^U?bk$tL;a5^9cI!zqj9D!a+X{-ANSi5th&xNxLzmWz)v z!?YTqLH>bMFoTLm9*1$br!{Erf&qrn3R|4tg_W$&B2kQ~3JKxp@)(oIR!*ln0|7=F76vg}U=32N{7x$7y4dS{=W zB@O{qXkDE|DCqEpoepc8hWl@K1ncf33RDqjq=x`Fi!3frpI+OFz1_(-rk6%{2!+o> z$d|i{Z?F_(6y7WuHLu;2ek1BW;HhZ8%MNlXPmu7rg^o9-N-bO$-n-^9o9p$39@85u zA1VZ|iVita;l?D8m_8*fM^udj!~zk;Ep`Ex*$Ze6+{s}1j%s`Qgy`Pbr5INU)nX04 zP%dTHOABQ!J3~1hV&XzVS_g=B`uG@N=fUtW?Q9tUlrLYBt}XhRS8Jvv)W~UFjgpZH zW$>H|lQO2mkkFXk{)uPh`AZSX*~S9h9j2UXw|&?Lyv!8)mNwaEBz?lsPw!mxz?xx-U-l*Eg?i$wj2< zJ&OiSZn`*YkTVp;_Z<7u4?C~@1jje3j{$JJlVuq9wmNgM;iac29&Dsba=xu&$J=)?x4M0->+N>(AEog`X@nIC)B>DIj7 zJrQwnTl+8(E6q+8@S+oFcZz5aO=-KE%hPd%K1+;`FX=i4_;gV8T{8<{dw|H5{cgdG z-_?HZ8sqxzeH?Rg7c%p$JW&yCZ|5~A=vjwlD?`Tn<)LCD&^kZ{rJ7zjeKfzEAg+5{ z3RqDNlZ*8ecbYh*}x!C9GATw&$QE`%72a|bTiD{tZ6iS?B=$;?u5sDVTcyFaQw93$m1e56i7+XP_sM<2j^z=pUdx#tZk1Q@bIC6a@(3`Bf4 z639o=B@rk}Xp0%5<{jS z=$!UE>4k8g`YzAMoGaH2{H3<9u-ZULVk;D6K398l0w7*gSTy)A81|enMJ!r%Z}b#% z@jCa$)2&s1=H3SbIF>Ktv(BD)(Dd5nCGt|Pype?p2iJ`S)32Zso^Cy}R%?TH%7ip> zUjgjO@q(6E44&!2l)^HNxtD>%fR*dsx_5zwH@!pLii)D>v|ilOClTAD)@Oab4xTF4 z*r{rr?MfamF$p4lhFyz(-kNN)gX*^eu@x1pnPsr_N!R75PkC!4lDIoQYt&HCb_~sk zZ&1ta&+@eyZWp6lB=HgWO#cXwH}S^r?W>kdZwby+-Hwlvk>m^vA+1}nT;UveO?D;p zTG7>Jc5Hf|O_9}El_;_pt0Y~s3iKYTPB&ioP@R^^IIIY`RHyGn8Y zSPP+836LZEm@HdLSNe)F>FSw6X4bZTSCX8HvS9WlgrbhyvX~kWg>dnhDHd^|f3;)% zf1ufXOm?m@(s)gTqqJ$tds%2kb1z-l9GLS+xh3|r3a!MgVHaSDU@X>%#MfzA&jE|R zfqD=v<~2zP87tu50!y%9v8= zdYug0U(eb?b7YucP&*R5sFFAfr9KH&!0cWLL@ zJ!X)9Yo60L=>+c)5iq-K>4E~)*~S+tf;vQRBD`W|yJ-EE$Nt*@h8{*D3EsB=eHIP@ zvO+A|d@eutdG622X92!n@KxfNqxZ;fgo7;s!YNvuMIY96E`@O_dC~gZ84Of}{o9uc zDA)S3^k|7g00tUExo?m`KE{qQf7U3VENs`+)y04b1RFPa4%!uW5-O9!=lq`e zox8gl;yws6K7L#XH0bm&Sbq>nf~dI`Xd&q3d`S84NnFevJOJC5aWDYuEcg=a2~Q(~ zJRC@5RBkT1+>#^#pW677!{1{7vwE<+Z%tQ|UDUb`{i3iFz{x)>PHBVOH zxpNy6BAh6pPu?8Ed%!qk>QvhK2IxSd&p=6`2fBx*Co~52#K9i`4hL4_#sEpkI6zv>YtxU)Xud*VXdP&J@ zm=hctD$6fSE>jIA(pDAkW~-hBZPF@`M?vfC;>ltiPTA+6S59aV@7h>w)MUK-* zKctIPVF1t%bM_dlRp;&l@t(f4vynj;J*@A~RbRGXb5LVD!>?qj`miVOVsh80IxoG* zlkUzy^BI1AL8~EyP~A44e3XPcM}}#>+9=As0(rs09Uj%%8P8L{RZ>A~I!K@)1?SNb zW6*0!p63JYhq)2@Vo+@HbD~1>34LlZh0*Yw=F1m0ieBF)ZVK;9K8PTGlrc(8lOS}8 z3w66yv%}IQmvrpyqV^}NU`QN6 ze^x>e=IFb{K#hFRcpqh-3AcjvXPv$S3;I0kUFMw!Dx|z@dTwT2BG4dcn;#kI?tYCz zj!^q7Yo|#TYv|wu)CjK~NcEtPG7~U|V5rz}`8`b7+W4lgnV*B6rXn$aR$EMhbn?}v zlRN*VA6cA#sqPn``!K32=Hmp@k}3IyW0j-DLscauC9Z3xsBM4XCO-vqAN$*qvMH#F zukUwGJ&F;bX&2`5>1>0~Wdl#nN6sQZAnHUrBjLK@ASyLBN&-hbuYy>EZ|a5HNCY4N zCe{@~17pTS;wGz=J3P6S+X${(R1Ec_&7_b{P+lR-OfOS`Y4`8n9_k8P22d~#SeC== zJ_se6y@|H)1>M#4uT>* z_{JP1`pz^1#n~)QH-TaY0AY{?V*qX0O@jCVWb5G$eSARtx&m}uLKU?rSN^BXC;Fc-L(>a1-o#pm0Ij=6d4?`WBSR5$v?$#)ANs6knK@Ro`M zPE%9!C4%0?&hGx80xO8WfN0JaWFUf0V@?YG=6YBgbt2v@pZ^B@MDJ#OU0of(1n|8o zAh`Z4q!>s`-1*J7y(yG&P`08B7pD#RT>jhVg(Gm1-7{}CHV^>YfVVwB9R%Ko!B+mx zWhe{S(f9eXVkBrl7H}2_sq(DQ%C{M>(dDXm2;McR#vg$Oo@2v6EI)XKsJq_Kru%_k zovf@Za5ymcR-~^AXmoH`Gj(40eV3R=Et>*Hkc2%#>W`chL7=Dv@jts1nn{I;}|C+cZnAd$4-0lIl3 zz1E;Qr{>b@rHA6|RI8*dFnTMWm=$si4Cgyo-=yR>`H z7m?Os`#-Nd0d<5U5k~lr<|+X0Xb>;fgyTm$xSMse&tR~qvaIagAUQO59dq-~H`O^f zIFH`tdI^bm6eve?SAOf&yf5etm zQ&%5!!xda4cp_f`nj{p3;1#qCP)hjy?Mp_0w5tR`$n#4?Y<1HdP(vSM!w7i!2Tt-T z5JaCTJomexSWg038pyWjkZe4qsg|#M6Xk*%>+gSnISWY~o-e5SZ9$^hTKQPGld#Wp zo}hAiSLgC+V=`K(h|{qa{kw)^5D*qd4rEHmLSvPW)AkKGD$kvT27>-(RiguLvfp}o zdRkiplj4U!b*A{{`dc~zXznzI>(6z~=Fdk@Sd_Z~G%3pO+mRp$S5Ad=P`4(+<LQW} zQrzc~5WmmnY4Y$P+&S1TYgR5CbOH0oncGX?T_6(^$wCM!DsVLWv!quk0wDy7->z2$ zqm_@1P%gHDx*5dV{Ia9>fKZh8% zw}LqT^8>nTWe`N-dFaPUNyaa ze7_Udmf^YJkjccMUW@lcT>=&EJ3o+?e!dhl@}*7R6JF)<=5Dg=5s%S^DIk(V1!2 z4rdr&>-6TxE~%c?WwG;`xy1NAZG11;t;_>!6afyRfVMPTTl632`Thy159Gp*6}7F| zdZVi5v_1u^CvQcMVIVu+3f_6#D&-H1H;%)mLkzsG3i&h~sjC~=#l%E2VQZ`nc}(x% z&lI{x&=&D;z0a(-_HR^ZHoZ5D2~aj}_v>SGEZl)Qz+En>T%7ib`lW#F;&JAvpmhWM~n{b}9ei67GbQ25a+1+_N zSf|sXIK*tet!Im_ZBcEuc7O{bI4mnE(c24u{er=b1$@nq?5;$&dgNyO<&7@AjS>B7 zvsv5yR(G*2TQ3Z`K_vFdkNw-zew6sJwSkKN)!umrHJyG7KZuKqfVwK`$^sUOQdI;5 z6kMf9b&)1r0YOR#A`*}iSlbE+N{4_bNSAIX3B?rwX^M0RBqF^ek>1IBzM#AQ_U`-F zy)*B;GnX018S*9Hr=D}3Q$A1kUQMce=`!>@a?5oVe}t>Ifhs)gmax>5zSoH~DUpy+ zLbF_hM&Xt_DD@XGl9Agha39WKe8xE}3(U(KhpB5z)a8L27K)rRXa0sHz9B3%6j4f3 z#hBscP9u9^foRfcAyedvIZ6jtg-UrBnXx!1iJP@w?PVP~{P&1#c9@O9)RvV?dNwcq!U!Y)jv968)E&8Y&`+W~bT{6(tguJ6~}Az>qtZ90Gh> zge|ziRt!4Z3!U^V+U7IEYVGWhIHMP{`~~xF_4U$^s3yt3*^NJjuW-owG8B5>DUYTi zEwy+b>9>Xu8=I05Mq|*~+KOi%NVn2p4B!>VnZruVmiY<@3}8!p z-hLYHm7gK@6|D^Al-kiNEBfw>YG5Njcn`3`23W1~a$hSjDl;s9>u=OEOC)1fv!3JD zo+L2s|JlPBlv5pvvC?H!w$vuXro?D}9>ul#hP>8B_C=;Y*JW?y2Op;?*hGP5_=>5gAj}N8Z-b<4%CuM=E2_kF?b+sh~EAP8$<0Quv*`Om+l9r=FaSK=8rb}^=%d5Os`WEeK@mF&GF zYP|U=(@je}-%Ut_0E&Fgb>s&|`LrFj$G2Ym9=YeV*fo$U6@88K6Q1)5zSBmO=}!a8 z!7J@K#OJ}EBXP{L;Tmp;8M%jc)SGGn89%xltb-yzk!;4J-|ZMwCn*OM&DDDNM% zzJnKjVDZV9gPj8z(y)pfvPX57^1oZ+&X+axkdb}F5s5yb)S@j*MwTQx9- z7TD!1EOl}UOI*`{9?(dyNAXH=$-Y7J0B?JCh|j%;gc}C$bgC?kBs4TULy# zAkW5Q*Lq;aR_F>AzRTzwWCH8A7LjyavIg(vbU8QM;_E;r|7p%J2~;*Kxi$~at!d_T zo$&1ll-f?zRq1|)$b@rHF7`rswEnxDN4#opUbiL3@;C9pr=RNu1iS6K!lNCt6!f0r zR_ko^EM~`y$XO9;m(| zzsjR=;w-C=5Z0>Z7KF9xe+czJ@1IRnL2XO@?>5kp28N=&z4}G-!~fDvlaldE)mQ%Q zgPneQ|NenH%2|$W*LSkyYp*++CyTCXANS~G{o=LO8-ekie~@9IwDK{8IhNU>IP<{r z#yGY-&TOH2-a#q5W8BhfXbWSN%A{mHh9xwb3iUAv+RsgCOzR&*LX6y2E~~lk4oUbM zX!P+R|C>GqiQyNS9k}qbYj5?aayJ+8!1wh(46^O7_B`oGwdbUVqE;%we6(gRX3n{( zKczDJLU6NsmafB>2IC7Xy+pUfMg%J^>rb6g2q|W-+vY}RsHEH z$7@F1>SsIVR6>JvGqu=o*@9Mso5OziWhu$dj`@k-d(n%)U*AY%4qIEwwynXSl^RJR zAke)DD}`M=mW$Q%jgM+h%sEQUqo5i!yb?#8YE|;F9P?f!6GB#pb9VZ%%*cc8LRQTV zKYzs}E0+$SFS&&Utk1v=x?{p==JwEI+81P47AhosQY~^UeV0fVPtV5V7TUL$8tE}% z9t7X|4)RcOpVJwq7iSr@icgYP6GD7?8$|1$ctKs-uK_>rioB;8FZ}d&p#h9|Ss>`( zYutX!{^wI2C@tyazRuf%fpJJYLD)3RXrQ5QLeZSD1N>DE&s}tTsN! zr+*xvm6FVsI8t25%F0Eh({t7Q`W2+5nW$6-CDC^BgmiLui0|d)nLn8y&0msKC_~cX zx{nr9>!M0Y?@W~(hF_*bFUxJLT(E4PuF?($pP zpWhRrZ28KsZ83`J4X&dLHf>bAou0C@40|7g;(Ue$?VUEmvVi09S#6VC%@U)LEiI83 zt))*17I-5GV1o?FwRH2Y&2Q3P?BC_r_=Yw$U>OGlvh^G=tx1`oEp3dtX5X30?tbRH za9D@scsC7rDNCIY1;CA6t8)JF_1Mv-W^74^IO&GIwi}Sau*8AO+_}95#g1;N#k;O8 zbeI=w3B%$shs7gu4JBibo*k9UoUCQe)Qs#3@Y)7)QepdU%@%A-Y&CP_MQDg zC+qWo*2Oy+Od1A49Dh&MUWSPc=St4nG<%nXm%r}phgA~wQ8z0)2ROj3!8@^9yBAFh zMNKUAfr+bzD|3K?QAL`UA5Gr1H(#TWeyiU3#$QFFXXq~9?6qXh*GyW7lBj3f-HRme zp(4t-ZQ+8kKqKIKl@wPF##n9Y8=KM-;UO2;aQkUb_blm}?zSv-Jg&0mI&QxK(^|pe zOI!WLPA}Umu-|8r0d~TtA%h}eICYLf@$YdyT$rqe&eB{BBa;}uv^>jI z{`QlBFMgA%bJ+ByueZo^%M~fk*CJkamwE_khj`j%KAP#agzepQtVvdXhOm57_UNsb z#Ya0NMAXY~&IKY{yLJ55^wz{2@BZbvpm+!$LUrt^Z!*PxQ!b}@_UQdi$N+j_x8(}9 z^duP-_rlW=>A)nL@5YcZS1r{p-M`}4V|bxF{64>)n-z;s*5@iHdx__f^$Pxkg1;bR zCg+)(Q8xg)FVei#nKpI`)Z%jM4b>-ak3TrLQFqf{g;TV zrZ>~4mxFQY^wx;ot5Fwy)RHZah9xXcRS8$14VNM?-j-Z6)gL}Z%S6YjtxY%z)#50{A|xCVlbTQeEU2?4aR@7(A>hpwYA(0fO+#!Q!X;J9kLOt~zsXv* zIqDTx*b9UZo}Lh5>Nlel_KLg5bnwV+s>y(2b(h4>Uui*mx&0aw%R&A_iT0ZzPo7-{ zhyZYZvTCp8Gr#4YG&j=Rh!aZzd|O`+85>$M-DwSj7~ju59g3ixaBK6_(E1?eR64^W zVJ;3jaNk+tTl0^y=9cXC1c}JxU-qqC8&UFcstCx}wp$E&Pu5mc=r94zW z6l6N6$L_^#FA#y0CXCD_4kr^TNpxeZzP>zEDP*OqBeKG?zuKgvqNDsq(R%-gC4cpf z^ELnCV!|3#)lzc1UFZ|7Wx^R<rsnrDTeE)wJ@BIgP*w=y0Y`;&$vM)Y z2WURI1x0Hh2UC0M+pow7F0_0KS4Jf_2V+2})h~-k?2i}`lUHw%I&L^3`7X43)H0|Z4 zW68_w2Z-;_z5i~1no8()i0~YbLg#4yi?ypQw?yyYTW(_>%qX6p&&K@ABme&z#Q$*) z{_k7t=UnUS>pQZ|Tl7Bme(w!{^FeZ$ohGE)DPZXh(h%$&9ku69gUZK9aZ@ec!|P}! zF>&#(h_JNvB51q}I&?5xBN;(HXzXe6gZhEhm_cAtf%}$Ri0<3`hGVb9fNKdCkBnK_ zZ3A549!kzB2w1Jxt{Zn)Y==bMC#*uN^P&p0rswCE?rcMN((+x&tRtFV?a|TBu22Eh z+A_#t+_!&!C=*hD+@GBoy^z7KCztR+X>FljR$SJQV8YAC7wM^)9BQnibs(?53&PDa zH63Rb2f~bhc)@qbG~PF?%rbBB-l3t)(IDVj)jlzli0b9P4*Wu`QJ2xnQQMwbA`TH` z2&C*ZZND_}eTK*w{Zz(_!?GiWA`x&Rk>!mxuvvucbKAwx&pm@Y?x?x@WhPld;tw-& z=?;YM#pz+wed3Iuw4BSKc5i+fnnNf3BBfj5(;528fBh|5@RpG8-m+7qXWu8=gV=z) zc1;(-apJ7t^^!+FrLdeZn=lNs4GIpnJ@HGdTo>`~PtNAbK2<|e_fo_$<1zplYeM5i zuk!r(I(%Eyd)TPp%i1`N$=@v8&Fy!MlQuKjqOImfJG(s7a*;tPBb%yC-4EJXv!(Y) z3d`4Yqq+}Mqkt3P^O`u0K^e}=MQI3|$C&o{UMTfZ_{3eKyFs^IH_Jsj>c$r)*iw;KrHJN+c!}fAcX;v2DNo`G;B_wAC~}`>+Os6;AoPwuru*w*uI+T zYMlf{pRv}X#xJ{Vx-jeYjIYcjLPA0^N$Cce1D@7%J0~2RQ98wPs;x#7@f0^6?Mw=D zZNC1UH)I-o^um5&zPZQIeA+%^QTJ@543r!WMGU?>^IDsHpdmU}%xo;Y{u*>4?C&l- z-Ehq}4K#7|lp?;rz7FS!hOST_>dVtBa$}wql-&ZXSXamF7uy(vjkX?hK&{JHH4Z)# z9Q$FoKf%dH_O-UkaU0E+{X~_%o}+sCNvxah&{Sa^MK@zI#h}XS_?Xv? zVUw1j&Qi-88|0(qB-Ix5EAkaw*3cYAI%#V*-G9JhQ|~J-TRDenr0h&r4VB{d(k(@E zOH&Q_MOvS->VXS#erDMGe)Qt~M{%XlaRBYqb2Gl@gobUa2&<3_?J@s9A= zSUM`lXSLwrRoI4)drU+ja_ZR%Us7%crQrZGK$e~oBSMjuy12=tt?@_w)ycLTVk;GJZ_??&4XDv_I zX2-%D*<#l8JhO*OC)`4k-yK>t_IZX}sEB7Xhg@8D_8blZAu^EnEDJoOp<<+)3E-w_N(+7Dp?< ze}%ZsKHvt;r{c@|%)R(c7aUi!uyI7Ff#LP!|H&zJo2-4Yx~j5@P#@Y4KhkqgKhvNV zQ)M+d@-Ydj#)+X5JM+dg`jaGvqbMMNlu2r7rc}< zDx*p`h!nQ~a0a`*{{43s7k#kUCSJ5zHuQ@*mNHj|`0s+)=aoyC1RgbpcWo0b=h*r3 zojwYlT?NX!=OwhEn7sE#o8ltl?rCC)pvZj{6``M6PnO4-D?$ovrnGz+m1u%tSZ$!7&$cU=?2- z98+4O2#0K^@kt*X1J{1pLPS+ZukZLsyyW76tHt=b)tuf_GR2-Xw4xR8PUlwSe2the zNs{8Dn4(63FCP8=JdW1QPk3Gk4mf?SGmm;vt$bMa0@-T+m79C%Y{Ihn#GCB0$Ayf$ zA+0IV*YH?k_Ix3$seb0}qF4o$V!U-=S0()vt_AHDvek>Y%%QT9{e`}WoF_e2vPU@o z4u?GRSMGt(5U>A z!G}jP8lKZnrx-p{9>X_tw5|MZr-zgZtCo>vgm^ubLIu^z&~0Xx=u5wGZ2xo0bvi|m&+O|=7p9$YqR$kz*tVdDV|`EU?>{7|;W$4x|}4R~|!JL9SlANtJus37XB zm29D|iD*S0?H=N-g-(_C&zU+O?U`FK>M2g`2uGqs5K_d=^l!(3n3%y9g1Ubqyjq9H zH2je4tZ}2|$>Yn{J7gDY6aq`aWY%+I>Toq%LKoQfInRaV85--ZS5HQfR3AKefLGOq zNwJJ|dZK$|w~&xfWaQK3vVM^Imm0-1);eBFWEcdPHpU<7Y0Qf`FjhXQA=CAKOuI-I zph)+gKR;MND#frBVj&GmEUJEpaCy?20m{K9v(YzlPI>iYi~8T;r~~N{nal-<;nLxH zp#}7=up;Voy)&P$Omx|Qc-1RrV#Sf3%NCY3ae3@M%KyvK@b`Y}TSe5{ntd`@H={Zj z#iz(nTpyzPLgcp{`$G2V>6T8Lhu(_(vwWY@Rz@wZJ0udkX44<@oNCkvtg>49&BB|N z6ElYgDBRDchBgw-7LF*L@>l1c|K@zG&(J*I6ehh)Em2>jOX1+xu9xDiqfsw+Z~bB3 z<2vzC3fG6z(?OnT9*PMG(a~R=byl+fV1IoaeM}l*9E5tO>l3{fUFUmPwb(Ph-Gi3p z<G_8gMx2jU<@at9xJ+}$AWb|ArrbWI%7g6UjNDPlf#4C?@=V9gYLEr+BSUonK z{7C#H{}Bi><-*$#_;}~*vgHOPj{0}Dw_Y3)m8!rH_zzgOZ?8Drc$1md`Em8tVn zqkIuIJW1y~3`1Z2s?Csb=0Ep$nAav9o<&yA`=`ulBxZ{IgOQZws&@CB6b%gBuI<@N zE7EY&&oiz=ba`hCdNFJK&a0H@Bcg-a*cFbpPf^^?*do!4Qjnz7(p2v+SYIYGu~N91 zngra$LzwKe`J?9q|NNjprv+b~OA{b>(!o>0wFGxx-rfUlt;Z0v97TfX(Du*$HOxw+ zFAr?jvflPXQy`j3=6X`!?+ESjTJPP1eLw_AGOK;uy?hyAHMDm34~Ns6 z_`z`PDzL*&bY7)jZycVcYiFIw8kH$jKndGJV}0)YPh8LW$E(s(Z(6tX8SXQIlDknm zPQmSWZc)Ms-mXBVg@c0W{4>|SH}?QVdbRR?rcq8^INjb5ax=>xHX}$;pDNa0}_XZEzPKQPU{-1U$r`AjqsPV4z(2frvTqoUD(*<>>zU~WDL_Hl`U9-TS;vuhNl#4#PCHO7ntfb` z3yu$ZdU}8d+dn!~Nhm}^7N2byJbAoBh94~W*4=Yi8FV2tqMN$po4)shy)Ip^p%l76 z4nghqkZgvBhiQ$#dJ;)f6L0L5BbYQ&ynw<51GfG27r*Yb6oq58MHoHH>r-s3s3utm zxIgxHAP}$BN192<%F8c}B!#?hXt)q}EYCfQrTDVgw(Z-&#MwyMKY4OMvHVD_22fQG z>{=)7%J|pu*}v+5f>5Xn26z}gs=ZallMz-tp zmbN$dHP#^YyKNC#oa4p-G!3pg zTw;d_IPvV<%UWUj;qYB-S7h(L+n0XEt0f{fXkh4M(bW>OY~Ws52kC-$klcfwmuMWc z*d!i!X_sh3fWpVZb}nim8sFu@p61*NDZF>eZVEh8rNu=j*9OsxY$Zi%w>d4*NTu+{ zcOVZ+7@1H%yefFw5zgfEiP%lKJk~v<+D0PA_2x-+G4xQ{sB?8-hJA_`&ro*9py40g zn~m=&m@7BJtjLCGK9%k3TCOUwm+EWoLAwbHb@@}|#~$nb=lB1tg_Kwm&$Qu_dIWZH zYxX=ZNfFhKwn=Os(ZQzv*d|kJzs}PY!VXlws^NN|i{H_<^C#)3orE2jLjBM!R|qGu zJiQOq-LJG@s1e6d!d>1VD|W*`?8HGq1JNNMn=yI})dSaa<|MN`f= zp9<>UEQ{+-9J-V!Q={!iFwy4wT@ZVeM||@q0jO5*@t>rY1FRjcA%<@QET*lkt(KN+ zi*+H(W#z1s*S5K(lJxHK_?6L|>f(<(?2`Z4FS9MdP8TiL@;bvI!Tm`LK*3g zLu?gkDk=nJ<;G-Xab=&wl(Qp3U+!v3F=9{LDWaQ`bZH?}fBHcP1F@hWAa&M6_v6W{ z`Ll*MYh>Cc)D1ooLR-JZBsw#j}j1b4e46grYv zBhs>@XcwpcYT5zTP%VAi-)_|VBq62s0E*>g%|MAQ)(Gsn+556AAVpLf!y1dnOL6z? z;Nia8Gs;dL^5J-b-)HW8&K=twYjLNw`#yk+2pQ{ehb(dNgby{;mw1~kGOKeC`heSy zVe_$sUH%K{_XGe`L|GdRMaWKvJqwVX5;KW)C_^y>L^qJ1hWo zwyq^&-1?;tx1OWV44|dPBjo%0`==@<^E6Zyrx)Q+N&)bZSd$n)fNK+bv|W|nC&$^cr0K5*aDe}*dN(vIb{+tH5z&^#E3y(jDq=71x z)1d|=JP6$_q&Fd!A>ySJke|{!0+;OsODk;wyaXJ1M@rhvqFl`3C<#-by}p#y#du_# zib27~T+VE3y^=0l@(^lvV+`3elQP)ZBjLkia*dp?Vz~)B6lti5Mv9O}=2qRxQtg_& zh?As`@m97_-xw-G7FRFNh65nzCm}=zpVe=^sTZSAb?k|j6}t6ABOu^hh@PFcQj|=_H$Cdq;kBi%{SBq}(B3?PRcSJ|G_1LYcTP3aW zmC2XXv-Ha~x>OLim&OFRy|8%*!((dJDsN$-KV;Wm?>zh2QZWGo`E1c~DLXOx+E^Qd ze6v<_Qf-%`zJI$@KiCfwZgz?Wd8b9nYBURYdXEM;T$;Ld)VBI>Z&f*AzG5N~U=6i} z0OF~?c8l?@hS7x8>fRxZ5 zLg6;DDV(oWSBSA1e0~P`kBIK^5O3O;^;h*%Q~91OA?$LLeNg|1;P!ZP4W88U^0=MP zKPXqndnM>|VdLg*fl-|_JMH8s7i2hYvA>GKngfX?OtX>pI?iP;vWPBQ!g9PW$^B!J zYpfT#AU8>0znzeCu~4Nd_Xwr1Ralt@9jVQA%_k_ zS7(qb?_Y2$y-K@()!H?7KKM6Vg-(hq zs65@)yBlPZLN~5W?GVdJa}x&A z-cf9lf=cvqra@+CPW@1D7t}kI93kFAIh7le8cW&OQGRm}H$TfZ5mi^m^AN<^RZ5Pv za7puLo*UV8C9g%wdsUc7~7uEW6lW&6ig%*;2d}nN0wdDM}%{ zthZGSg}n^+2fa*k79UN%7Ck!@w1g`U5O~`ZWIb-q6$WP!@Ej;e!I4F zVVa|rAXbG-GXR9CwDh%h3$Z;HpPo(^tqQ>4e~O?h$D+hc$d80jq6pOB=~D|6lYBeb z(3hGZxn(OP-|0k(^=?$9oE_b$N};oS6>IQ1zXOPM0YASY76vnrc)HVt|4e+=Ee!HY zn2>XMa8MC6X%)}^*<>EB)OvC_?@6C0FbP&{Th@R=ys^TQ;#`E9KwxN;}0v z&#^(xf}PbR`O+zZnzO}t4YXwMkZvHm{bKr%>Tq>`38-i3-{pZ$WZa5YZ!oj_@HC>N$31oqEU~Ir zB10Vk(X*-q83*CC!#3J#yfE$G)Kz5=s4Gv^b#;~dg8iH`Uty+a)Te91XBa`vZ@`3u zib`qiS>3FFKJ(zusy_JnfWefT>1T3MLV|+cGC=J8QelB{w01xD=CFV*I|{XVT`>L; za0q;rD~ru~KMQ_5@K+!F-bQ;XQfEr^ zj!&u%rlrNw-(}R=yA$?wI=bD7(R!$HN94TfwKpERc&Fl!HP@15;aW3@4T8C!mm2*V z2NT{!OuMgwb_$&(W8ptXm1oLzg`{bLLqpj!y!M=v`x?d+_YGNzZjP z#p(}^c#{M+ry^|?MTME$thu}&5I8l%&p}UDq2>#HN0s@7&=RwuCA&q-`MoTMMNq=V zIb;(!)P#K3{QI{#p14@vIy_mu90V(Hgm;1v7U7kbt)4OE)aR`T9BVC3cRgcH?y?Cp zEYwtD_7&R6qQfFR3am=gChPe{N+)ln*DAZZRzOsfW zm91@c>0?!u1G_M0a5$%2u-|e{);o4{#5y9jp_J}-RnK`X{KwQyS!A~Jimuf5u*YOn zGT}mujYJjDPplrnoq^fy2c&lid}mW^v%C&EA>m3yD_XzS!WDIYR#rP2f)!Go#rfYjsm)T+0^e3pv||B z7s3Kp<~?X(?|UDGLIRO22gGG7J6n%A!Kq{al~>jm^{3pVGXBWm7feAHE>smtqv|uP zMLe+9EhYMeC;KV7`kNnZeXZRwjz%}=SIA>&-fxq_ z8Y(N})cNdbxfgK7B3!IKYqzS|9=LJ+`ny&AViw7;2Uk3^FesTnG2l3Iz#znOiu)bQ z2D34R0L-2F7T9q>dTxg|tR7j^-2yufU!u?(?Evc8~av94zkCEpOUO=GpIL~#5Iwp|k0pwEFGd@w$fVCMq!4<4t@TT|m z0+7?X7chTXcuoB!r)+(FeZkKoWRb3(2BEkbX08S`swXmL5_0E9D@2ue3?#|r2g)8S3qtI(O&x(UB3_S`zUKUW6UwfxbJ(62ft@e#qlnXUw|M8PvY^z=MZ!b z{1Lqq2OT_wsh^;M2b#@uaS{tvCm zGEEPH0{SE#K9G0RTp4qJf6dr+Zm&REek=Q)+VF%AI>mK+teXZY5ma0TUhMLSiAUeE z2C*=B0ulqt%}MT9YvBZR@U>Z8$8n*$e;5Cp>dUs}Pm1E>ER+0s8$a?tEZe9V*$K8~ zF^(1}*;DAHM7~~V{FXu{eC3(2#yhG$&YyCr<%zofcXl-g`YU+Xr%Cy5EGppe$wDzYQs-qLY!Lo z=|My20ow(7K=Z!?{I3oE*AM>pF8u#19?a`@RM@?_tQw4s2GKo&gP*HZD(#P25+_1P zSO*SvolR0VoDUeQh0iB|Soiti>37~i*W|B57?1tnFu6~Pb}vl?!g_xh4whRS=vL3X zAY2-HIAqT2VotAI37jXfsbN7-o#LucY%Njy~hLGwXN?z!J!Y?JRcYt|Ae6l_x*X;Ztd8x zrFJhFyk?60BxBWzsc`4Mfrk_!FqEwzY?`_tb|U%aX_wc!3~3*lIWY8IgQG~;M1zg* z_68nmj_4ZagHWkJG8!V-_GfFNJsm1;BI108o^>k}Ndt_1wixOc@KAf0O;XS3Lv*pe zW5UNdhXEhpAr3rLJL5fgJ=Zve8Q}BdrG`)Jr}*hmf?qk{^+cfEc>oTqa}R=jLg*Vj z)cy`z5nHVAHqZus$Y118nirfzQK1(Z=3Y#)BoA{wnIc@M4DFl)@UO$ z+kl~={TDfAgbgc?S_YH}%M7NvZ0&Q(^giOEB zqmK*UHZ9sebaAzn?>C!DBc(tTyA`R9f00lOG)WaCN5r4r2^@Y%#(lPBHdv|Ycs%o8 z?cmJYS|3itXkk{ju~BGjZ@kcWqR7M}hEJg(#U+=cQ6XEVm`Q!#x<|+SNHx3KCRIJ1 zXK_mgT+>8{pvX5qZ*Dc{9Bs@*FKU%pPq{B`?++F7C|FFTb;^Cn;$hOx)i}LC9HeN2 z2Uq5EU8WAW>zy+r4f))UM!0yE7;^u`6c!PFZ1#?AlvyovmJexo>>}n9Z6pP?;-V|^ zNk)5r29hFt))HS!3w;E))_E&J!tHVC_(q7#k9DM0DLqUZei_N74QP|14P4P~mY(OUe&7&n-<&ZCjV^;p8cQ47i&D4#>TUPwzh_+r(?UcDYRb zsP>g%c-U;3Z`9>Nq)YYj?o_N-uJP%7m#iV~=KjjDk_Ca6|a-((P{dzOk}$qf{+ID=q3hIQSV?y zAK!v~a-JjP@VzhjZF~QFX2bWGwm#A=tyG=G@>YZg8qIwWc%ARI(%sr~Ihy!NF_5IX zPsuHfVdc`xak8Wtn&ByZa(cX|2nol>bmtQ%O{Td6F9^^#J0o(>g1djvhk<`Cn=?-< z9UE}L`K~#n)0At5%?O&ZP}F1Wvju?=?hcQ$j&`qEHX)Tx#d7UW{wQ&uym&I>Kb|qL zbkZ^IR+t=hq8xn-( z`-P8tl0;-A3XsU#XGvso_W$qzw+o!-{ZZ-d9BB7uuPYY^BAPStxsT-T+>e{D(S3C7 zvINzm&}qZq-P2JtH)|JzsfMdghuRl_8~^S@-?ZJh{X)zM&{qja9~hspRv z+M_Z_iGcw>T3YT5{=U(_hdIjhxyg{ecyU3Em&q2gA6OD_tYlMGUHXrlTt#Z|;R=y) zhQgl5c=|1O+b*8w=;@^SFSBvC9^N+TA6V(hip?|*Ch|c zFE|iHJZJ7_)2d!i7vRn+G_=h4J+@9&aZH%SoND;LBL;B!L-M4gdf7C}Z?!FkSC?bh z=G<0VEG&#o#cL3!L|lc>=ox%Q3%U%=*I!5qx+hg%Rj3I_y1@iR-{`NXJT#l`7uO~D z_#Y!Lu!}aA>skLVcKCl1@hzGB$(rTi;Y)>u+rbvu0wV?bl1IZu`(77c$~l8zA=uTY zo3f%)9cWTiZ5(p={UZ@$>{x_u)3oi6w*LTweHtf%|@FNB^+_UMd4Ae81*65Lefm;>>>>AMr@D5ic>y2o7{M zH0nvvy|*{_q4@lL)@WZd&9=EE8=DTdX@h|`rZSg3{2QWI zU1Hn7G&n!mu7T-Rj?>3#%pYn2PU4+~%7h^X7{J)m#lamb@ zV}(wZ-Q#%erf4}3*@{Al;+Y~Iyjla73dM?i`@);+Ho{Vp1+1|B4kMaBeeGiiUn3peDi_**CXkxlmNaKMw3BL3FE9kGqtgCt-i{r5fq@`BZ<=66Hxhg_L4jG zA|(Ja!y4MsuVoM!T;O$#(CMGod`3y+VRvW*kF9J-CHD}KsM`GsP9jY~ky1~3s)p}E zbJiW2wUwp2qdYU&A-^tex8DvM5BYB=Jd9Jz`!(vuWlMReUxJnaS{hPQMYurROEEFo z;VnE@Z5;A7#N;J;Pea!(M~K9F%Ciz*+8+Fo_Kuc=sxg(}W04T%8b--~CuMg0t$L&$ z4fILKh^{hdSp(4nU85CbvrGAV_$HA3+7UNX=>FCh!?2suHJvFfYXBzw8%v`k;FO?x z%_Vre%s%`$iHt?;S=Dsxg<9vT@`pvAF#vD!3#8_Z{K$=-cdKEtP$umT!BZk13kEHt z)(u3#e_W`hx_9R>IPxFVVBKPR{Z{?bRZiY39#y86NRyc;k$-oVuVh6@-g52t3jb7cf`mMBx;5$&smz`bcTG7qmq(3Lb z69`VImoygu96^3{YDshVg!AG5Ytow?`?3dI_61(HW0I|pu>4NLOoqGXXqX^Hh?BX%5xS@kTxkp)9`w1vB z+?RE?CBymqfWHv2)}a0)J=<}$N=c30Ti^k~z_3FQwR~IlZ3Bg6I0rGwOp9(MM;(QS zP1!yM!6*)sbX-EH)rv(%$;B?YO8?6p#{rfSDX=HxP;oB!51p(|g>NfqKS}tttel@+ zR(Uu|K<504L(+dAo*9_x-{gaBm57ATa0LB-M?iRUpZwN?t7i(*?$|E&qnPdISip7v zN%#ppvNSWPn){1!&I_5_TZC`y6|0+c2|3_J1 zuR9YRI*Yx$yhiOVUc9)$2?^i*BUpUHJ<~FTM;aR&r62=BQb<(<@;+5MBqDyEi6BNn zl*jt;M`Hi=BQ8=*ERSiR=bUOM=Q+=0708^ht_I7q7J5(kM{;@LeWu35I~)a>2!4eIUS21+3(L%{_lO(%yl-V z;~zok4cVF2tdpC%JI@8gb#^$Lv!>p!+flkn#E)(JiT<0#%glsx+k zh=0EYpuflT-##N6=8#j6JC&87C==b^W~&5SyvWk(TM*R}^Na|)RPVCEYhD9I>$0}8 zQBM=+dvLrLmNUmaUAzYgSm5k3cm2l3z~QuaKv~>jx;iULj?J~`&^8{(ZmOS2?$ypP z_Gj~?MhLBsAE7!Bd#1Kt!mzXHWvu+v@_e8Tb%H5@V27dQwy56_r+$(+Ds%W*z;4&i zZpp3)jrCN;n}`pKbNQJP-Ok~@k?OWcpWE3da&vxL&I2wLkp45 zlA@xbp7|T|moHx$89k=DSvDFgfXL{}$ijnGp4|WK1fZ~#7RT@OJoe7r<&hGZ{ztVL zeT)6sYBRFk?7X~8hLDGS^0m`*hd?cg-_+4jIhISE=kDEl8uqM%wHhs|8-bjL?cd2D z8q)trwrHM~Lcb+$ zi_z~@G0GYmW2G;X`0tTl@IuEv@3H!x@|kBAHuNi@0@LE2%WfWjv=RKs3aA}LtW|B~ z8Ih8cPjYZV<&SnA;1y6owLYttOA}PHAK|TY;9M)6Y6@!6{q}W@7Alwc=L?QcTWNkR zFK1;1ursr;IE^FpeoY%f8VnT)SSke2gs8)LenUGuE~Z6X0)m!d9MM)pP=Bsghv+vn z+sI`3VjG4tQNE|#fVjFsCdxv=XXOLD#3UYaE| z$Yq`tt%j1%{(Ff3lDD_F<7S&S1tn$ZxO3h9_ELCQ*fefi1oWx-@!Ijx0jJ7SA6p@a zar}C-DLxkZFDQgk?vHC6K8@wSCBsU-vogYHs{5?I1~tFCK4tBViBlUB;^IS>d!H1i z7DLKj>W|TV@AC6Acd+H?5;{K9sC495q*pdZB0kbVh^e<_qJ2`MHSRS=L8UfD&(qDu ztH<1UIXHf5u9_wpXDdcWM&^@jRxHItM~~#a@QfLw_%u5=H&*1kR6>L`v75qRrqGIi ziI3AsI>~rbDrRB9cqC6Gft`nkaZy=nDY z)Y~&hztMn;KJI>URKUHjUZl!$<-$g^#bBk==Hg<;C&ox1TKara%`Uc?d&)O3I;vi# zPDMu6JYzjIH8o@H1T4-i7@78|W3Ej+BqU^VU6ldE$O8!XW0Oiw)zw*F2EVyQu@&L`MmoI5)dXD*dZ<6H^y;1u0d-g^ zDIWYN>MGHBbYOSET;WhIp4xf-x?0b4bACPtr$1HtX39NEAKa1xKT+O<1zW=iGXo#{ zq=Lxr8c5z8I%)HC1tjHUjDSSjo3>5(xc!{t9S++E(iPTfQ_z%oYAc8;4+vewcb@(A zCb?`y9*fbN9d}@d($31tdg$5$ZqQPH_N^Kt3XiHSQcKow3No@TV`)YXhsm#=*fQg0 z&d$S+V$$wi;TogJ|DuRt^&zFWmkC^w_Snw`l5Lzk>zd`Z%^LCHB?8Fx!8FR7-24(4 ziHaGh>-&NK+`-O=tu$7M4$Mcneokv$ot@7p)&wqJ2Ha@yi`i<|)yi8>g{GTBUqCs1 zCP2rUJyys}hL+oJZizr)=GLW2DI~1wc|oCfNWwtm@75@28Hv4%cJFi^60d6A8izk& zOgan1CIK=>5cK;W)%fkbqRkw?r+T4wmdWVIk*+R!vXaOP-it=lXOkimw_7)f{l$Z* zs%#g!LvJe)laP#%q6J!-NM>)acJd)UL?L-Om_mOfi25vdpp}31E)lqek$0)bBQ5k1 z%LUizGO9&`0?iA^CB;^ZUt6MG1NFhQ;*}-+C11D74`rdB-wP@*vHGfA59*yfu5vDW zB1`h}2)CEK9eHKRn=$gL5_fIl4nCEjA>R<&DH&!fR#?xx-CO&;JUW5oD#`e0?xJKx zCkJ1L9Xc)|ZkbGZCI*&yr)|}&EwsUIJYQAg936n4vRP=v|gD z0oP0A<2{WX)^T=I4y_#X4@UuY8i9iHCPl-*@~s@krVPd&4vdbczL!m|S9N78!RX-; zcWNXpi$oi@qkBj9<>CZG46AQD7)Au;o~K{2)6nTjDIQ>Q@NqPhQRbA`TqaRv3Js(Z*#Ax&1R}M-tmeZ)P`=To zS~U;5W_OU-oWEnlVJ--Q*N8VAUT3tyysK|DEngNe?m5e#D?}cqMZ*9IR6QzxcGGMy z@8>IQDt4J$4nd7&W%t$0b#%TRFv_LNwI$p)PdUbQE#elU1tV-)!YvRb5t`ADe8q z;Q4Bf93B0XhOy<(Tp_8Q7Z4CIBWakZ6G_rTvF}=Gl1grN#OsuQNf2 z)Dd}p4vv@mTMHmFL_QVP3i@@7su@2n*P}wF3xl}W$fXEVg zrXej9z%#A-3|=B%SBciIj<`28HZ@VZZgq+J;72+o*^_rp!5;p#k>*#e?;eY;k&)5M zm$L29XTngiS3BP=GQkDC&NLtOneMo`N2oJmXobV_7;|e)$Kc+8Mih!0le3}}@4=UB zV~S<#`gevMv0Ml?rWSh3%51Q@mG?ysGEu4hWkew*;}wT?OZ{asbKH`f?MqL;Ao$`s zDugx{qM5e{4DG8VR2TGF?Q{Z+k8dEVL(6ka20q z_zm6YilAFTv5re!X&G4P9l0o`(U~){JSN7;$+@p;8qcOTq=AmHHr*Vu@h<85NX4VB z>;C@!vIJZ0GuC|e%kMd%bSD{sSH;b-rv{mA3;?*UQL?uBbbm4zSe;VffqgYKatc z)wR!rYjKHlO<+dsXY`fe7$wiF@Ykqs8k-b}W#YZk;=IDnY_Iy=(RoFkHzQJ} zbb7e!nbkX%{>=0)VNg`Y2l-a{{(x zjcRsO9NpW7$*v@EP%f~Y`4I}pkeRqgHt^l~&g;=%w$Wczzt?v-kEydc+qO|TRUSaW zV{ovgtv5efX0vh8W_hSkyd8oBBzCm$Kr-T;DSv2EU^$ad`)0DgGi@uG^D|G7F%r5q z?j7NkD*+LQhI|>Xa9JBGi_}8Tj+}E`a5@`*^4HJ0j+mFD%ivkS?OeOKXaWcY;5Rku z&^$@OMbr1&&wbC=?l(&`1yc5O_*zG9B`?j(6K{WF3huFmEQY}Z2+q%;mFvz=q#~~L zoX%5q`wl@Z?;^$e0p7g6ihZ~+4M-94Q6LfVjKRbx(*!0)TBreX0Tf5_UGxP~S9qkND35C8=Hi+OkO_UF571lA z7kMVXgswE`S`U`mCh!;T=I|%UE#Yj8mDr`mQ%NEz4*vBmZ$5kxGTGbQ+%)(;Aoytr z_n9H72dK9L%GTQYPI|#hI`*nw`u7*|@eE5u~<7^#c;gUK+AgmU>dYKfuefzeos6Q?`$`=D0|NC0w z*R?Cqe(-V&aDp86y=MRpQl_rhdP{X*MEr%j+0->xDD_jS-0DPFvBG4)C~&{ z=W}QrI`2B5y>)9S2A=)}HMRmXF##37<9_+UYDI^-0Y4X4pBHZAXFT&I+bO;=H)wbm zFn?`jW##vbGn<+%0CG)1yo%h@NplkOh1(g~{-}G-)(Nra^k-s~p=kvu<$yEcOWT?=v#C*g+?L)`h7&3*A z>`pb9S!9ZD7|a}H2WBRvpeQ_1KaY!^n*i@)EeSB?`N;-DMsVr zb<;DU;W51d;Vu%f7FyJGb$v}>(e1EM*V94|+(d?}6~WC1jgL1mWo=%mODYjZ%v7x9 z+`TT%=H8a<)G3**$mf3SLQywmK9$3t#WIu*?0Tw)&}74Oxaa*T9sX{GVqsy))~eBT zBf~S@K+=Y++WzW)sU(xHTJ^18PeWt;UD0A=R(3IMvTLRx;%AwFc?t3NH_HQm82bDE z<`Bji%L~ss17&_a<@4U6Ko4cof|HziKh;t7Hk} zt|ICH`Z1Yph_xqvnQ5OcZ;dLnFh9J_%Q+VamC=}nP@`>GLeNP4!(J*+;zh65qX&54@@Q&kgl^gfm)Z|RL_`ou+?&1C3HY;?|5Bqo zYTqzAzEzT|b?L4dZXlVeEy?8NV781X(y0FH{ha{=!OuG~m*)Lg&S|e-eC?o#GCarE zHFCLYqSfJ&cG;M(MC8KJU>PYoqY16piBHs(LVbC1W!*`p0sF z4bT^&qYLfo9~XqNJBTR|y<}w?TQ~@@``o*^$m^WQQ@_Zy=p}B<2N_oTLy|lAf5`Lq zMnjdvp;Dd>${$-d|hH^kaEpR&gKoL?o(AIBKL@OTXs1>2-8CgntZt8zVoEsvR*nG~Tf z+aIe<**meyC22T8tlQ@&1=^en%$tGAiP#&!CJHgr-o(;&c&Mb#ZI(K3HIHY^;n(8( z)?7rssJJJ_B0E-zAJf#{zQ10+gv=P-sz{YfCXwmim~J5@ngs&PygUo1U7egqFWuky zXBbd1&k5QIIZ4+Y3JyBBql*V#dr7S`u(-6;uRhL2Y9s@&C1Gh_UtgLJJ07e$et!%= z0?@>^oD{+%-w@deUT@S*LeHyqkZ;YTRgr)F_KEr zWa71(Pslv%GHo@vY)!ZCaE^<4&?Cy>{1&Y=Hg`#RClJ??3xVc!VECajMNQ?zcZOJ=84hoUN5j{MXv!rR}7 zsZII0&3C@sZYkDz@zzUvt5&CX_}w{aGGd?n%L7%Vf-FTd(RK&(b!BU4m7Q5>C7^!u z$3!0gtjQ~)`ukOdY`{sExT5SW%2Qsrt#rGSS1~Ud=F+vA{;b&Z&n}_HKo5pjqOb4u zU?N9FS=o1ZWZ%{VFOr=WnJbq&0957Mnw%7Nfu!5PD%NG{JKppN*CGK=vwcElih(h4 z!-eG)bE#fFx2;=QPaXErdW)rZ8BGe|p)YAvRr}X?7o-(qmijN=q+`L>cf; zdwUr4Au*Kw(-~M(q&0ikg??>6<%xZ>+I0Dj`&zluLRzufMO+VngP?WKT2SsO;2yqu zf=mJ^GG_%5q`r#qXv_2~23ab1%1-oY>;1$w4GUMIxUF+hvL^Me%m%6QJW+TR&Hlj9uMIkBA+x$jW?n)0YCLO|w8rHL6X>cK%rp zWY+$zt-3(%E(Zq(Krv6-%-gKXDnU3aB&=#R1NV7si)R7`mTUf55hjy9h0|Qpab@l& zZVpe9pGU^V77GX`JhO8Dym_Z^Fh-6kw31DGppR9fd|J`!tQo~9&foY&MwA9*= zJg`H@R!1c6P>vMy&=0x^6T)h?0-cOVAzp+TW3F*ZsZ*b3~huaN@ zuYBX;%*d~ZW;MGfgA1Hu!wwo6irZ{#Y-X&7M!U`29{87IEAzLm^`^@i#)_f+(|uZ0mM*wC)>vEj zZLpRF!Z$SEBbD0d z_pZwbu3*b%A|Oq?)35qQ zMpSA4BOhhaldY748v?mGNsN!|9FP#R+qqxuOGj0;XL+KN7BE9JWteo%F%010;bmuK zeIGUw>#gRhaDb_~$FX591v9ZfHo%9jW3H$%!>93WUhcv)dQAf~OUc@s8M7%Vz$1@4 zz#8~!?{RQkx47}^Nkj#RWcNryS8bX9q$wm}=0F+=Rq_h-X^$1%`5}mq&=O36srRs0 zJEe8)?G;y_H39MF6PjnDVrGm0qMv`@$M?BSSrj7%#&U{g$MvP;iK-oiO~t|>O$Q>` zjVR5Xr}DJNFR^}Sk4c>k+f>@*Se{MEc)L22q9~{7H?D03!7m^OUI9P$p2XK6^bW#Apoo&bnICTzL()09dz{6&FV@ltp4Kh4b zFy%YVPge=P!kjfa$x_LJ4I1$|A@OfW5)T3b@4}DJ+hE|KK&Yh3--8N{bG27FaSkUu z34RP4rGP@#QHnMaQQvU^5}~Q60b$%Lt&*u;o~Xo+Avf~jVNzkDPBfuH_R10h&a}fy z#6xK2u8cNOP?lQqW=4WqW_aXZ>%D-PF76D>bT{Ht6vse~!CHtH_Eu2bdqDSl_=w8I zx9J8V!FU?YrWa%hhyu?m$@;0*m!&cC`zNikYV;&)xZesXgWm6k`Bh ze*5INpLISnWKZhAL*M)%pTp{>QO`gD#15zmY6~}0<-ymJA-7y7!wKt-qP0AHsr@^fEb|I4veE)cq;xxAUB=J2BWa##g4%OsCq1iJxSJKecO+wye6D4 zHTK~nxO$i1s|Q*q$hW^yVZ91b)6fVQ4wy|QUzUJ=zK_v{6$+j`qxHVgiKxmH0}S(Y zd0ywOdDKJcC{ssPIOMAMY8n*( zS>2b22NS#F9xs5#*X%mLe)le1$OHENN`LSbKF-}rlLjRlHnFFgJ*G}hP6h^zkD5dh ztbR>=P1`aBj29G;Dr^#CNpmy(cv$FV9Gc-8+f5!RAd{|GV`PwR6pirx=B(?O##L6j zZf;22z2PSP=$7x>$pavw>GUD>4NA|POBgnhv(@^qUwK)0GjNft>3->lYr;l)LW49* z2~81NXtvMZmD7+3`+(vlB_QR3PO;q+M-RyRyStzFc3^|DhOMnU5Jo(o+Is;E=lqWB z);7NFQkO0i0}7|Mqp%?Ub_DR&tN?FNX0%&UENl5gU@;%>c%S|o*Yj5S%KVPMCKi@f zE7k-znI_WHZ{5f6XpgVJEPnwK`i6Y+D>db$Yxk^#SDBk8@M6Ws9(gIks;eP#aOB(= zb}LSis&p$LfNjzai7Bq6GQAq+`;uP@9UFwq`?}Sp%{432!pugBSxinG4gH4i&y%kQ zD1+t70P2O<$#TjG4epprT9v`-ylxvV%)`vgJZc*|`AZYeYZpbef~-<&?>w=!CpQBI z1p0IvxA+i=+hA&HIb#&Emt4r7G$j8OJ5%~1TUWad$!b(YgfBtudfTRj>=jGNWjXte zy+cs~f!=OrmTXG00&I`7V&^MXKc|lXdVX76T%2u-p0O~2>w3b~sKT=JQH?QueD zlvi7y%%UoXz7*@X5C>-hTbSxZe>dYOZ0+cXRvC>;8@(iZ^jKjnoHW$zoMlnOteCkh z?iy38g8(O|F87ZL_bukxpE*bY57yFjQQI?G87~Q{%-GiaoB=Q$cI^djXbUO^_v?f^ zhm5l$9D5eTKNwJXwCTz>H8xiAbyhxjs8_tJ(#kWriVc8=0Ahaw?}+}9{^PG|ZQN@q z8F)yRw?8$!^tCQz5S7L@Ab$*Y(PGN#l>i?)t?Is7%@4nGK~z+fzoYrB`=dX8q2 zR`Sipt5(gavTfaw*$d43+n*T-bJR*!^P8xM zh6ca0Lpv*QM@-Qvf97<1+}hRA=2X0HQ@eiK$x zQ&S5pQR($QdjU#*)YR@CFQ1+YEO$_neYJO{1+Y-1*WS4vg}FW>(^Bt-|;sJ8oVi>mw|fc;D1+xMPgGm zQR(`;ZZ{vSTv$&(F8+CqB{)X+PyM}|2?!xyv8g{6VGscf40m0S?Y}u6$;;x4nN}E* zox(PHRkFvJ^JjPEt=^clkn9{H1#<&~M_SS5PD+$Txl#B&#g|AzT5sfRUp-Jc`I6vJ zk)0HWzOs6ak}KqHE@Q7s`xDZTcaynJLxvs-iowK~SgD~nI>p16X@+QY+%ntwZCXf4}wU>A_4fIunq z&MKSNH_#QyZt9)C~&Pxngv2tKtS zvy2)!{4n(a0#+la0@~RrwD$-lip0bhh9qEEWh-(Le7#fBrD~2jkrFN(-6(#k7SQ9}IXDqZ2jyfcRFNiDH39fl8EHr|`ELXGl|Hg%yny zM8kDY1B_d<)kXs7{XxKLgm%MpH!`URcd!cINCHU-)Ifk1jE{UMr7NK+l-VwSNuuDb&Yb>53^z`tZY>mzEb|+o-{Nz zUitohnVv$g>Z!>-V`OMqSy>eVwTQ||?k(Fftk45Z-dCXPMH7I)lz}WzK5hpWyQz!- zwuW&Z$Yc<%pE%x(-yvAx$LSmm%GS%QD}dbcwwEO~l8!Yl`AAYAvn-r==uGTndo;Lf zoI3cbFcf(=%31|&YiO(DSPE}$63+0os09IB)7}@Y1;Gs8FqCgQWO$Jm4Bd!FWYWK?zV>A<=M%zNf z=>UL6j13~YH}+gwuNzXV<;cznui<5ur?al5BI`q^xgJ}{jqwPPfl63k?vubceSj8P z6U84^MfR{V?J3l=S{Bi@`R}_v*v$FnnjNgE+M`lgfgWQoC%*808w(vR0>ag^V6Tvj zM}Zy{%dv8WeyV32pbE5&2)cXVkp?8WI1RduN4>@&sC<%&Mxg^S!V|Q+1nt{lQ0fyv z5Bg0dd(Tl$io8psYUGdW;J&peW+c(C<3?+f4Kl_;YFuFXR;{__Z(i)<0P|w^D=V;? z#WfDHl;cTxwpqA(y8P%E7ho%Hi`_thMeEEkE0=`K2MY~@jzB3IDBVTa?cctM^vXaS z;jTMuHp6;6d7wV(1B^nJf`hvpB(gs zsSpH}OiBCR2TJvhQK0P9x|_s2JLQ( zV{5B@J<@+Dq&oVffOw6*vpg^&&HZj~VMLMt!9|_MR8`xpG`mP*Cu4>QPw{ z9;oueTN8W^kYB98lAzM9xDJHnx)__9re^i!HiSFd{(y8$ifF&&1572?iZ?v7Ln8|- zA>HrNpix^ESu|z-ZQ%~1xMaf!L;6z5U&UHY@+_J3OX4nNIJLs!r!&{V1ppyeJdFFq z<+@GyWifaFlmWsC+Auvt?PEZ2=3S+)SUuP19q80&(svlE#!MVUCE&c!oqSsQIuXB ze$B4%J42PLI7u27;JeL2Lwo0{Q@xf z74T|CQ!c$p{;ExAN1RX%Xmq5&+1?Dp3l_3FsOnQ6VpSP$H1pNYn#zHlg3KWt8YZ$+ zTW$=Xz@Ca71Z0w{)12F;wy_*7UQ`cz7%bf2j#`;|f8?_!eu2*_pdCc43%nQT#)526 zWe|-LCoR3&%Dn&FgpxVBQT}=z{fOZ}8OuNo$$av{El4%g)!}^nX-nGN9XwACoJv5c z%3hpRwjsd+409mUajLZNQ^?>V7D){zjRfPUsj1n*TR{KbtZ_5wepyGmXTY+m1Ary6 z3NhAe$oW~hI!5zv)C7GmRaJa;US{EDajE*Kh&`>6KvzX~z;yw^0)3%dSJcRaMTX#g zKFe0r#d@W`;%2itdcRB|5Y6o;5v2EYCjmHu3AgFOMT;s9OOO+)2Wt7LRQPj-ZX2*P zf+i0MZ|D04TM8Yem6iN}W>61+2=-8Mt9YD34onMTBM_@`*NApkgv&KjfK};FXCvao z$vP2RriE*NL0xQ$#$sFSjQ0&E$b(B{=$=;8VN3QXr7z!`fv6TN+W^jD5KxVafh zQbE1W=*5c%fM@zLAiA+sEIY*liqM5CC(0$`!y86#j--0lHU&|Kt4)%=8;M4XkJgg` z2Zfh*T0%5ki_qUC5zZ7@V0~3h$ce)b6jD=EB_MX&Q^aVsQ6VwLo>@Hc%K~+KF2@Nz zR3E4@ggFxc4XlB~Ie)tGd~T*!=I`cb?z>r9HL)lvG+_!ocQD0odV?&0yKzm(w>()9 zL$5Hfr?KwsZ@smElx+%xz~)XnpM^X8oJ{0vaM7CpCPb}{fr}t~r$F*wJ|@Fl^;eqB z$;q)mR;qAU!SYNc3I`fyK=l3T;N7~h8Hg|k2_Iz{GX|Q6%^d1FJ3HZKVqD0hUa#rz ziZtO~ASaWaJm6j`72$9TZ0#!yc+T7Z@+~SZxbM{>X9@HoCnqOwFAcO1^ZY{6LXTy3 zvj0?M=4AmWJME!Fh#n$>06UrnlMy$s7X9f4tTF|7djoS0R+4rmY(7tpBWw?MU*5-n z;_V6$e|NaX3wLaPHJ&eeFyT+ahL4BWtjG<|_WkYh3kp2}+ZLdGJAOacDL&8o3aN1B zn?<0Ta%vp$rM#SJ4h{MuW?ujnRt{SDw@AR@rvl&scd7Sl(gIZWW5yb8E$4)wVS2tH zV6-vtTR-+Mj?s7afMA=*%0dNK{0Br@>&ow4hdf%F-HIRdiN>E5hh?m!d;jBL_#3_4kZ*OI!WZYZRHnYM^Qn-oh;m0QilRVbBzjKAZA@h|RwtagQ-co=F<$LuH`3D)8EUof|r! z<@YLp5O`_Evs{6cd(P(`&Hj@;=xphU+HW z-xfZWf(G(TrQGtqhqGDoOgf2?vTr0R-ns~`X|{aLnI2eD>y8W@G2d zP4l@xGajfyZ+rW$0Ld_G=)}H?fesP^ikrhjVi)bMZRa#Fm{btw zYlJjZcE^v8p!P0BI4Y1gB^HWh2_A9_V5}v(ZF&Zp=NxLS1?tvfdY60ts zIBv2)s^*Vm*Cdw!NZu(4aLXG%oRu=DU+Xu8fJT)1l}^a{0Z^+w+Wp8dktLRKSz|9a z!u2-63C`afnuF2HLwbSh8BvcTWY@d-5VL5dikXo<+5zw0l~!chpbb`W4TJt!)8o!3 zkRm)z;9KX(UU2Py{CJx+#$nk0DVW8|Rww{N_?cb_?4*RDTW``#s)#%?`!e=Y3zeBc z0^jORmIR7|in{vpJWifMx;#E5ubyX#rr_C5lXQ@!BSnK{XJBOC`{&OWNCYNCNsmCD zs?47mA1W-xNXA!{Oxf>WHfrN1ZRKP0SZx8-olawbTsA(=l_w-5td81Oz`$bF8~mlA zK@7wI8o7c^_%wW-heIBF@LD;iiZ@7F#A*JEByhV%Kxv)hWGYj-wr9=w#8 z-oM55*dY1F(qb5-d>cl2Ira^GB-`bc0eP0nk(gT+XWE1f2$;l~VXu5YQ{8qXi z*cTE9FPVW(e|gq$Mn*=vqBO^awl_mq+MM*it8}x{Qc~{%1B)+ttb9~wH6*@w=MK;v zLBUR~?bzkn-!vRil^RZBP)9=cLyUs`6a^v>$6Tq#7OS8&k+m<24m zr>Dn$4{)1GA{)n3*rn+S}$yhc5E`5eZM=&h@cCK9D0!Q(+-TB%!m5A_xt7z3dCZ_32wL zo#8q;67BYcj%H?3Ir0Cb>3O;#lD`A7f#_wpD?AGeLCJi)s8$w8_{zV0uC)T1>tc`Z z>fK?d0Mm4J$-=2)Q_o@aPl9zTf)lJedA%e}R$re24@J{xwOY1fiNzRG_(-1Hku&V8 zrXoAv|0XS64xah9r&$dIbr3Mi*qE5FTmYN3$y9+~&5^X#Lqu~xH1~&S|E@C#jq z9sNTfwZ-gg{x8+<^eTNd3FEV{U*aWM0E9pu8_9-%#BU zbUQ4KTnFt%_LIMU{hFLijI1s%FL&CUjh=mJhOE3l`^^{MGQGYk*L z$*Wrl3D-B}=Rn`yK+GyRIeEF`dZHN`6z{J$@ORQ`9yoJ*CJsR^Cr7B3jvRt>EfV;s z;}=kE)O!t^KT6!brle;rH?)+QGzDjj`Evyhz~_GB5qC9^#(fUTBi5t-JDs2n zFdn$AKZxS$TM_T5Tz);+dyoad37qJ`mpknWJpb~?@0Y5=EY9aBX2OwK zjtC@-DYyz&js}gz z>)HyN0Kc^c;JEu--$2v{y<3jpUD7T5A-O+$(~bxA3gB5PvBdWmxA#Ft2k(9XWj_}b zW3NI`|HtL5ze5@+Dk%Z&WhS!A4$PZ7u(W>ues~M0MzOH6{+L0BoIREc{(d>4a^Sut zva$>ucX}YWmYSOvp(-i+(LcA0RCzxPjx=n{%%yT!KY#v&U-%P)Am?|>)qe;1UeEG% zmZh2}hGX4C3!1;3NKkSXJlH2j)n4;hB3-~+Xo%waOjoq{HGUE&ONKL8O*0BglC#9) z;3kAC9iR)JeE3@O$CCtBy2ssqZUzawXsL@kUKSTR&SR$wi)D`hL&N#$+pGjp2mK@#5$I$UOhj(5Rs*B!J}KOhL930hCf zKi96iK(~x~SIZ66R`Ej!wU4k}v}w7hRoM5r301kN6)mrV+-9Y?C$t$%aM-nWEaR#w zh{`vvxPFkjT9m(Mmt;xiHZ{gZv3IVDXLRFmM9Y$`oO`M~M zGLGZU1owmVj+n_XT_|dm=O%{MH28(AewRF6F&wW-O2+MvrXSU89?0^{E@ zX=IIKi>4RF?&O_Lyh%_898sE=yvYfhf2h~IlsJi|%7 zSL@lc7F~&oK~-*N=Q@r>*AJ|}W=X0!q(HeI?z+?9Vtl>v&#(UL*sEY;aow6C2wJ}8 zK-&*2y-l(XqBN19 zAYh@WG!X=)3yM-gR7#`;Tx@`VB2uLY5|9=IsiCbj1wxTdfFROB3oX@3nc>R+D3HN=Kxn|~?ne&{2;mGVlh5)YM4;I0er!#jMhmYdl`sm3|cEZLa z>f%zoJZ=c)go$lbaA~r3pNJeSnmkc~G8_t1Z@g|GSYqvP{e}m#pO(VnOiBF8ncG{Bo*G*FrN_p+(X> zI?8=<*q#2W!f9SyeEcWj;l`FBNviWyYWjTq^ew)kH1{Fn`*hPl>Qd%xq3yIte|P~a z(qw5;FDi&C=fQUF=bNK-qvnHhTV@{<+ZHHAGsZkIhgrt^-{7O1rp8lZWxo^`qkd8+ z@?GYYnZ}YS&Q8|#sNh;RoA#~i>Fv^d{*XgPr~+468=s%)l*yZN%Jy@eUdtgPrN#cf z+HFp{npHfx5hZ^3Z(|Oe=dz#d!VP^^-1lx0d3jBc#~%naV_h7={`mY%sQcL{-0%gb z7LvVH%vR<3@kJafLyvX(wra5{GOEF^2xp{nv<(X1mBN=@fS-n)qs=MOsFPpZr-rc) zrsT%5kNr8ix2hWuBEyHrmw)%8&Id4v`3=n3qsFrYmiFwVS~6a2O!h_OvNvh$Na6Dg z0n;>uK+>Lu@FMbE?l-CPXEHUZ%k2ytb>cp^CyeX!urhTryl65qcgOOR?RtS-$D-yx zZS-wqlPMP2J)c9V@ux$||TX|_-1-}%3%3uvUH$s6Jyd9xHTytw}nh3pc z>b41ENRP6YnQx$CjGo+r9GS&Y6Bn_PPjc7b#M5>ZxwptJF>3Vk$JEENXEKO+-$#i~ zG#1eaTXg-Ot42fFRKjnTYh>NWW+=u|)83?xYm5L=*EozT3XV#LNdA+)&sf$FcB#^3 z%xTy_Y0wSUkLb)uqArC6aURx9H6~HpD?g&lV3>2$wji+ceB=Q zMI*FWqC5y8Qc;lPR zroA@(SVJL!$}@ZN>=B;JorkBy61J;aRuZX<7_V=>$RbI1PKena>2Os2hK?AvpGV~A z;%6AlB4&9ABgosna#A>WT=>zH!`7853gQQUWk%wbtVyTDT*sHR6HdK#xs-tX;fx&mcH>^SPB~Bn2--TdD_`PM6f5!z>!|~y{~9GO#KzE z;N(;^_f<9S-km7Z%OOSgR*6Y}oYU%}XqjUv7w5YfTN2fC=g&Im@pXa83TbStExokP3d)5A?fq%?ePPLr+B*<($Y(w`flXR5I9NVFk zgrAG$U2f7Nx()6qiW$Zgy)m3CpS4m*Z5cLk>EA$SQJ0PNE*Sry^IV>%V2AwkwEtAu zKbAOBz>`kiRo>mTshFChYp~S6LrvnL9VR2@NYoN>`OX?()o~lB?!)f#U|Z)07U8e) zC>uu+Byv>NjPG!t{_f8jAm%lwPcoNwxHFTY76Kww193I@iMI;Zm%4dR$0=O8zEs6k zbd}iR&nnVmsKoGFt_9lQB0kXUtNVYZHsFS|zS`EYHWag_O$f@mB)lzJ!O8qCb$vJTx(xSu&6!_mSi>YYpd?jTB;DT5 ztk1}BAKy{PENJ&9lk=7b%uTYJmWGmA^7X_JI#8}CW>zP+$$a_jsBeYENXsocfU7-4 zo-W(>y?0+Id_Tp&w#d&!6@pk-deuDEsqgf5-tEy#XVeQjHi)b$i(L;H?n;V zfV){fAU1J3AkjHDOvKZ$I*sV6G$HRizcONkO}t)d+w znoDK#Kt)A8P2W?-i8aSxW~E+l_s3szVJhSgEYYkZ;uqcw=D_rgI*SMdSV@FLVqskEmW2zhCvhanfS6i{h>fG z%d2{iWR?5r%jk^Lnd8f}1%`9M3~T6HM79@NalL7Tjnag!kELjK6dQ-dQ-}2BLyp;9v_@YR>=CiDCMT*)+{bp#w5pBq-7?=;~##6cnQRd zW=90-5JF#h`*gFhaEA&l2ajpvHJ$aSj*r_UwzNz+=Kk=0qra{*eRbMFCqwCW79pec ztp@j5^#jRnMGK+JPQmcfoREPG|)Ik&q$Ie%O+Ek2M-~q4i5{HNS6^B>xqAFBYyLr)q!p9Rn z7vDMtHnDe?$YQ6q7hCN0P@1WEH<RkTMuJyyqo9 z_0(b+a{U?Fu^f%~MmhK^&aQ#0_iHa+>wlnNAfgq+9WLlz9fK&o6xCvPo;y z0x-S4h_lGV?tEWqlOQ*|g9})_=-XdHhB-Lgd?U9N&!}Hmh*Ml1D`I*Y`yH8)y5OF{ zGzxdXyl9plgRFb5j|o@Cuv8w#x}Dt^2ogMyITdaxUbv_u0bIVG34VmGey89dSAJch zKp|30g};48b@d%-E*XUSmcf^(W5%90#}cJ>{N7Bb?G7LJwazSZ9g+pU=6IXOpdneH zmBtY%{h_5EP`BEMUO@A@u_&2;>Zj|`+?O2yHOsDDZHg^0md1#WI)Oq%w6GLt;U-VE zR_=|l`vrjC&;0mp9VzUTJglqxRJ{9xzS`x|K%(13(JgL|SB7g?FQb-e-|5Q&Q;t2o zNqbg@`kC@VeBoD!wXcllhav0H&6=O_iZ3*;Jl7ZI6>HJjY&^s){BCj_Hx$On3f6Q} zd1s9i=g; zm{f~@FyxP)b$5QyqyFXg1p7G%LW|RQd6zCf0czayY1MOft~}WwegWeLuTAg@Al`+exQ-EO&ZYS56Y0LC)g0^o&fx{ps!KgrPdhRXxLMVzd*aQ6#Q&;Vpc( zc6q!yQTu$CkUQ5)W1qvDOgwvaH3}UO-+MYa5OydQW%DTopB^ZyL7}1EyxX=A+jZp6 z+m7X$H14i^zPzsNJ+z9Gq%y_J(%+TVo01Z+?rs7}s5fa&UFC|q>H0Pjq|dAqgu zZ{xt1smr(mLhKLlzO{ZG;SF#oAkvKH&;b9Ap%jlPn{6eyB|escI^EdYzN5 z-yzNIwH}>9@7#S6Jh(Hpm-e~&%5N?fbl*RpK@@SHD)-IoUoxI8@6_1P&5s%E`_tEb zeH`W9JK(PiS^lf*J6O28}?W#Dth}WG?FS zal9+o;W*Q5VuY`3#$xA!QCqj>FKsRk4E*aBX#B36VDt5L$u&i%hNzQoVb)-RQT0+t<68Z zMIBwXkgtpXht4Y|IKldLN=Q{!%e#N~MBfm8bDOpHXALd?a&?+jU~TaK(t-V#+y4KD z9`=jB__(J3eqlxYd0KzlS01FJsjO8qr1Y;1fk~pM}@S2NaXfy zX`5ElAOL3}>{drl*{ns9lehg?i?ajwbAgTP5ywU`!<-jYeE?s?F@~2TA^J51FPC+boe32(SH4h$4I?i}DnoLE;nO#a?Qu2~smVk&A;;GCn@O zes{4FM_cX&5$yY#39pR)^Od-oppovkvZat6n?9L% zQAK7DDgc2X3e6L;yLu7|&_^bL9-}I|12wYEB~zdLkw5WM7^Gu?0S9aTF<&;O(CpP| z4nJ|6EjL+$gF$(E^dk4h;y}^hF;GS95UYHMT(R=(vTmMx?8hdvg?2|agW6&-+n+yQX0t<0Jc_V)NFyfY-3x?}{gAzD3i(cER|Zsz<{I2yBS zzRficlHe8lU8=b~%G_!o;fHzWvU>vRX$r=0z%9f5?t3tSei!n2KMLMg0Cc_?SIgv{4$6;Ou1mSRT9}XubO(-ltx3}&qz@CAG$es2 zFk5CeF;T%Q^xus>pn!OMiA_g>_W6mytBciZ95n2RChB;Rq$-Suu}|oIpaF|u?wJ%UC(*1EgHP3IM6oeuYGl18YQ|z(5Zn>tj@{n_=Ua_ zq7gMBLtwV>`qcP9!T`%z`^CN-$?X2H#%~4rZQE;&3!Iyh>yK6NsE`MyCN$Caxw}Ob z`OieKkG6NJ+npyF{T^zT((n+o#<4~-Zs`^gD`^UgWnB`*wC$g&-Ni84L_MR;&Ik-vJgyQQ-<)O<7l`O z3>6|emv}-Cd+K!AR}?*f|G++Iv2|K!?~(JYu?}1K;fRvL`gTKYE9)UPW5927mmrYQ z``Gt7=@KXB=iY^%>b%4Gnq3LcF|S>FYY=lW{RB@Fc;dswjI6B*KzoN&%_d5}{oJpC(!Q%=j|Shq&YVo~_t0;r7xye^-BVGbfRc*uPJ>aB6c-XS< zH(;JydG3Ga=ie7(92*%Uq%30SzaPi@vt`dW8JDG6b$0yHQFD4bmB^QN3(SjW{d9mq4XL$m8aP0x%*v&Fy zXyg{a$nRA78T78xOM*XsG zB_v0Mtnrpf1G>yTqJ@skr2L^)bsibZL4I>ZCBYI3Dq?W@9I$VG!NN%$td9+bbAP|D zvZu$)g|GNxkl_BB6SA__G3l*JT@l^hREzSr&A8znF_rRKU$3GfbjEoT;a{$8NJqnCLC@gr?w2Q!waJ7 z=bu*$ZM;dN9P4y)u=Vo3q4o01GfNLuu~L$Zgj&kL@#%bLZ{sjG>z4%?`b9!VghK$I z14W@B%YHwGls%!#+`ng=ZJw_d<}(^qk$uqO8-&n;x2$$o>VEP%X?e~i>a={iUB{Dz zflisp9=$y#uud?XUe8D0jD=^599amNyx+%%~^$ix-Re)-;6TOi7@ zwp7)v+QqDtgfaj6a+WWnHz7NveK-lT+3NejYsNArG>Kva$!HExP*9~_Rue?snWcpn z;z3)Gvoc7&r!;!QB|bYG9c~+I={XmKd9g?Db-2+tc~13#+bi@qK+^Ns`o-Z+xN0H+ z;fE*vMVJh_+vFUGr~4RV_E{YRk^&HaMT3-%L6{ZUf0)2=kT zY%Tc)m zWp&;A_G!H~S+tT#G&0gjT4$ubqQ7i@X~O0m4}PW-UQW6Jbk>JcQb+68Oz z_Wbe;Xq(I|zJiHrNncD50x*VnTV>S3Ic@F~MpOKg+=mURfU7Rw(N_j=8H=L%d8hCX zWbYBB_7wK+URB^c>SO1&EfXNUz64wvpTS~}X*~NOoH)B<+#Zk5y^Z#N3NxpSS4-Bm zKJ^}$ng={2y}y+19rADNLbEk;#eva((o@$JR_s|?K$JEzbZ6@jdYE(ed24f>XI?|K9&+X9k42RWXbn^+!4WE%Fex%4|ckSdd>{j>xx)*o|A zTdhZdr>5>+{MP}GK%{bAi$=v#>T)mZ+8f^m9N|hQ7BVW2v~JZLh(R&;2`0a z0g{SPtFiTSn@XJ&TP}CAb-_cjwX=DqhVQ-j-k*F$^gG~%ED)Lto9($}d4Rx?4dwCh z?Egf6Pepw|3^>kMaSFg+gKkGUSpeON=v_0j za|0g8GN9vh143BN9tD$lyH>Kg}Fg(?rZwpvlLfIzGTpwK(*FjL^cW7JCuu3p7{ z0*qVlAx^nqTnU-I1~BGirz(T47b=;o|nq4!45;NV}C`*4$5m{7W? z>kP_H@&kalt8Q^8bi7o?`Q{pmM%5xLjQNdMDAiLzHW9!vHdUk*OM)eE)UpTy;8PgG zTV32|SNQwP58nucP}Qwl!s&kgJ0<KX#5WMOD7pEN;E<~L;^?NNQ6kozd% z@q>)G7pGA^aWqUL$E%TI0<|zm93|A|3Vk9u;hd!3z{*GgQy?H^IyZ+x2d1Oyp=%lT za%FWu8+Fmg(trC?t?=ln_@h>$2d(Vv*Cek}>5AS;@H7qS!4I?mg>Ba`>lt&J_RD-{yee-T=XxQ z4q2>=KSy@lG{Ecg)5=><>%z|<6S0}^iPOCP?J8cPqS#?UT}Qas>tXS1HiEcW*o zk&$VbuIyiEr3ti0$vAyg;#n(fi34g+O5#d2?@Ulo?Z9_zvwHg4aQx!0Nc&D`+Ih2B zFzCvA`{}`YmHkdP0SvkDMD3L(Q2hYgcoxP$G`MPD3IVaP-a-fMy6dEm8Ebf2lPW@V0hNeCPMR+eOhF-e zI0n7}*B_;i;^zyqYJe94Km%pw57m$D1424!pRj2uDXBP5^?=uaYoA*94eIorcr{Zz zUqp6Yp@gNjfaa~S@e3DW#02Eesnou{TjH?hO;nWh`NEkSRTdqj735&$Hgt#gw+X_i z=Hw{phuEP8cd^R(jxG(|LZP5-C$u>=GJ9Irw_&G$JM_wKL;9E23Cuja0rw4H8;mEC z=!J{b2Cnf00zf;UU>li7Ui=Rdl{IAWaTb=0q0{Onjy*8Y@k9QF;}oXq#Gsd8O0zB z0CzcMaEy`#NWuBgl8@xnb|$v**hG}GRHrW?0)Rab0>Q-C^WGLHd4=^mgI4=0 z`4ICnOx6Qt6eAUGtR_{Wn?);Iw@I3sXLBy&Vyu3OpPygY<3Na&6$iyU3r~(of3wXc z3uECejVp8I6!>D>c%+`BH;QFjMIYr^N__wy0b(u2ei7*y3L3W@!pmn?NSy1>rM~P! zMgt+CvTBMYY{nUX=<9HXz1nFR@W>r(1^Ow1?5gIwG=P#Ww0Ucg@>NN-Gz3&Ze&iV4 zl$zi>PGdL42H8DT?%b?ZlCNIz;qfDq7X3H5vKm=Q$yhrJ)gJffX-U8!U%%}ahthb# zQzWXnj=Elej5PpmP=oj2m7mY(d~LX{r1`;yDS7X(RVeyoTk-p;Gy^heotSi$)9n)? zzwz=?({7w^(BW-L+^ZFSEQqKVAD^R^5i5@omPdtaLP*bS#!+W#WXER5)29*%M=wTX zg3UlppG3~~0pVP@Sc3NuCGRF9fArTw63Ts|5n*OAda5=QK%650zL!Sicwkd^8TnA5 zh-wZsG;E%5bG5(7hF3KE{_uyEO-{Z`>M8oa{JbP zU29L0^3FS>Xk`Jpmwi3w%>$9e+b5@VhbX69oj;@U5CAS=a^0Bo@Jf3*CDkhxRb$ZA z5~0*r*VG)ojSCgazIH6^rU61+nw~REG5P_qfq6#S2LQ-6PqBD7HfJm!)lwVnH;|=XdP;iQd2JduXOvU_K8du@%Ri<+XtFK9XH)Ua z!fnXu>8&lHxb3@0|H*H}u6c@U<0sw2~$3Sg(M1r5} zVe>5emwj6F+zEMzLMaaEHfw2{oUktW0%t~T45&HK>@Ma8oG+6*>=DoocCRB4Z%T^P zpAz@tCus?tfu+zt_(a3&$&zS{S=Ov-c6h%i`l4)sYDP>X4%04J$Qka9@r*4ry!ZO7 zPGjwm6&PKaM<7}IK%^0d0XluBQ!#-{ooca9YO>$AbTztEGt6_vFTNqzOYTtJ5c--U zQ(XR&z|IVA2U!N^Tg%6L0s2~D#N*`~B4(5ybL66|c~G;}oZ5a5rF7rCp-5<0iIVe! zmqeuJ=i5;K;8+gibCI%X=zgoxYJVZCbbX#WEvxNJI6vP$%l*=QakyC9_{c+pX<>#s zs2RWCorRR8un4_^jPgNZy?(6ARp0t}DY7eN`DFkE!JLFyEDFnP{Lua5C#vSQ%%3fm$>`b{y^~@x(wc z?TyHhEq*iWgR2hVDtV@tQvNPD!Cy`A%fJ-k^=g;&ON1L72a0Ds9p&Tge-72GH9U!8 z8z7BRNf8~=mMcpmXY4$IC;}dJ|2D9Nc3SojI^6%tmixiBU8v~U)uXY+W>o#{%&zOw zJ4)lZu+H{esjs|l(8qyQ7@A%57cpXb%CgDcl^34iICfpi0qG!fPFNg}jeYR-ev&<^ zS$o|Fj(l>4W=!S4RL|_oIlbS?T8_NF)J3e_?g{LB!Bu^T@7+C7UtbR(qKJU1zUnn( zq9pKgjAD6F9-_$dSyb~mc6RJ$?C(x^vCrYw`-@@|CAljXkMh)lYsVr1prGr$n~FXv z48pV~t==A1vt8{l5D$%lp;d*Dhe&|~gcCcJB~*2$Hb4Fy*Ko6dJ)?Y1M#6*&oB*s_ zrN8a(=XyG`CJmUJBnowejS5{u|B_&^y&It~4}740SqCe>wQ$bIg5hEfA?|H=89L@* znx&Do+KBMS#Kh&RqP?WB9!c@P!aXbR3CI!r`s`sb8R)Db=&6_ z1r1nV1-p=}wyWXGzF`7O+JBrlu$pw5%m|0L?T2iLF|B%0x0=G8iug#7=SPh8SI9rL zdci(G>c#P(aSVR4S@86^p3L@hbc?+Flu28q0I_<+ih~pL71>9`dWXUt@y{gJs`Yjm z!Y1y^N|$34-Tn6a=WJ1Ktj#&VaX{?K;vi&eM8yTqS=%1-+I$Xuq%AA-NLSsish4^I zBRa&Eqp!U?uaUUP%l-FrAyjj!#9_itY4q^adC#Sk8^8^Xcbie!AbSg5=(wSrsF#iY zwsRLTZjUmCP(=|YUBl4@=68XX1Tx0zd=%;(1OdPXzAUYCz#$K5rfj!?;uoO zH}eD}><~h{>NtueMe_LZT@8sLCP&ShxtrP(A`bYy2rB(3{>?%;vy%Vz?B(Z)v`beu zpgc5?g<_8hh?K8y(LNR)qaO53pP}dE*E1pUT$t5>MMzfQY9;>`V#Sx4u-)=Lvg$y@-}fyz1PdglO@#fc-!&Xln(_;eJ4LuIodYeMb3=Gw!DNV zN*J2}#?ZsX=}+=Opg6>R*e6PVOW89E0egSRP5~?e6cyn zASr%t7a#xIggt^(HEhyqdyW8qQ-hzceez(-%bkpXy>v-Dq;fy6m9ZK+s)4y8Rl5h8 zmw-%{n_~OD4w-p{ht1Hb^lc?$BUu=NfQ+J4(+MsCuRv!mfl$@DE%oO!b#?O9(v1sZ zg8W`QiqTJK*`FEOrQ7D&VPw-FCShgS4E$#Nw?UimAui&zxGSfi$A%l$_t}}5MiY*+ z=bn#+9g%Tu-}Zou| zcpPQrALR)Ux#wW5orgi!1@ZDnb06S`Ngce{zbjvFjf+ruX%+u)Q%aL| zkN*q)82!P{Lv%%K5Wy-wZ-thH-QL-U-0bg7QJu9WdMFkSGAL;` zS-AUr;J#xWhIEpGEW`cWmR!3w`sbQk+{qa+(bD4hAYB9QWs$*5p|=JJ@f*#Qx`^fS zLqG&H9Dl9C)oa25uKYL(8|s2TEMRD8R1}cHk;nz}uJS{2#aa`BLov5F^m?A!0XQ8P z`;A;6IP5g}E}8RaAx4*LO Date: Fri, 3 Jan 2025 16:19:19 -0800 Subject: [PATCH 25/26] replace vrf with locator in the key combo of SRV6_MY_SIDS --- doc/srv6/srv6_static_config_hld.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index e6bf7c6aa8..1f38ec8c54 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -115,14 +115,13 @@ Schema: ``` ; New table -; holds local SID to behavior mapping, the keys are full IPv6 addresses of the SIDs +; holds local SID to behavior mapping, the keys are the locator name plus the full IPv6 addresses of the SIDs -key = SRV6_MY_SIDS|vrf|ip_address +key = SRV6_MY_SIDS|locator|ip_address ; field = value -locator = locator_name ; the name of the locator that the SID belongs to action = behavior ; behaviors defined for the SID, default uN decap_vrf = VRF_TABLE.key ; Optional, VRF name for decapsulation actions, default "default", only applicable to uDT4/uDT46/uDT6 actions -dscp_mode = dscp_decap_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions +decap_dscp_mode = decap_dscp_mode ; Optional, the parameter that specifies how the node should handle DSCP bits when it performs decapsulation, default "uniform", only applicable to uDT4/uDT46/uDT6 actions For example: "SRV6_MY_SIDS" : { @@ -131,6 +130,7 @@ For example: }, "default|FCBB:BBBB:20:F1::" : { "action": "uDT46", + "decap_dscp_mode": "pipe" } } ``` From c5b1b06577c0194a028ba4b4626bbbce54af7073 Mon Sep 17 00:00:00 2001 From: BYGX-wcr Date: Mon, 6 Jan 2025 15:41:55 -0800 Subject: [PATCH 26/26] fix typos and add an example for my locators table --- doc/srv6/srv6_static_config_hld.md | 34 ++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/doc/srv6/srv6_static_config_hld.md b/doc/srv6/srv6_static_config_hld.md index 1f38ec8c54..96b061253c 100644 --- a/doc/srv6/srv6_static_config_hld.md +++ b/doc/srv6/srv6_static_config_hld.md @@ -104,6 +104,16 @@ node_len = nlen ; bit length of node ID portion in address, default func_len = flen ; bit length of function portion in address, default 16 arg_len = alen ; bit length of argument portion in address, default 0 vrf = VRF_TABLE.key ; the VRF that the locator belongs to, default "default" + +For example: + "SRV6_MY_LOCATORS" : { + "loc1" : { + "prefix" : "FCBB:BBBB:20::" + }, + "loc2" : { + "prefix" : "FCBB:BBBB:21::" + } + } ``` @@ -125,13 +135,16 @@ decap_dscp_mode = decap_dscp_mode ; Optional, the parameter that specifies how For example: "SRV6_MY_SIDS" : { - "default|FCBB:BBBB:20::" : { + "loc1|FCBB:BBBB:20::" : { "action": "uN" }, - "default|FCBB:BBBB:20:F1::" : { + "loc1|FCBB:BBBB:20:F1::" : { "action": "uDT46", "decap_dscp_mode": "pipe" - } + }, + "loc2|FCBB:BBBB:21::" : { + "action": "uN" + }, } ``` @@ -158,20 +171,19 @@ module: sonic-srv6 +--rw SRV6_MY_LOCATORS | +--rw SRV6_MY_LOCATORS_LIST* [locator_name] | +--rw locator_name string - | +--rw prefix? inet:ipv6-address + | +--rw prefix inet:ipv6-address | +--rw block_len? uint8 | +--rw node_len? uint8 | +--rw func_len? uint8 | +--rw arg_len? uint8 | +--rw vrf? union +--rw SRV6_MY_SIDS - +--rw SRV6_MY_SIDS_LIST* [vrf ip_address] - +--rw vrf union - +--rw ip_address inet:ipv6-address - +--rw locator? -> /sonic-srv6/SRV6_MY_LOCATORS/SRV6_MY_LOCATORS_LIST/locator_name - +--rw action? enumeration - +--rw decap_vrf? union - +--rw dscp_mode? enumeration + +--rw SRV6_MY_SIDS_LIST* [locator ip_address] + +--rw ip_address inet:ipv6-address + +--rw locator -> /sonic-srv6/SRV6_MY_LOCATORS/SRV6_MY_LOCATORS_LIST/locator_name + +--rw action? enumeration + +--rw decap_vrf? union + +--rw decap_dscp_mode? enumeration ``` Refer to [sonic-yang-models](https://github.com/sonic-net/sonic-buildimage/tree/master/src/sonic-yang-models) for the YANG model defined with standard IETF syntax.