From 1e05640993b3af2509d016d62bcaf44a18eca190 Mon Sep 17 00:00:00 2001 From: Mohanarajan Selvaraj Date: Fri, 16 Aug 2019 11:20:59 -0700 Subject: [PATCH 001/175] This document describes the functionality and high level desigh of broadcast, unknown-unicast and unknown-multicast storm-control feature in SONiC --- .../bum_storm_control_hld.md | 411 ++++++++++++++++++ .../images/storm_control_architecture.png | Bin 0 -> 21052 bytes .../images/storm_control_disable_on_port.png | Bin 0 -> 16127 bytes .../images/storm_control_enable_on_port.png | Bin 0 -> 16269 bytes .../images/storm_control_update_on_port.png | Bin 0 -> 19513 bytes 5 files changed, 411 insertions(+) create mode 100644 doc/bum_storm_control/bum_storm_control_hld.md create mode 100644 doc/bum_storm_control/images/storm_control_architecture.png create mode 100644 doc/bum_storm_control/images/storm_control_disable_on_port.png create mode 100644 doc/bum_storm_control/images/storm_control_enable_on_port.png create mode 100644 doc/bum_storm_control/images/storm_control_update_on_port.png diff --git a/doc/bum_storm_control/bum_storm_control_hld.md b/doc/bum_storm_control/bum_storm_control_hld.md new file mode 100644 index 00000000000..e3317cd2dc4 --- /dev/null +++ b/doc/bum_storm_control/bum_storm_control_hld.md @@ -0,0 +1,411 @@ + +# SONiC BUM Storm Control +# High Level Design Document +#### Rev 0.1 + + +# Table of Contents + * [List of Tables](#list-of-tables) + * [Revision](#revision) + * [About This Manual](#about-this-manual) + * [Scope](#scope) + * [Definition/Abbreviation](#definitionabbreviation) + * [1 Feature Overview](#1-feature-overview) + * [1.1 Requirements](#11-requirements) + * [1.1.1 Functional Requirements](#111-functional-requirements) + * [1.1.2 Configuration and Management Requirements](#112-configuration-and-management-requirements) + * [1.1.3 Scalability Requirements](#113-scalability-requirements) + * [1.1.4 Warm Boot Requirements](#114-warm-boot-requirements) + * [1.2 Design Overview](#12-design-overview) + * [1.2.1 Basic Approach](#121-basic-approach) + * [1.2.2 Container](#122-container) + * [1.2.3 SAI Overview](#123-sai-overview) + * [2 Functionality](#2-functionality) + * [2.1 Target Deployment Use Cases](#21-target-deployment-use-cases) + * [2.2 Functional Description](#22-functional-description) + * [2.3 Limitations](#23-limitations) + * [3 Design](#3-design) + * [3.1 Overview](#31-overview) + * [3.2 DB Changes](#32-db-changes) + * [3.2.1 CONFIG_DB](#321-config_db) + * [3.2.2 APP_DB](#322-app_db) + * [3.2.3 STATE_DB](#323-state_db) + * [3.2.4 ASIC_DB](#324-asic_db) + * [3.2.5 COUNTER_DB](#325-counter_db) + * [3.3 Switch State Service Design](#33-switch-state-service-design) + * [3.3.1 PolicerOrch changes](#331-policerorch-changes) + * [3.4 SAI](#34-sai) + * [3.5 CLI](#35-cli) + * [3.5.1 Data Models](#351-data-models) + * [3.5.2 Configuration Commands](#352-configuration-commands) + * [3.5.3 Show Commands](#353-show-commands) + * [3.5.4 Clear Commands](#354-clear-commands) + * [3.5.5 Debug Commands](#355-debug-commands) + * [3.5.6 Rest API Support](#356-rest-api-support) + * [4 Flow Diagrams](#4-flow-diagrams) + * [4.1 Enable storm control on physical interface](#41-enable-storm-control-on-phy) + * [4.2 Disable storm Control on physical interface](#42-disable-storm-control-on-phy) + * [4.3 Update storm Control on physical interface](#43-update-storm-control-on-phy) + * [5 Error Handling](#5-error-handling) + * [6 Serviceability and Debug](#6-serviceability-and-debug) + * [7 Warm Boot Support](#7-warm-boot-support) + * [8 Scalability](#8-scalability) + * [9 Unit Test](#9-unit-test) + * [9.1 CLI Test Cases](#91-cli-test-cases) + * [9.2 REST API Test Cases](#92-rest-api-test-cases) + * [9.3 Functional Test Cases](#93-functional-test-cases) + * [9.4 Scaling Test Cases](#94-scaling-test-cases) + * [9.5 Warm Boot Test Cases](#95-warm-boot-test-cases) + * [9.6 Negative Test Cases](#96-negative-test-cases) + + +# List of Tables +[Table 1: Abbreviations](#table-1-abbreviations) +[Table 2: Storm Control SAI attributes](#table-2-storm-control-sai-attributes) + + +# Revision +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.1 | 06/24/2019 | Mohanarajan Selvaraj| Initial version | + + +# About this Manual +This document provides general information about Broadcast, Unknown-unicast and unknown-Multicast storm-control feature implementation in SONiC. +# Scope +This document describes the functionality and high level design of Broadcast, Unknown-unicast and unknown-Multicast storm-control feature in SONiC. + + + + +# Definition/Abbreviation +### Table 1: Abbreviations +| Term | Meaning | +|--------|--------------------------------------------------------| +| BUM | Broadcast Unknown-unicast and unknown-Multicast | + + +# 1 Feature Overview +A traffic storm occurs when packets flood the LAN, creating excessive traffic and degrading network performance. The type of traffic can be Broadcast, Unknown-unicast or unknown-Multicast (BUM). +The storm-control feature allows the user to limit the amount of BUM traffic admitted to the system. This can be achieved by configuring the type of storm (Broadcast or Unknown-unicast or unknown-Multicast) and the corresponding bits per second (bps) parameter on a given physical interface. Traffic that exceeds the configured rate will be dropped. +Unknown-multicast traffic consists of all multicast traffic which donot match any of the statically configured or dynamically learned multicast groups. + + + +## 1.1 Requirements + + +### 1.1.1 Functional Requirements + 1. Support configuration of Broadcast, Unknown-unicast and unknown-Multicast storm-control independently on physical interfaces. + 2. Support threshold rate configuration in bits per second (bps) in the range of 0 bps to 100Gbps. + +### 1.1.2 Configuration and Management Requirements +This feature will support SONiC CLI. + 1. Support a CLI to add or delete broadcast, unknown-unicast and unknown-multicast storm-control on a physical interface as described in "Configuration Commands" section below. + 2. Support show commands to display the storm-control configuration as described in "Show Commands" section below. + 3. Support debug commands as described in "Debug Commands" section below. + 4. Support openconfig REST API and gNMI. + + +### 1.1.3 Scalability Requirements +Storm-control configuration is done on physical ports. Hence it should be supported on all physical ports of the system. + +### 1.1.4 Warm Boot Requirements +Storm-control functionality should continue to work across warm reboot. + +- To support planned system warm boot. +- To support SWSS docker warm boot. + + +## 1.2 Design Overview + + +### 1.2.1 Basic Approach +The Policer Orchestration agent is used for handling BUM storm-control configuration. + +### 1.2.2 Container +No new containers are introduced. Functionality is added to the existing swss container. + +### 1.2.3 SAI Overview +The existing SAI policer and interface APIs shall be used to support this feature and they are available at below location, +https://github.com/opencomputeproject/SAI/blob/master/inc/saipolicer.h
+https://github.com/opencomputeproject/SAI/blob/master/inc/saiport.h + + +The details of the changes will be discussed in the design section below. + + +# 2 Functionality +Refer to section 1 +## 2.1 Target Deployment Use Cases +Any Layer-2 network segment where unknown-unicast / broadcast / unknown-multicast traffic storm should be controlled. + + +## 2.2 Functional Description +Refer to section 1.1 + +## 2.3 Limitations +BUM storm control +- Configuration is not supported on VLAN and port-channel interfaces. +- Statistics is not supported. + + + +# 3 Design +## 3.1 Overview + + +![Storm Control](images/storm_control_architecture.png "Figure 1: Storm control High Level Architecture") + + +__Figure 1: Storm Control High Level Architecture__ + +1) Storm-control configurations are parsed and stored in CFG_PORT_STORM_CONTROL_TABLE in Configuration database by the Management Framework. +2) The Policer Orchestration Agent subscribes to notifications from the CFG_PORT_STORM_CONTROL_TABLE and parses the input parameters (interface, storm-control type, bps). A policer_name is created internally by encoding the interface_name and storm_control_type. +3) create_policer SAI API is invoked to create a policer with the given input parameters. +4) The identifier of the policer created is associated with the encoded policer_name. +5) The policer identifier is passed to set_port_attribute SAI API to set the appropriate type of storm-control on the port. + + +## 3.2 DB Changes +This section describes the changes made to different DBs for supporting storm-control. + + +### 3.2.1 CONFIG_DB +A new table CFG_PORT_STORM_CONTROL_TABLE is introduced in the configuration database for the purpose of storing storm-control configuration parameters. This table is filled by the management framework. +#### CFG_PORT_STORM_CONTROL_TABLE + + ;Store Storm Control configuration per physical port + ;Status: work in progress + ;storm control type - broadcast / unknown-unicast / unknown-multicast + key = CFG_PORT_STORM_CONTROL_TABLE:port:storm_control_type ; Ethernet Interface Name and storm control type + ;field = value + enabled = BIT ; Is the storm control enabled (1) or disabled (0) on the interface + bps = 1*13 DIGIT ; CIR value in bits per second + +### 3.2.2 APP_DB +No tables are introduced in APP_DB +### 3.2.3 STATE_DB +No tables are introduced in STATE_DB. + +### 3.2.4 ASIC_DB +No changes are introduced in ASIC_DB. +### 3.2.5 COUNTER_DB +No changes are introduced in COUNTER_DB. + + +## 3.3 Switch State Service Design +### 3.3.1 PolicerOrch changes +Policer Orchestration agent is responsible for the following activities: + - Subscribes to notifications on CFG_PORT_STORM_CONTROL_TABLE entries in the CONFIG_DB. + - Creates an internal name for policer by encoding the interface name and storm-control type. + - Creates the policer based on the parameters and associates the policer identifier to internal name + - Populates the port attribute SAI structures and pushes the entry to ASIC_DB. + + +## 3.4 SAI +Storm-control SAI interface APIs are already defined. The table below represents the SAI attributes which shall be used for BUM storm-control. + + +###### Table 2: Storm Control SAI attributes +| Storm Control component | SAI attributes | +|--------------------------|--------------------------------------------------------| +| Meter type | SAI_POLICER_ATTR_METER_TYPE | +| Meter mode | SAI_POLICER_ATTR_MODE | +| CIR (bps) | SAI_POLICER_ATTR_CIR | +| Unknown-unicast policer | SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID | +| Broadcast policer | SAI_PORT_ATTR_BROADCAST_STORM_CONTROL_POLICER_ID | +| Unknown-Multicast policer| SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID | + + +The BUM storm-control feature can be enabled on a physical port. + +The **create_policer** SAI API is used to create the policer based on the policer parameters listed in Table 2. + - Meter Type - Can be packets or bytes. Storm-control uses bytes meter type. + - Meter Mode - Can be st_tcm or tr_tcm or storm. Storm-control uses storm meter mode. + - CIR (bps) - Value of CIR configured in bps. + +The **set_port_attribute** SAI API is used to set the policer on an interface. + - Unknown-unicast policer - Enables storm-control for unknown-unicast traffic received on the interface. + - Broadcast policer - Enables storm-control for broadcast traffic received on the interface. + - Unknown-multicast policer - Enables storm-control for unknown-multicast traffic received on the interface. + +## 3.5 CLI +### 3.5.1 Data Models +Custom Yang model will be introduced for this feature. + + +### 3.5.2 Configuration Commands +BUM storm-control can be configured only on physical interfaces. +**switch# configure terminal**
+**switch(config)# interface Ethernet **
+**switch(config-if)# storm-control {broadcast | unknown-unicast | unknown-multicast} {bps \}** + + +#### 3.5.2.1 Enable Broadcast storm control on a physical interface +This command configures broadcast storm-control on a physical interface.
+**switch(config-if)# storm-control broadcast {bps \}** + + +#### 3.5.2.1 Enable Unknown-unicast storm control on a physical interface +This command configures unknown-unicast storm-control on a physical interface.
+**switch(config-if)# storm-control unknown-unicast {bps \}** + + +#### 3.5.2.1 Enable Multicast storm control on a physical interface +This command configures unknown-multicast storm-control on physical interface.
+**switch(config-if)# storm-control unknown-multicast {bps \}** + + +### 3.5.3 Show Commands +The following show command displays storm-control configurations. + +**show storm-control [interface \]** + +Following is a sample output + +**show storm-control**
+ +###### Table 3: show storm-control +| Interface | Type | Rate(bps) | +|-----------|------------------|-----------| +| Ethernet0 | broadcast | 1000000 | +| Ethernet0 | unknown-unicast | 2000000 | +| Ethernet2 | unknown-unicast | 5000000 | + +**show storm-control interface Ethernet2**
+ +###### Table 4: show storm-control interface +| Interface | Type | Rate(bps) | +|-----------|------------------|-----------| +| Ethernet2 | unknown-unicast | 5000000 | + +### 3.5.4 Clear Commands +Not applicable +### 3.5.5 Debug Commands +Not applicable +### 3.5.6 REST API Support +REST SET and GET APIs will be supported. + +# 4 Flow Diagrams +## 4.1 Enable storm control on physical interface + +![Storm Control](images/storm_control_enable_on_port.png "Figure 2: Enable storm control on physical interface") + + +__Figure 2: Enable storm control on physical interface__ + + + + + + +## 4.2 Disable storm control on physical interface + + +![Storm Control](images/storm_control_disable_on_port.png "Figure 3: Disable storm control on physical interface") + + +__Figure 3: Disable storm control on physical interface__ + + +## 4.3 Update storm control on physical interface + + +![Storm Control](images/storm_control_update_on_port.png "Figure 4: Update storm control on physical interface") + + +__Figure 4: Update storm control on physical interface__ + + +# 5 Error Handling +# 6 Serviceability and Debug +Debug commands as described in Debug Command section will be supported. Debug command output will be captured as part of tech support. +- A CLI error will be displayed via console and configuration will be rejected +- Internal processing errors within SwSS will be logged in syslog with ERROR level +- SAI interaction errors will be logged in syslog + + +# 7 Warm Boot Support +The storm-control setting on the port should be retained across warmboot so that the BUM storm traffic gets rate-limited as per the configured policer parameters. + + +# 8 Scalability + + +Storm-control is a physical port parameter. Testing would be done by enabling storm-control on all the physical ports. +###### Table 3: Scaling limits +|Name | Scaling value | +|--------------------------|--------------------| +| Number of interfaces | max_physical_ports | + +# 9 Unit Test +## 9.1 CLI Test Cases + + + 1. Configure broadcast storm-control on interface and check that it is updated in CONFIG_DB. + 2. Configure unknown-unicast storm-control on interface and check that it is updated in CONFIG_DB. + 3. Configure unknown-multicast storm-control on interface and check that it is updated in CONFIG_DB. + 4. Unconfigure broadcast storm-control on interface and check that it is updated in CONFIG_DB. + 5. Unconfigure unknown-unicast storm-control on interface and check that it is updated in CONFIG_DB. + 6. Unconfigure unknown-multicast storm-control on interface and check that it is updated in CONFIG_DB. + 7. Execute the show storm-control command to check the configuration. + 8. Verify that the BUM storm-control configurations are correctly re-applied after cold reboot. + 9. Verify that all the three storm-control types can be configured and rate limiting is + applied independently on the three types of traffic received at the interface. + 10. Verify that the bps value configured is independent per interface. + 11. When user configures BUM storm-control on interface where the same type is already configured, + verify that if bps value is different, the new bps value is updated to the CONFIG_DB. + + +## 9.2 Rest API Test Cases + 12. Verify broadcast, unknown-multicast and unknown-unicast can be configured on interface using REST. + 13. Verify broadcast, unknown-multicast and unknown-unicast can be unconfigured on interface using REST. + + +## 9.3 Functional Test Cases + 14. Verify that broadcast traffic gets rate-limited as per broadcast storm-control policer parameters. + 15. Verify that unknown-unicast traffic gets rate-limited as per unknown-unicast storm-control policer parameters. + 16. Verify that multicast traffic gets rate-limited as per multicast storm-control policer parameters. + 17. Configure all three BUM storm-control on interface and verify that the rate-limiting of traffic is as per the + respective policer parameters. + 18. Verify that other traffic streams are unaffected by BUM storm-control configuration. + 19. Verify that after unconfiguring BUM storm-control configuration on interface, BUM storm traffic rate is no + more rate limited. + 20. Verify that traffic is rate-limited as per the updated value of bps when user updates existing + BUM storm-control configuration on interface. + + + +## 9.4 Scaling Test Cases + 21. Configure BUM storm-control on all the physical interfaces on the system and check that rate-limiting is + performed on all interfaces. + +## 9.5 Warm Boot Test Cases + 22. Verify that BUM storm-control configurations are restored after warm boot. + 23. Verify that BUM storm rate-limiting continues to work at the specific rate across warm boot. + 24. Verify that BUM storm-control is only active on interfaces that previously had storm-control configurations + before warm boot. + + +## 9.6 Negative Test Cases + 25. Verify that storm-control configuration errors out when applied on port-channel or vlan interfaces. + 26. Verify that error is returned when the same configuration is repeated on the interface. + 27. Configure BUM storm-control on interface without providing bps value and check that configuration is + not accepted. + 28. Unconfigure BUM storm-control on interface by providing bps as input and check that + additional / invalid parameter error is displayed. + 29. Verify that invalid parameter error is displayed when value of bps is out of range or invalid. + 30. Verify that invalid parameter / input error is displayed when invalid input is provided for storm-control type. + + + + diff --git a/doc/bum_storm_control/images/storm_control_architecture.png b/doc/bum_storm_control/images/storm_control_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..7c5c01747de3ea96fd98166a4c94cb7b33f4834b GIT binary patch literal 21052 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 BK2ZPw literal 0 HcmV?d00001 diff --git a/doc/bum_storm_control/images/storm_control_disable_on_port.png b/doc/bum_storm_control/images/storm_control_disable_on_port.png new file mode 100644 index 0000000000000000000000000000000000000000..6fb6db10b56e69845e0e5b0e258d5447d9847b9a GIT binary patch literal 16127 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 Q6yP63QA43X&g{wm0292@&j0`b literal 0 HcmV?d00001 diff --git a/doc/bum_storm_control/images/storm_control_enable_on_port.png b/doc/bum_storm_control/images/storm_control_enable_on_port.png new file mode 100644 index 0000000000000000000000000000000000000000..683102bf2da2a7a960a2cdd44ddc23eca5f78e0f GIT binary patch literal 16269 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 anIJ-*6sN=ib%4nOX{zg9E4X46`ab|FO&7BO literal 0 HcmV?d00001 diff --git a/doc/bum_storm_control/images/storm_control_update_on_port.png b/doc/bum_storm_control/images/storm_control_update_on_port.png new file mode 100644 index 0000000000000000000000000000000000000000..f305183757da4db935d5d7f0841bb1b1b9067656 GIT binary patch literal 19513 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 Date: Fri, 22 May 2020 22:21:11 -0700 Subject: [PATCH 002/175] Distributed forwarding in a VOQ architecture HLD --- doc/chassis/system-ports.md | 233 ++++++++++++++++++++++++++++++++ images/chassis/architecture.png | Bin 0 -> 41796 bytes 2 files changed, 233 insertions(+) create mode 100644 doc/chassis/system-ports.md create mode 100644 images/chassis/architecture.png diff --git a/doc/chassis/system-ports.md b/doc/chassis/system-ports.md new file mode 100644 index 00000000000..695f21c90ce --- /dev/null +++ b/doc/chassis/system-ports.md @@ -0,0 +1,233 @@ +# Distributed Forwarding in a Virtual Output Queue (VOQ) Architecture + +# High Level Design Document +#### Rev 0.1 + +# Table of Contents +* [List of Tables](#list-of-tables) +* [List of Figures](#list-of-figures) +* [Revision](#revision) +* [About this Manual](#about-this-manual) +* [Scope](#scope) +* [Definitions/Abbreviation](#definitionsabbreviation) +* [1 Requirements](#1-requirements) +* [2 Design](#2-design) +* [3 Testing](#3-testing) + +# List of Tables +* [Table 1: Abbreviations](#definitionsabbreviation) + +# List of Figures +* [Figure 1: VoQ Distributed Forwarding Architecture](#41-general-flow) + +###### Revision +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|--------------------| +| 0.1 | May-19 2020 | Kartik Chandran (Arista Networks) | Initial Version | + +# About this Manual + +This document provides an overview of the implementation of SONiC support for distributed packet forwarding across a set of devices that have a VOQ (Virtual Output Queue) architecture interconnected by an internal fabric. + +# Scope + +Support for distributed forwarding encompasses the following aspects +- Physical interfaces and VOQs +- Logical interfaces such as link aggregation groups (LAGs) +- The internal interconnection fabric +- The packet forwarding data plane +- The control plane, both internal (within the devices in the system) and with external devices. + +This document covers + - The basic SONiC architecture enhancements to support distributed VOQ based forwarding + - Representation and management of physical ports across the system. + +The other aspects listed above are expected to be covered in separate self-contained design proposals that build on this architecture. + +The initial target for this work is a VOQ chassis system in which linecards running SONiC are interconnected over a fabric and the overall system is controlled by a supervisor module that also runs SONiC. + +However, this architecture makes no hard assumptions about operating within a chassis and can be extended to other form factors with the same VOQ architecture. + + +# Definitions/Abbreviations + +| | | | +|------|--------------------|--------------------------------| +| FSI | Forwarding SONiC Instance | SONiC instance on a packet forwarding module like a linecard. +| SSI | Supervisor SONiC Instance | SONiC instance on a central supervisor module that controls a cluster of forwarding instances and the interconnection fabric. +| Forwarding Device | A unit of hardware that runs SONiC and is responsible for packet forwarding | +| NPU | Network Processing Unit | A component on a forwarding device that performs the packet forwarding function + + +# 1 Requirements + + +# 1.1 Functional Requirements + + +## 1.1.1 Distributed Operation + +* Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more NPUs on the device, including the front panel and internal fabric ports connected to the NPU. +* A Forwarding device must act as a fully functional router that can run routing protocols and other networking services just like single box SONiC devices. +* The system of forwarding devices should be managed by a single central Supervisor SONiC instance (SSI) that also manages the internal fabric that interconnects the forwarding devices. + +## 1.1.2 Intra-System Control Plane + +- Each FSI should be able to connect to other FSIs over the internal fabric in order to be able to run protocols like BGP within the system. + +- This connection must be fate shared with the data path so that a loss of connectivity in the internal fabric is reflected as loss of internal control plane connectivity as well. + +## 1.1.3 Intra-System Management Plane + +Every FSI must have a management interface over which it can reach the supervisor and the rest of the network outside the system. This network must be completely separate from the internal control plane network described above. + +## 1.2 Configuration and Management Requirements + +- Each SONiC instance must be independently configurable and manageable through standard SONiC management interfaces. + +- All ports in the system must be statically provisioned at startup. Any changes to physical port configuration require a restart of the entire system. + +# 2 Design + +## 2.1 Design Assumptions + +In order for the system to function correctly, some state that provides the global view of the system to all the FSIs is necessary. This state is stored in the SSI and all FSIs connect to the SSI over the internal management network to access this state. + +## 2.2 SAI Support + +Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](https://github.com/opencomputeproject/SAI/blob/0dfc6bf390e4ace3fcc59c2ba47e387ff8aa36f4/doc/SAI-Proposal-VoQ-Switch.docx). + +## 2.3 State Sharing + +![](../../images/chassis/architecture.png) + +All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called “Chassis DB”. This instance is accessible over the internal management network. + +FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. + +## 2.3.1 Chassis DB Organization + +The Chassis DB runs in a new container known as ‘docker-database-chassis’ as a separate Redis instance. This ensures both that the Chassis state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. + +## 2.3.2 Config DB Additions + +``` +{ + "DEVICE_METADATA": { + "localhost": { + …. + “chassis_db_address" : "10.8.1.200", + “connect_chassis_db” : “1”, + …. + } + } +``` +Two new attributes are added to the DEVICE_METADATA object in Config DB. These are used to convey to an FSI that a ChassisDB exists in the system. + +## 2.4 Chip Management +There are two kinds of chips that are of interest + +### 2.4.1 NPU + +The NPU (also referred to as switching ASIC in SONiC terminology) performs all the packet reception, forwarding, queueing and transmission functions in the system. + +## 2.4.2 Fabric Chip + +The internal fabric that interconnects forwarding engines is made up of multiple fabric chips that are responsible for moving packets from the source to destination forwarding engine. + +NPUs are connected to fabric chips over internal links that terminate on fabric ports at each end. + +Fabric chips do not play any role in packet forwarding and do not need to be explicitly configured once initialized. All subsequent interactions with fabric chips are for monitoring only. + +Each chip in the system (NPU and Fabric Chip) in the system is given a global ID called a Switch ID. In addition, to support multi-core NPUs each core within a forwarding engine has a Core ID. The combination of (Switch ID, Core ID) must be globally unique across the entire system. + +## 2.5 Port Management + +There are four types of ports that need to be managed + +### 2.5.1 Local Ports + +These are front panel interfaces that are directly attached to each FSI. They are modeled and represented in SONiC exactly as they are with existing fixed configuration devices. + +### 2.5.2 System Ports + +Every port on the system requires a global representation in addition to its existing local representation. This is known as a System Port (AKA sysport). Every system port is assigned an identifier that is globally unique called a system_port_id. In addition, every port is assigned a local port ID within a core called a “Core Port Id”. The scope of the Local Port Id is _within_ a core of a forwarding engine. + +System Ports are modeled in ChassisDB in the SYSTEM_PORT table. + +``` +;Layer2 port representation across a distribute VoQ system +;instance_name is the name of the SONiC instance on the forwarding device on ;which the port is present +key = SYSTEM_PORT|instance_name|ifname +speed = 1*6DIGIT ; port line speed in Mbps +system_port_id = 1*6DIGIT ; globally unique port ID +switch_id = 1*2DIGIT ; global switch ID +core_id = 1*2DIGIT ; core id within switch_id. + ; switch_id+core_id must be globally + ; unique +core_port_id = 1*6DIGIT ; chip specific port +``` + +The globally unique key in the SYSTEM_PORT_TABLE is the name of the FSI instance and the front panel interface name. + +### 2.5.3 Inband Ports + +Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding device local CPU on one side and the internal fabric on the other. + +Every inband port is assigned a System Port Id just like front panel ports which are known to all the forwarding devices. Thus, every inband port is reachable from every forwarding engine. + +All other provisioning and configuration aspects of Inband ports are the same as front panel ports + +### 2.5.4 Fabric Ports + + +The provisioning and management of Fabric ports is outside the scope of this document and will be documented as a separate proposal. + + +## 2.6 Orchestration Agent + + +### System Port Handling + + +System port configuration is expected to completely static and known at the start of the system. + +Based on the state of ‘“connect_chassis_db” in the device metadata in ConfigDB, Orchagent connects to Chassis DB and subscribes to the SYSTEM_PORT table in CHASSIS_DB. It uses this list of system ports from the SYSTEM_PORT table to construct the switch attributes needed by the create_switch SAI API. In a later phase, the system ports could be directly created by making sairedis calls from orchagent. + +A system port can be used in lieu of a physical port in several SAI API calls as relevant. For example, a system port can be added as a vlan member or be a lag member. To account for these, portsorch will be updated to support sysports. + + +Portsyncd does not have to support sysports because sysports do not have any associated kernel devices. + + +# 3 Testing + + +Test coverage for the distributed VoQ architecture is achieved by extending the existing virtual switch based SWSS pytest infrastructure. + + +The distributed switching architecture is represented as multiple VS instances connected with each other and called as Virtual Chassis, where one of the instance plays the role of the SSI and the remaining instances as FSIs. + + +## 3.1 Regression Testing + + +Existing SWSS pytests can be executed against any of the instances in the virtual chassis to ensure that existing SONiC functionality is not affected while operating in a distributed environment. + + +## 3.2 Distributed VoQ functionality + + +Additional tests that specifically validate distributed VoQ forwarding functionality run only in the virtual chassis environment. + + +### 3.2.3 test_virtual_chassis.py + + +Is the top level test driver that executes testcases against the virtual chassis. + + +Sysport handling is tested by test_chassis_sysport which validates that +* System ports can be populated in CHASSIS_DB +* All FSIs can connect to CHASSIS_DB and access sysport state +* Orchagent programs the correct SAI Redis ASIC_DB state to represent the configured sysport. diff --git a/images/chassis/architecture.png b/images/chassis/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..7820d886e2e34943c5ba5c0d2da73c5d4c23aa1e GIT binary patch literal 41796 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 N)ReUzl`2}k{x1_GjqCsb literal 0 HcmV?d00001 From 98194932d5f167849095482d5ced04b181f56dc8 Mon Sep 17 00:00:00 2001 From: Mohanarajan Selvaraj Date: Mon, 1 Jun 2020 01:51:29 -0700 Subject: [PATCH 003/175] SONIC broadcast, unknown-unicast and unknown-multicast (BUM) storm-control HLD --- .../bum_storm_control_hld.md | 133 ++++++++---------- 1 file changed, 60 insertions(+), 73 deletions(-) diff --git a/doc/bum_storm_control/bum_storm_control_hld.md b/doc/bum_storm_control/bum_storm_control_hld.md index e3317cd2dc4..dedae088a25 100644 --- a/doc/bum_storm_control/bum_storm_control_hld.md +++ b/doc/bum_storm_control/bum_storm_control_hld.md @@ -41,7 +41,6 @@ * [3.5.3 Show Commands](#353-show-commands) * [3.5.4 Clear Commands](#354-clear-commands) * [3.5.5 Debug Commands](#355-debug-commands) - * [3.5.6 Rest API Support](#356-rest-api-support) * [4 Flow Diagrams](#4-flow-diagrams) * [4.1 Enable storm control on physical interface](#41-enable-storm-control-on-phy) * [4.2 Disable storm Control on physical interface](#42-disable-storm-control-on-phy) @@ -52,11 +51,10 @@ * [8 Scalability](#8-scalability) * [9 Unit Test](#9-unit-test) * [9.1 CLI Test Cases](#91-cli-test-cases) - * [9.2 REST API Test Cases](#92-rest-api-test-cases) - * [9.3 Functional Test Cases](#93-functional-test-cases) - * [9.4 Scaling Test Cases](#94-scaling-test-cases) - * [9.5 Warm Boot Test Cases](#95-warm-boot-test-cases) - * [9.6 Negative Test Cases](#96-negative-test-cases) + * [9.2 Functional Test Cases](#92-functional-test-cases) + * [9.3 Scaling Test Cases](#93-scaling-test-cases) + * [9.4 Warm Boot Test Cases](#94-warm-boot-test-cases) + * [9.5 Negative Test Cases](#95-negative-test-cases) # List of Tables @@ -87,7 +85,7 @@ This document describes the functionality and high level design of Broadcast, Un # 1 Feature Overview A traffic storm occurs when packets flood the LAN, creating excessive traffic and degrading network performance. The type of traffic can be Broadcast, Unknown-unicast or unknown-Multicast (BUM). -The storm-control feature allows the user to limit the amount of BUM traffic admitted to the system. This can be achieved by configuring the type of storm (Broadcast or Unknown-unicast or unknown-Multicast) and the corresponding bits per second (bps) parameter on a given physical interface. Traffic that exceeds the configured rate will be dropped. +The storm-control feature allows the user to limit the amount of BUM traffic admitted to the system. This can be achieved by configuring the type of storm (Broadcast or Unknown-unicast or unknown-Multicast) and the corresponding kilo bits per second (kbps) parameter on a given physical interface. Traffic that exceeds the configured rate will be dropped. Unknown-multicast traffic consists of all multicast traffic which donot match any of the statically configured or dynamically learned multicast groups. @@ -97,14 +95,13 @@ Unknown-multicast traffic consists of all multicast traffic which donot match an ### 1.1.1 Functional Requirements 1. Support configuration of Broadcast, Unknown-unicast and unknown-Multicast storm-control independently on physical interfaces. - 2. Support threshold rate configuration in bits per second (bps) in the range of 0 bps to 100Gbps. + 2. Support threshold rate configuration in kilo bits per second (kbps) in the range of 0 kbps to 100,000,000 kbps (100Gbps). ### 1.1.2 Configuration and Management Requirements -This feature will support SONiC CLI. +This feature will support Click CLI. 1. Support a CLI to add or delete broadcast, unknown-unicast and unknown-multicast storm-control on a physical interface as described in "Configuration Commands" section below. 2. Support show commands to display the storm-control configuration as described in "Show Commands" section below. 3. Support debug commands as described in "Debug Commands" section below. - 4. Support openconfig REST API and gNMI. ### 1.1.3 Scalability Requirements @@ -146,8 +143,9 @@ Refer to section 1.1 ## 2.3 Limitations BUM storm control -- Configuration is not supported on VLAN and port-channel interfaces. +- Configuration is not supported on VLAN and port-channel interfaces. User can configure on physical port which is part of a VLAN / port-channel. - Statistics is not supported. +- REST, gNMI and Klish CLI are not supported. @@ -161,7 +159,7 @@ BUM storm control __Figure 1: Storm Control High Level Architecture__ 1) Storm-control configurations are parsed and stored in CFG_PORT_STORM_CONTROL_TABLE in Configuration database by the Management Framework. -2) The Policer Orchestration Agent subscribes to notifications from the CFG_PORT_STORM_CONTROL_TABLE and parses the input parameters (interface, storm-control type, bps). A policer_name is created internally by encoding the interface_name and storm_control_type. +2) The Policer Orchestration Agent subscribes to notifications from the CFG_PORT_STORM_CONTROL_TABLE and parses the input parameters (interface, storm-control type, kbps). A policer_name is created internally by encoding the interface_name and storm_control_type. 3) create_policer SAI API is invoked to create a policer with the given input parameters. 4) The identifier of the policer created is associated with the encoded policer_name. 5) The policer identifier is passed to set_port_attribute SAI API to set the appropriate type of storm-control on the port. @@ -181,7 +179,7 @@ A new table CFG_PORT_STORM_CONTROL_TABLE is introduced in the configuration data key = CFG_PORT_STORM_CONTROL_TABLE:port:storm_control_type ; Ethernet Interface Name and storm control type ;field = value enabled = BIT ; Is the storm control enabled (1) or disabled (0) on the interface - bps = 1*13 DIGIT ; CIR value in bits per second + kbps = 1*13 DIGIT ; CIR value in kilo bits per second ### 3.2.2 APP_DB No tables are introduced in APP_DB @@ -223,7 +221,7 @@ The BUM storm-control feature can be enabled on a physical port. The **create_policer** SAI API is used to create the policer based on the policer parameters listed in Table 2. - Meter Type - Can be packets or bytes. Storm-control uses bytes meter type. - Meter Mode - Can be st_tcm or tr_tcm or storm. Storm-control uses storm meter mode. - - CIR (bps) - Value of CIR configured in bps. + - CIR (bps) - Value of CIR given in bps. The **set_port_attribute** SAI API is used to set the policer on an interface. - Unknown-unicast policer - Enables storm-control for unknown-unicast traffic received on the interface. @@ -232,60 +230,64 @@ The **set_port_attribute** SAI API is used to set the policer on an interface. ## 3.5 CLI ### 3.5.1 Data Models -Custom Yang model will be introduced for this feature. +Configuration is supported using Click CLI commands. ### 3.5.2 Configuration Commands BUM storm-control can be configured only on physical interfaces. -**switch# configure terminal**
-**switch(config)# interface Ethernet **
-**switch(config-if)# storm-control {broadcast | unknown-unicast | unknown-multicast} {bps \}** +**switch# config interface storm-control {broadcast | unknown-unicast | unknown-multicast} {add|del} \ {\}** #### 3.5.2.1 Enable Broadcast storm control on a physical interface This command configures broadcast storm-control on a physical interface.
-**switch(config-if)# storm-control broadcast {bps \}** +**switch# config interface storm-control broadcast add \ {\}** #### 3.5.2.1 Enable Unknown-unicast storm control on a physical interface This command configures unknown-unicast storm-control on a physical interface.
-**switch(config-if)# storm-control unknown-unicast {bps \}** +**switch# config interface storm-control unknown-unicast add \ {\}** #### 3.5.2.1 Enable Multicast storm control on a physical interface This command configures unknown-multicast storm-control on physical interface.
-**switch(config-if)# storm-control unknown-multicast {bps \}** +**switch# config interface storm-control unknown-multicast add \ {\}** ### 3.5.3 Show Commands The following show command displays storm-control configurations. -**show storm-control [interface \]** +**show storm-control {all | interface \}** Following is a sample output -**show storm-control**
+**show storm-control all**
###### Table 3: show storm-control -| Interface | Type | Rate(bps) | -|-----------|------------------|-----------| -| Ethernet0 | broadcast | 1000000 | -| Ethernet0 | unknown-unicast | 2000000 | -| Ethernet2 | unknown-unicast | 5000000 | ++------------------+-----------------+---------------+ +| Interface Name | Storm Type | Rate (kbps) | ++==================+=================+===============+ +| Ethernet0 | broadcast | 1000 | ++------------------+-----------------+---------------+ +| Ethernet0 | unknown-unicast | 2000 | ++------------------+-----------------+---------------+ +| Ethernet2 | unknown-unicast | 5000 | ++------------------+-----------------+---------------+ + **show storm-control interface Ethernet2**
###### Table 4: show storm-control interface -| Interface | Type | Rate(bps) | -|-----------|------------------|-----------| -| Ethernet2 | unknown-unicast | 5000000 | - ++------------------+-----------------+---------------+ +| Interface Name | Storm Type | Rate (kbps) | ++==================+=================+===============+ +| Ethernet2 | unknown-unicast | 5000 | ++------------------+-----------------+---------------+ + + ### 3.5.4 Clear Commands Not applicable ### 3.5.5 Debug Commands Not applicable -### 3.5.6 REST API Support -REST SET and GET APIs will be supported. # 4 Flow Diagrams ## 4.1 Enable storm control on physical interface @@ -353,59 +355,44 @@ Storm-control is a physical port parameter. Testing would be done by enabling st 8. Verify that the BUM storm-control configurations are correctly re-applied after cold reboot. 9. Verify that all the three storm-control types can be configured and rate limiting is applied independently on the three types of traffic received at the interface. - 10. Verify that the bps value configured is independent per interface. + 10. Verify that the kbps value configured is independent per interface. 11. When user configures BUM storm-control on interface where the same type is already configured, - verify that if bps value is different, the new bps value is updated to the CONFIG_DB. + verify that if kbps value is different, the new kbps value is updated to the CONFIG_DB. -## 9.2 Rest API Test Cases - 12. Verify broadcast, unknown-multicast and unknown-unicast can be configured on interface using REST. - 13. Verify broadcast, unknown-multicast and unknown-unicast can be unconfigured on interface using REST. - - -## 9.3 Functional Test Cases - 14. Verify that broadcast traffic gets rate-limited as per broadcast storm-control policer parameters. - 15. Verify that unknown-unicast traffic gets rate-limited as per unknown-unicast storm-control policer parameters. - 16. Verify that multicast traffic gets rate-limited as per multicast storm-control policer parameters. - 17. Configure all three BUM storm-control on interface and verify that the rate-limiting of traffic is as per the +## 9.2 Functional Test Cases + 12. Verify that broadcast traffic gets rate-limited as per broadcast storm-control policer parameters. + 13. Verify that unknown-unicast traffic gets rate-limited as per unknown-unicast storm-control policer parameters. + 14. Verify that multicast traffic gets rate-limited as per multicast storm-control policer parameters. + 15. Configure all three BUM storm-control on interface and verify that the rate-limiting of traffic is as per the respective policer parameters. - 18. Verify that other traffic streams are unaffected by BUM storm-control configuration. - 19. Verify that after unconfiguring BUM storm-control configuration on interface, BUM storm traffic rate is no + 16. Verify that other traffic streams are unaffected by BUM storm-control configuration. + 17. Verify that after unconfiguring BUM storm-control configuration on interface, BUM storm traffic rate is no more rate limited. - 20. Verify that traffic is rate-limited as per the updated value of bps when user updates existing + 18. Verify that traffic is rate-limited as per the updated value of kbps when user updates existing BUM storm-control configuration on interface. -## 9.4 Scaling Test Cases - 21. Configure BUM storm-control on all the physical interfaces on the system and check that rate-limiting is +## 9.3 Scaling Test Cases + 19. Configure BUM storm-control on all the physical interfaces on the system and check that rate-limiting is performed on all interfaces. -## 9.5 Warm Boot Test Cases - 22. Verify that BUM storm-control configurations are restored after warm boot. - 23. Verify that BUM storm rate-limiting continues to work at the specific rate across warm boot. - 24. Verify that BUM storm-control is only active on interfaces that previously had storm-control configurations +## 9.4 Warm Boot Test Cases + 20. Verify that BUM storm-control configurations are restored after warm boot. + 21. Verify that BUM storm rate-limiting continues to work at the specific rate across warm boot. + 22. Verify that BUM storm-control is only active on interfaces that previously had storm-control configurations before warm boot. -## 9.6 Negative Test Cases - 25. Verify that storm-control configuration errors out when applied on port-channel or vlan interfaces. - 26. Verify that error is returned when the same configuration is repeated on the interface. - 27. Configure BUM storm-control on interface without providing bps value and check that configuration is +## 9.5 Negative Test Cases + 23. Verify that storm-control configuration errors out when applied on port-channel or vlan interfaces. + 24. Verify that error is returned when the same configuration is repeated on the interface. + 25. Configure BUM storm-control on interface without providing kbps value and check that configuration is not accepted. - 28. Unconfigure BUM storm-control on interface by providing bps as input and check that + 26. Unconfigure BUM storm-control on interface by providing kbps as input and check that additional / invalid parameter error is displayed. - 29. Verify that invalid parameter error is displayed when value of bps is out of range or invalid. - 30. Verify that invalid parameter / input error is displayed when invalid input is provided for storm-control type. - - - + 27. Verify that invalid parameter error is displayed when value of kbps is out of range or invalid. + 28. Verify that invalid parameter / input error is displayed when invalid input is provided for storm-control type. + From 84599875eb835c4128fa82c582102f2f364d71f4 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Tue, 23 Jun 2020 16:24:25 -0700 Subject: [PATCH 004/175] Updates after review meeting dated Jun-18 2020 NPU to be replaced by ASIC/Multi-ASIC for consistency throughout the document [AI: Kartik/Arista] => document updated to use ASIC instead of NPU Section 1.2: Config & Management Requirements Rephrase second bullet to reflect port configuration is static i.e physical wiring only => Wording clarified as requqested Add context in the document for dynamic port changes [AI: Kartik/Arista] => Section outlining dynamic system port support added in "Future Work" section Section 2.3: State Sharing Update image separate Syncd, swss, DB container per fabric chip [AI: Kartik/Arista] => diagram updated to show multiple syncd, one per fabric chip Section 2.4: Chip Management Update section 2.4.2 to clarify switch ID numbering scheme in the system with reference from SAI specs. [AI: Kartik/Arista] => Section updated to reflect the correct numbering scheme with reference to the VOQ SAI spec. Section 2.5: Port Management Section 2.5.2 update system port table schema [AI: Kartik/Arista] => Updated to reflect proper instance naming as below Section 2.5.3 Update inband port to be explicitly provisioned [AI: Kartik/Arista] => wording around inband port is clarified. Require more clarity what is meant by instance - if LC has two ASICs then what will instance scope mean - swss/CPU instance? Is there is 1:1 mapping between instance to ASIC? [AI: Kartik/Arista] => Added new instance naming section describing naming scheme for both the FSI and an ASIC --- doc/chassis/system-ports.md | 121 ++++++++++++++++++++------------ images/chassis/architecture.png | Bin 41796 -> 44202 bytes 2 files changed, 75 insertions(+), 46 deletions(-) diff --git a/doc/chassis/system-ports.md b/doc/chassis/system-ports.md index 695f21c90ce..caf1ce728f6 100644 --- a/doc/chassis/system-ports.md +++ b/doc/chassis/system-ports.md @@ -23,7 +23,8 @@ ###### Revision | Rev | Date | Author | Change Description | |:---:|:-----------:|:------------------:|--------------------| -| 0.1 | May-19 2020 | Kartik Chandran (Arista Networks) | Initial Version | +| 0.1 | May-19 2020 | Kartik Chandran (Arista Networks) | Initial Version | +| 0.2 | June-22 2020 | Kartik Chandran (Arista Networks) | First set of review comments from public review | # About this Manual @@ -56,26 +57,24 @@ However, this architecture makes no hard assumptions about operating within a ch | FSI | Forwarding SONiC Instance | SONiC instance on a packet forwarding module like a linecard. | SSI | Supervisor SONiC Instance | SONiC instance on a central supervisor module that controls a cluster of forwarding instances and the interconnection fabric. | Forwarding Device | A unit of hardware that runs SONiC and is responsible for packet forwarding | -| NPU | Network Processing Unit | A component on a forwarding device that performs the packet forwarding function +| ASIC | Application Specific Integrated Circuit | Refers to the forwarding engine on a device that is responsible for packet forwarding. Also referred to as NPU # 1 Requirements - # 1.1 Functional Requirements - ## 1.1.1 Distributed Operation -* Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more NPUs on the device, including the front panel and internal fabric ports connected to the NPU. +* Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more ASICs on the device, including the front panel and internal fabric ports conn ected to the ASICs. * A Forwarding device must act as a fully functional router that can run routing protocols and other networking services just like single box SONiC devices. * The system of forwarding devices should be managed by a single central Supervisor SONiC instance (SSI) that also manages the internal fabric that interconnects the forwarding devices. ## 1.1.2 Intra-System Control Plane -- Each FSI should be able to connect to other FSIs over the internal fabric in order to be able to run protocols like BGP within the system. +* Each FSI should be able to connect to other FSIs over the internal fabric in order to be able to run protocols like BGP within the system. -- This connection must be fate shared with the data path so that a loss of connectivity in the internal fabric is reflected as loss of internal control plane connectivity as well. +* This connection must be fate shared with the data path so that a loss of connectivity in the internal fabric is reflected as loss of internal control plane connectivity as well. ## 1.1.3 Intra-System Management Plane @@ -83,9 +82,13 @@ Every FSI must have a management interface over which it can reach the superviso ## 1.2 Configuration and Management Requirements -- Each SONiC instance must be independently configurable and manageable through standard SONiC management interfaces. +* Each SONiC instance must be independently configurable and manageable through standard SONiC management interfaces. -- All ports in the system must be statically provisioned at startup. Any changes to physical port configuration require a restart of the entire system. +* The physical configuration of the entire system is fixed at startup. This includes + * The Hardware SKU that is used for each forwarding device + * The Physical port organization of the entire system + +* Live replacement of forwarding devices or pluggable modules like transceivers must be supported as long as the part being replaced is an identical SKU. # 2 Design @@ -95,7 +98,7 @@ In order for the system to function correctly, some state that provides the glob ## 2.2 SAI Support -Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](https://github.com/opencomputeproject/SAI/blob/0dfc6bf390e4ace3fcc59c2ba47e387ff8aa36f4/doc/SAI-Proposal-VoQ-Switch.docx). +Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](https://github.com/opencomputeproject/SAI/blob/master/doc/VoQ/SAI-Proposal-VoQ-Switch.md) ## 2.3 State Sharing @@ -124,32 +127,51 @@ The Chassis DB runs in a new container known as ‘docker-database-chassis’ as ``` Two new attributes are added to the DEVICE_METADATA object in Config DB. These are used to convey to an FSI that a ChassisDB exists in the system. + ## 2.4 Chip Management There are two kinds of chips that are of interest -### 2.4.1 NPU +### 2.4.1 Forwarding ASIC -The NPU (also referred to as switching ASIC in SONiC terminology) performs all the packet reception, forwarding, queueing and transmission functions in the system. +The ASIC (also referred to as NPU in SONiC terminology) performs all the packet reception, forwarding, queueing and transmission functions in the system. -## 2.4.2 Fabric Chip +### 2.4.2 Fabric Chip The internal fabric that interconnects forwarding engines is made up of multiple fabric chips that are responsible for moving packets from the source to destination forwarding engine. -NPUs are connected to fabric chips over internal links that terminate on fabric ports at each end. +ASICs are connected to fabric chips over internal links that terminate on fabric ports at each end. + +Fabric chips do not play any role in packet forwarding and do not need to be explicitly configured once initialized. All subsequent interactions with fabric chips are for monitoring only. + +All chips are managed based on the existing Multi-ASIC paradigm in SONiC, in which there is one instance of syncd (and SAI), swss and other related agents per chip. + +### 2.4.3 Switch Numbering + +* Each chip in the system (ASIC and Fabric Chip) in the system is given a global ID called a Switch ID. +* Each chip consumes C consecutive switch IDs, where C is the number of switching cores. +* Each core on a chip has a core ID between 0 and C. + +Please see the SAI VoQ spec for more detailed examples. + +## 2.5 SONiC Instance and ASIC Naming -Fabric chips do not play any role in packet forwarding and do not need to be explicitly configured once initialized. All subsequent interactions with fabric chips are for monitoring only. +### Forwarding SONiC Instance -Each chip in the system (NPU and Fabric Chip) in the system is given a global ID called a Switch ID. In addition, to support multi-core NPUs each core within a forwarding engine has a Core ID. The combination of (Switch ID, Core ID) must be globally unique across the entire system. +Each FSI has a globally unique name that represents that SONiC instance. In a modular chassis, the name would conventionally be "Lineard-N", where N is the slot in which the linecard is inserted. -## 2.5 Port Management +### ASIC Name + +In addition, each ASIC has a globally unique name which would conventionally be "Linecard-N.K", where K is a slot local identifier of the ASIC. + +## 2.6 Port Management There are four types of ports that need to be managed -### 2.5.1 Local Ports +### 2.6.1 Local Ports These are front panel interfaces that are directly attached to each FSI. They are modeled and represented in SONiC exactly as they are with existing fixed configuration devices. -### 2.5.2 System Ports +### 2.6.2 System Ports Every port on the system requires a global representation in addition to its existing local representation. This is known as a System Port (AKA sysport). Every system port is assigned an identifier that is globally unique called a system_port_id. In addition, every port is assigned a local port ID within a core called a “Core Port Id”. The scope of the Local Port Id is _within_ a core of a forwarding engine. @@ -157,38 +179,32 @@ System Ports are modeled in ChassisDB in the SYSTEM_PORT table. ``` ;Layer2 port representation across a distribute VoQ system -;instance_name is the name of the SONiC instance on the forwarding device on ;which the port is present -key = SYSTEM_PORT|instance_name|ifname +;instance_name is the globally unique name on the forwarding device on ;which the port is present +key = SYSTEM_PORT|asic_name|ifname ; speed = 1*6DIGIT ; port line speed in Mbps system_port_id = 1*6DIGIT ; globally unique port ID -switch_id = 1*2DIGIT ; global switch ID +switch_id = 1*2DIGIT ; global switch ID. core_id = 1*2DIGIT ; core id within switch_id. - ; switch_id+core_id must be globally - ; unique core_port_id = 1*6DIGIT ; chip specific port ``` -The globally unique key in the SYSTEM_PORT_TABLE is the name of the FSI instance and the front panel interface name. +The globally unique key in the SYSTEM_PORT_TABLE is the name of the ASIC instance and the front panel interface name. The ASIC name is chosen so that various agents like syncd can use this name as a filtering criterion to select the subset of entities that they need to operate on in order to manage a specific ASIC. -### 2.5.3 Inband Ports +The only restriction on selecting the ifname is that the key "SYSTEM_PORT|asic_name|ifname" must uniquely identify a port on the system. -Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding device local CPU on one side and the internal fabric on the other. +### 2.6.3 Inband Ports -Every inband port is assigned a System Port Id just like front panel ports which are known to all the forwarding devices. Thus, every inband port is reachable from every forwarding engine. - -All other provisioning and configuration aspects of Inband ports are the same as front panel ports +Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding device local CPU on one side and the internal fabric on the other. -### 2.5.4 Fabric Ports +Every inband port is assigned a System Port ID just like front panel ports which is known to all the forwarding devices. Thus, every inband port is reachable from every forwarding engine. +### 2.6.4 Fabric Ports The provisioning and management of Fabric ports is outside the scope of this document and will be documented as a separate proposal. +## 2.7 Orchestration Agent -## 2.6 Orchestration Agent - - -### System Port Handling - +### 2.7.1 System Port Handling System port configuration is expected to completely static and known at the start of the system. @@ -199,35 +215,48 @@ A system port can be used in lieu of a physical port in several SAI API calls as Portsyncd does not have to support sysports because sysports do not have any associated kernel devices. - # 3 Testing - Test coverage for the distributed VoQ architecture is achieved by extending the existing virtual switch based SWSS pytest infrastructure. - The distributed switching architecture is represented as multiple VS instances connected with each other and called as Virtual Chassis, where one of the instance plays the role of the SSI and the remaining instances as FSIs. - ## 3.1 Regression Testing - Existing SWSS pytests can be executed against any of the instances in the virtual chassis to ensure that existing SONiC functionality is not affected while operating in a distributed environment. - ## 3.2 Distributed VoQ functionality - Additional tests that specifically validate distributed VoQ forwarding functionality run only in the virtual chassis environment. - ### 3.2.3 test_virtual_chassis.py - Is the top level test driver that executes testcases against the virtual chassis. - Sysport handling is tested by test_chassis_sysport which validates that * System ports can be populated in CHASSIS_DB * All FSIs can connect to CHASSIS_DB and access sysport state * Orchagent programs the correct SAI Redis ASIC_DB state to represent the configured sysport. + +# 4 Future Work + +## Dynamic System Ports + +Dynamic system port support is required to support the following forwarding scenarios + +* Addition of a new forwarding device into an existing running system +* Replacing a forwarding device with another device of a different hardware SKU (such as replacing a linecard with a new linecard of a different SKU in a chassis slot). + +Both these scenarios can be supported smoothly as long as the global system port numbering scheme is maintained and the modifications to system ports can be performed without impacting the System Port IDs of the running system. + +Support for dynamic system ports requires SAI support for the `create_port` and `remove_port` calls. + +### Overview of PortsOrch changes + + * Subscribe to the SYSTEM_PORT table in PortsOrch + * React to changes in the SYSTEM_PORT table + * Make the appropriate `create_port` and `remove_port` calls. + +In addition, forwarding features that are dependent on System Ports need to react to these changes and reprogram the related forwarding plane state such as routing nexthops, LAG membership etc. + + diff --git a/images/chassis/architecture.png b/images/chassis/architecture.png index 7820d886e2e34943c5ba5c0d2da73c5d4c23aa1e..bafcb49a072429e641ebda77edce7e3ad71fa407 100644 GIT binary patch literal 44202 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 z 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 literal 41796 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
<7wdblK$H&L&8nX_zwiEci@CyOo74!hJ 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 N)ReUzl`2}k{x1_GjqCsb From ddf468a0661eeb595b8f1b453baa834fd92c040d Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Fri, 26 Jun 2020 10:57:47 -0700 Subject: [PATCH 005/175] Second set of edits from review at VOQ working group. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ifname must be unique per FSI. If we decide to create kernel devices for system ports, ifname may have to be globally unique. AI (Kartik/Arista): Amend wording in the document => amended wording in the document Any existing swss test can be run in the virtual chassis mode - except for LAG tests which aren’t compatible . AI (Kartik/Arista) - Clarify the conditions under which existing tests can be run unchanged. => clarified How would dual supervisor scenario work? What considerations do we have for two SSIs? (Danny/Microsoft) AI (Kartik/Arista) - add a summary in Future work section. => added a new dual supervisor section in Future work and summarized some high level approaches --- doc/chassis/system-ports.md | 46 +++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/doc/chassis/system-ports.md b/doc/chassis/system-ports.md index caf1ce728f6..fbb967cd39f 100644 --- a/doc/chassis/system-ports.md +++ b/doc/chassis/system-ports.md @@ -24,7 +24,8 @@ | Rev | Date | Author | Change Description | |:---:|:-----------:|:------------------:|--------------------| | 0.1 | May-19 2020 | Kartik Chandran (Arista Networks) | Initial Version | -| 0.2 | June-22 2020 | Kartik Chandran (Arista Networks) | First set of review comments from public review | +| 0.2 | June-22 2020 | Kartik Chandran (Arista Networks) | First set of review comments from public review | +| 1.0 | June-26 2020 | Kartik Chandran (Arista Networks) | Final set of review comments from public review | # About this Manual @@ -57,7 +58,8 @@ However, this architecture makes no hard assumptions about operating within a ch | FSI | Forwarding SONiC Instance | SONiC instance on a packet forwarding module like a linecard. | SSI | Supervisor SONiC Instance | SONiC instance on a central supervisor module that controls a cluster of forwarding instances and the interconnection fabric. | Forwarding Device | A unit of hardware that runs SONiC and is responsible for packet forwarding | -| ASIC | Application Specific Integrated Circuit | Refers to the forwarding engine on a device that is responsible for packet forwarding. Also referred to as NPU +| ASIC | Application Specific Integrated Circuit | Refers to the forwarding engine on a device that is responsible for packet forwarding. +| NPU | Network Processing Unit | An alternate term for ASIC often used in SONiC vocabulary # 1 Requirements @@ -157,7 +159,7 @@ Please see the SAI VoQ spec for more detailed examples. ### Forwarding SONiC Instance -Each FSI has a globally unique name that represents that SONiC instance. In a modular chassis, the name would conventionally be "Lineard-N", where N is the slot in which the linecard is inserted. +Each FSI has a globally unique name that represents that SONiC instance. In a modular chassis, the name would conventionally be "Linecard-N", where N is the slot in which the linecard is inserted. ### ASIC Name @@ -190,7 +192,7 @@ core_port_id = 1*6DIGIT ; chip specific port The globally unique key in the SYSTEM_PORT_TABLE is the name of the ASIC instance and the front panel interface name. The ASIC name is chosen so that various agents like syncd can use this name as a filtering criterion to select the subset of entities that they need to operate on in order to manage a specific ASIC. -The only restriction on selecting the ifname is that the key "SYSTEM_PORT|asic_name|ifname" must uniquely identify a port on the system. +The ifname is expected to be unique within a SONiC instance. As a result, the key "SYSTEM_PORT|asic_name|ifname" uniquely identifies a system port in the system. ### 2.6.3 Inband Ports @@ -206,13 +208,12 @@ The provisioning and management of Fabric ports is outside the scope of this doc ### 2.7.1 System Port Handling -System port configuration is expected to completely static and known at the start of the system. +System port configuration is expected to be completely static and known at the start of the system. Based on the state of ‘“connect_chassis_db” in the device metadata in ConfigDB, Orchagent connects to Chassis DB and subscribes to the SYSTEM_PORT table in CHASSIS_DB. It uses this list of system ports from the SYSTEM_PORT table to construct the switch attributes needed by the create_switch SAI API. In a later phase, the system ports could be directly created by making sairedis calls from orchagent. A system port can be used in lieu of a physical port in several SAI API calls as relevant. For example, a system port can be added as a vlan member or be a lag member. To account for these, portsorch will be updated to support sysports. - Portsyncd does not have to support sysports because sysports do not have any associated kernel devices. # 3 Testing @@ -240,7 +241,7 @@ Sysport handling is tested by test_chassis_sysport which validates that # 4 Future Work -## Dynamic System Ports +## 4.1 Dynamic System Ports Dynamic system port support is required to support the following forwarding scenarios @@ -259,4 +260,35 @@ Support for dynamic system ports requires SAI support for the `create_port` and In addition, forwarding features that are dependent on System Ports need to react to these changes and reprogram the related forwarding plane state such as routing nexthops, LAG membership etc. +## 4.2 Dual Supervisor Support + +Dual supervisor modules are a common feature in chassis based systems where one supervisor acts as the active and the other as a standby. The presence of the standby supervisor allows the system +to continue functioning without manual intervention in case of a hard failure (such as a hardware failure) on the active supervisor by transferring control to the standby. + +The standby supervisor has its own console, internal and external management IP address. + +There are typically two forms of redundancy + +### Warm Standby + +In this mode, the standby supervisor has booted into the OS and is waiting to take over. No configuration or operational status is known. When a switchover occurs, the processing is very similar to what happens after a fresh boot of a supervisor. + +Warm standby can be supported in SWSS as follows + +- Gracefully handle the loss of connectivity to the SSI and terminate OrchAgent, syncd and all related containers +- Process device configuration and populate standby Chassis DB with static information +- Modify the ChassisDB address in DEVICE_META +- Start all the containers which will now connect to the standby Chassis DB and continue operation. + +### Hot Standby + +In the hot standby mode, the standby supervisor has the control plane running in standby mode, such that it can take over with minimal (or no) disruption to forwarding device. + +At a high level, hot standby mode requires +- Starting Chassis DB on standby SSI in standby mode where it mirrors the Chassis DB. +- Live sync of Chassis DB state between active and standby Chassis DB. +- Graceful handling in OrchAgent of loss of connectivity to SSI and continuing to operate autonomously. +- Reconnecting to Chassis DB when Standby SSI is ready. +- Reconciling relevant Chassis DB state with SAI Asic DB state and modifying SAI state as appropriate to be in sync with Chassis DB. + From 88a798ac9044e8dcc0033328bbefb53f2875fce0 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Wed, 5 Aug 2020 23:11:57 -0700 Subject: [PATCH 006/175] Changes for Rev 2.0 of the document - Clarifications on DB structure and naming - Cleaning up redundant sections that are expected to be covered in other docs --- .../{system-ports.md => architecture.md} | 121 +++++++++--------- images/chassis/architecture.png | Bin 44202 -> 56364 bytes 2 files changed, 57 insertions(+), 64 deletions(-) rename doc/chassis/{system-ports.md => architecture.md} (72%) diff --git a/doc/chassis/system-ports.md b/doc/chassis/architecture.md similarity index 72% rename from doc/chassis/system-ports.md rename to doc/chassis/architecture.md index fbb967cd39f..6542ba0aeed 100644 --- a/doc/chassis/system-ports.md +++ b/doc/chassis/architecture.md @@ -1,7 +1,7 @@ # Distributed Forwarding in a Virtual Output Queue (VOQ) Architecture # High Level Design Document -#### Rev 0.1 +#### Rev 2.0 # Table of Contents * [List of Tables](#list-of-tables) @@ -25,7 +25,8 @@ |:---:|:-----------:|:------------------:|--------------------| | 0.1 | May-19 2020 | Kartik Chandran (Arista Networks) | Initial Version | | 0.2 | June-22 2020 | Kartik Chandran (Arista Networks) | First set of review comments from public review | -| 1.0 | June-26 2020 | Kartik Chandran (Arista Networks) | Final set of review comments from public review | +| 1.0 | June-26 2020 | Kartik Chandran (Arista Networks) | Final set of review comments from public review | +| 2.0 | Aug-5 2020 | Kartik Chandran (Arista Networks) | Revisions after further community review including description of global DB structure, removing sections on system ports, testing and future work to be covered in other documents | # About this Manual @@ -68,7 +69,8 @@ However, this architecture makes no hard assumptions about operating within a ch ## 1.1.1 Distributed Operation -* Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more ASICs on the device, including the front panel and internal fabric ports conn ected to the ASICs. +Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more ASICs on the device, including the front panel and internal fabric ports conn ected to the ASICs. + * A Forwarding device must act as a fully functional router that can run routing protocols and other networking services just like single box SONiC devices. * The system of forwarding devices should be managed by a single central Supervisor SONiC instance (SSI) that also manages the internal fabric that interconnects the forwarding devices. @@ -106,28 +108,68 @@ Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](http ![](../../images/chassis/architecture.png) -All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called “Chassis DB”. This instance is accessible over the internal management network. +All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called “Global DB”. This instance is accessible over the internal management network. FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. + + +## 2.3.1 Global DB Organization -FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. +The Global DB runs in a new container known as ‘docker-database-global’ as a separate Redis instance. This ensures both that the Global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. -## 2.3.1 Chassis DB Organization +Multiple databases can be instantiated inside the Global DB analogous to the existing CONFIG_DB, STATE_DB structure in SONiC Today. However, at this time the expectation is that _all_ static configuration including globally applicable conifguration is stored in the FSI CONFIG_DB and only operational application state that needs to be shared between FSIs is stored in the Global DB instance. Accordingly, there is a single DB within the Global DB instance called "GLOBAL_APP_DB" to clearly mark the difference between this DB and the local APP_DB which is accessed by OrchAgent. -The Chassis DB runs in a new container known as ‘docker-database-chassis’ as a separate Redis instance. This ensures both that the Chassis state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. +A new systemd service `config-globaldb` starts the docker-database-global container in the SSI. In the FSI, the config-globaldb service reads the contents of default_config.json and populate /etc/hosts with the IP address for the “redis_chassis.server” host. -## 2.3.2 Config DB Additions +The server name “redis_chassis.server” is used in database_config.json to describe the reachability of the redis_chassis redis instance. + +**database_config.json** +``` + "redis_global":{ + "hostname" : "redis_global.server", + "port": 6385, + "unix_socket_path": "/var/run/redis-chassis/redis_global.sock", + "unix_socket_perm" : 777 + } + + "GLOBAL_APP_DB" : { + "id" : 8, + "separator": "|", + "instance" : "redis_global" + } +``` + +The following information is present in default_config.json, which is loaded into CONFIG_DB ``` -{ + "DEVICE_METADATA": { + "localhost": { + “global_db_address" : , + “start_global_db” : “1”, + } + } + +``` + +This indicates to the SSI that the Global DB instance is to be started. + +## 2.3.2 FSI CONFIG_DB Additions + +Two new attributes are added to the DEVICE_METADATA object in Config DB. These are used to convey to an FSI that a Global DB exists in the system. +``` "DEVICE_METADATA": { "localhost": { …. - “chassis_db_address" : "10.8.1.200", - “connect_chassis_db” : “1”, + “global_db_address" : "10.8.1.200", + “connect_to_global_db” : “1”, …. } } ``` -Two new attributes are added to the DEVICE_METADATA object in Config DB. These are used to convey to an FSI that a ChassisDB exists in the system. + +The `connect_to_global_db` flag is distinct from the `start_global_db` flag to signal which instance owns the DB and which instance is supposted to connect to it. + +### 2.3.4 DB Connectivity + +The platform implementation is responsible for providing IP connectivity to the redis_global.server throughout the chassis. For example, this IP address could be in a 127.1/16 subnet so that the traffic is limited to staying within the system. The exact mechanisms for this IP connectivity is considered implementation specific and outside the scope of this document. ## 2.4 Chip Management @@ -177,23 +219,6 @@ These are front panel interfaces that are directly attached to each FSI. They ar Every port on the system requires a global representation in addition to its existing local representation. This is known as a System Port (AKA sysport). Every system port is assigned an identifier that is globally unique called a system_port_id. In addition, every port is assigned a local port ID within a core called a “Core Port Id”. The scope of the Local Port Id is _within_ a core of a forwarding engine. -System Ports are modeled in ChassisDB in the SYSTEM_PORT table. - -``` -;Layer2 port representation across a distribute VoQ system -;instance_name is the globally unique name on the forwarding device on ;which the port is present -key = SYSTEM_PORT|asic_name|ifname ; -speed = 1*6DIGIT ; port line speed in Mbps -system_port_id = 1*6DIGIT ; globally unique port ID -switch_id = 1*2DIGIT ; global switch ID. -core_id = 1*2DIGIT ; core id within switch_id. -core_port_id = 1*6DIGIT ; chip specific port -``` - -The globally unique key in the SYSTEM_PORT_TABLE is the name of the ASIC instance and the front panel interface name. The ASIC name is chosen so that various agents like syncd can use this name as a filtering criterion to select the subset of entities that they need to operate on in order to manage a specific ASIC. - -The ifname is expected to be unique within a SONiC instance. As a result, the key "SYSTEM_PORT|asic_name|ifname" uniquely identifies a system port in the system. - ### 2.6.3 Inband Ports Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding device local CPU on one side and the internal fabric on the other. @@ -204,40 +229,16 @@ Every inband port is assigned a System Port ID just like front panel ports which The provisioning and management of Fabric ports is outside the scope of this document and will be documented as a separate proposal. -## 2.7 Orchestration Agent - -### 2.7.1 System Port Handling - -System port configuration is expected to be completely static and known at the start of the system. -Based on the state of ‘“connect_chassis_db” in the device metadata in ConfigDB, Orchagent connects to Chassis DB and subscribes to the SYSTEM_PORT table in CHASSIS_DB. It uses this list of system ports from the SYSTEM_PORT table to construct the switch attributes needed by the create_switch SAI API. In a later phase, the system ports could be directly created by making sairedis calls from orchagent. - -A system port can be used in lieu of a physical port in several SAI API calls as relevant. For example, a system port can be added as a vlan member or be a lag member. To account for these, portsorch will be updated to support sysports. - -Portsyncd does not have to support sysports because sysports do not have any associated kernel devices. +The details regarding the schemas, Orch agent logic changes and flows are described in more specific documents # 3 Testing Test coverage for the distributed VoQ architecture is achieved by extending the existing virtual switch based SWSS pytest infrastructure. -The distributed switching architecture is represented as multiple VS instances connected with each other and called as Virtual Chassis, where one of the instance plays the role of the SSI and the remaining instances as FSIs. - -## 3.1 Regression Testing - -Existing SWSS pytests can be executed against any of the instances in the virtual chassis to ensure that existing SONiC functionality is not affected while operating in a distributed environment. - -## 3.2 Distributed VoQ functionality - -Additional tests that specifically validate distributed VoQ forwarding functionality run only in the virtual chassis environment. +The distributed switching architecture is represented as multiple VS instances connected with each other and called as Virtual Chassis, where one of the instance plays the role of the SSI and the remaining instances as FSIs. Existing SWSS pytests can be executed against any of the instances in the virtual chassis to ensure that existing SONiC functionality is not affected while operating in a distributed environment. -### 3.2.3 test_virtual_chassis.py - -Is the top level test driver that executes testcases against the virtual chassis. - -Sysport handling is tested by test_chassis_sysport which validates that -* System ports can be populated in CHASSIS_DB -* All FSIs can connect to CHASSIS_DB and access sysport state -* Orchagent programs the correct SAI Redis ASIC_DB state to represent the configured sysport. +More detailed test cases are covered in other HLDs. # 4 Future Work @@ -252,14 +253,6 @@ Both these scenarios can be supported smoothly as long as the global system port Support for dynamic system ports requires SAI support for the `create_port` and `remove_port` calls. -### Overview of PortsOrch changes - - * Subscribe to the SYSTEM_PORT table in PortsOrch - * React to changes in the SYSTEM_PORT table - * Make the appropriate `create_port` and `remove_port` calls. - -In addition, forwarding features that are dependent on System Ports need to react to these changes and reprogram the related forwarding plane state such as routing nexthops, LAG membership etc. - ## 4.2 Dual Supervisor Support Dual supervisor modules are a common feature in chassis based systems where one supervisor acts as the active and the other as a standby. The presence of the standby supervisor allows the system diff --git a/images/chassis/architecture.png b/images/chassis/architecture.png index bafcb49a072429e641ebda77edce7e3ad71fa407..cdf9b75be51387db11fa60b95e12ec873737163b 100644 GIT binary patch literal 56364 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 AV*mgE literal 44202 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 z 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 From 90c1289eaf89a70939e7c81e042e261947c6a850 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Fri, 7 Aug 2020 18:31:59 -0700 Subject: [PATCH 007/175] More edits after community review - Clarification of terminology - Renamed Chassis DB to Global DB - Revised the Global DB configuration structure - Added a failure handling section --- doc/chassis/architecture.md | 132 ++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/doc/chassis/architecture.md b/doc/chassis/architecture.md index 6542ba0aeed..b37b70ccbf5 100644 --- a/doc/chassis/architecture.md +++ b/doc/chassis/architecture.md @@ -56,11 +56,11 @@ However, this architecture makes no hard assumptions about operating within a ch | | | | |------|--------------------|--------------------------------| -| FSI | Forwarding SONiC Instance | SONiC instance on a packet forwarding module like a linecard. -| SSI | Supervisor SONiC Instance | SONiC instance on a central supervisor module that controls a cluster of forwarding instances and the interconnection fabric. -| Forwarding Device | A unit of hardware that runs SONiC and is responsible for packet forwarding | | ASIC | Application Specific Integrated Circuit | Refers to the forwarding engine on a device that is responsible for packet forwarding. -| NPU | Network Processing Unit | An alternate term for ASIC often used in SONiC vocabulary +| NPU | Network Processing Unit | An alternate term for ASIC often used in SONiC vocabulary +| Forwarding Module | A unit of hardware that runs one instance of the SONiC OS and is responsible for packet forwarding | +| FSI | Forwarding SONiC Instance | SONiC OS instance on a forwarding module like a linecard. An FSI controls one more ASICs that are present on the forwarding module +| SSI | Supervisor SONiC Instance | SONiC OS instance on a central supervisor module that controls a cluster of forwarding instances and the interconnection fabric. # 1 Requirements @@ -69,10 +69,10 @@ However, this architecture makes no hard assumptions about operating within a ch ## 1.1.1 Distributed Operation -Each forwarding device must run an independent SONiC instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more ASICs on the device, including the front panel and internal fabric ports conn ected to the ASICs. +Each forwarding module must run an independent SONiC OS instance (called the Forwarding SONiC Instance or FSI) which controls the operation of one or more ASICs on the module, including the front panel and internal fabric ports connected to the ASICs. -* A Forwarding device must act as a fully functional router that can run routing protocols and other networking services just like single box SONiC devices. -* The system of forwarding devices should be managed by a single central Supervisor SONiC instance (SSI) that also manages the internal fabric that interconnects the forwarding devices. +* A forwarding module must act as a fully functional router that can run routing protocols and other networking services just like single box SONiC devices. +* The system of forwarding modules should be managed by a single central Supervisor SONiC instance (SSI) that also manages the internal fabric that interconnects the forwarding modules. ## 1.1.2 Intra-System Control Plane @@ -89,10 +89,10 @@ Every FSI must have a management interface over which it can reach the superviso * Each SONiC instance must be independently configurable and manageable through standard SONiC management interfaces. * The physical configuration of the entire system is fixed at startup. This includes - * The Hardware SKU that is used for each forwarding device + * The Hardware SKU that is used for each forwarding module * The Physical port organization of the entire system -* Live replacement of forwarding devices or pluggable modules like transceivers must be supported as long as the part being replaced is an identical SKU. +* Live replacement of forwarding modules or pluggable modules like transceivers must be supported as long as the part being replaced is an identical SKU. # 2 Design @@ -110,67 +110,47 @@ Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](http All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called “Global DB”. This instance is accessible over the internal management network. FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. - ## 2.3.1 Global DB Organization -The Global DB runs in a new container known as ‘docker-database-global’ as a separate Redis instance. This ensures both that the Global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. +The Global DB is hosted in a new redis instance called `redis_global`. This new redis instance runs in a new container known as `docker-database-global`. This ensures both that the global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. + +### 2.3.1.1 Starting redis_global in the SSI + +To detect if the `docker-database-global` container needs to be started, a new configuration file called `globaldb.conf` is introduced at `/usr/share/sonic/device//globaldb.conf`. +The contents of this file will be -Multiple databases can be instantiated inside the Global DB analogous to the existing CONFIG_DB, STATE_DB structure in SONiC Today. However, at this time the expectation is that _all_ static configuration including globally applicable conifguration is stored in the FSI CONFIG_DB and only operational application state that needs to be shared between FSIs is stored in the Global DB instance. Accordingly, there is a single DB within the Global DB instance called "GLOBAL_APP_DB" to clearly mark the difference between this DB and the local APP_DB which is accessed by OrchAgent. +``` +start_global_db=1 +global_db_address= +``` -A new systemd service `config-globaldb` starts the docker-database-global container in the SSI. In the FSI, the config-globaldb service reads the contents of default_config.json and populate /etc/hosts with the IP address for the “redis_chassis.server” host. +Since this is a per-platform file, the IP address to host the redis instance can be platform specific and the platform implementation is expected to provide connectivity to this IP address for all the sonic instances running within the system. +A new systemd service `config-globaldb` starts the docker-database-global container in the SSI by inspecting the contents of the `globaldb.conf` file. -The server name “redis_chassis.server” is used in database_config.json to describe the reachability of the redis_chassis redis instance. +### 2.3.1.2 Connecting to redis_global from FSI +In the FSI, the contents of `/usr/share/sonic/device//globaldb.conf` are -**database_config.json** ``` +global_db_address= +``` + +The `docker-database-global` container does not have to start in the FSI. However, the FSIs do need to connect to the `redis_global` redis instance that is running in the SSI. To achieve this, the `config-globaldb` service in the FSI read the contents of `globaldb.conf` and populate `/etc/hosts` with the IP address for the `redis_global.server` host. The per-ASIC database_config.json includes the redis_global instance information so that orchagent in FSI can connect to the global DB. The server name `redis_global.server` is used here to describe the reachability of the redis_global redis instance. +``` +database_config.json: "redis_global":{ "hostname" : "redis_global.server", "port": 6385, - "unix_socket_path": "/var/run/redis-chassis/redis_global.sock", + "unix_socket_path": "/var/run/redis-global/redis_global.sock", "unix_socket_perm" : 777 } - + "GLOBAL_APP_DB" : { "id" : 8, - "separator": "|", + "separator": ":", "instance" : "redis_global" } ``` - -The following information is present in default_config.json, which is loaded into CONFIG_DB - -``` - "DEVICE_METADATA": { - "localhost": { - “global_db_address" : , - “start_global_db” : “1”, - } - } - -``` - -This indicates to the SSI that the Global DB instance is to be started. - -## 2.3.2 FSI CONFIG_DB Additions - -Two new attributes are added to the DEVICE_METADATA object in Config DB. These are used to convey to an FSI that a Global DB exists in the system. -``` - "DEVICE_METADATA": { - "localhost": { - …. - “global_db_address" : "10.8.1.200", - “connect_to_global_db” : “1”, - …. - } - } -``` - -The `connect_to_global_db` flag is distinct from the `start_global_db` flag to signal which instance owns the DB and which instance is supposted to connect to it. - -### 2.3.4 DB Connectivity - -The platform implementation is responsible for providing IP connectivity to the redis_global.server throughout the chassis. For example, this IP address could be in a 127.1/16 subnet so that the traffic is limited to staying within the system. The exact mechanisms for this IP connectivity is considered implementation specific and outside the scope of this document. - +As described earlier, the platform implementation is responsible for providing IP connectivity to the redis_global.server throughout the system. For example, this IP address could be in a 127.1/16 subnet so that the traffic is limited to staying within the system. The exact mechanisms for this IP connectivity is outside the scope of this document. ## 2.4 Chip Management There are two kinds of chips that are of interest @@ -201,11 +181,13 @@ Please see the SAI VoQ spec for more detailed examples. ### Forwarding SONiC Instance -Each FSI has a globally unique name that represents that SONiC instance. In a modular chassis, the name would conventionally be "Linecard-N", where N is the slot in which the linecard is inserted. +Each FSI has a globally unique name that represents that SONiC OS instance. In a modular chassis, the name would conventionally be "Linecard-N", where N is the slot in which the linecard is inserted. ### ASIC Name -In addition, each ASIC has a globally unique name which would conventionally be "Linecard-N.K", where K is a slot local identifier of the ASIC. +In addition, each ASIC has an ASIC Name. The ASIC Name is no different from that used to identify an ASIC in any multi-chip SONiC device, except that it is globally unique across all forwarding modules in the entire system. When applied to a chassis the name is conventionally chosen as "Linecard-N.K", where K is an ASIC number within the linecard. + +The ASIC Name is used as a qualifier in global database keys to create a system wide unique key. It is also used as an identifier the group of software components that are instantiated to manage each ASIC on the system (containers like syncd, OrchAgent etc.) ## 2.6 Port Management @@ -221,9 +203,9 @@ Every port on the system requires a global representation in addition to its exi ### 2.6.3 Inband Ports -Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding device local CPU on one side and the internal fabric on the other. +Inband ports are required to provide control plane connectivity between forwarding engines. They are connected to the forwarding module local CPU on one side and the internal fabric on the other. -Every inband port is assigned a System Port ID just like front panel ports which is known to all the forwarding devices. Thus, every inband port is reachable from every forwarding engine. +Every inband port is assigned a System Port ID just like front panel ports which is known to all the forwarding modules. Thus, every inband port is reachable from every forwarding engine. ### 2.6.4 Fabric Ports @@ -232,6 +214,23 @@ The provisioning and management of Fabric ports is outside the scope of this doc The details regarding the schemas, Orch agent logic changes and flows are described in more specific documents +## 2.7 Failure Scenarios + +## 2.7.1 FSI Failures + +If an FSI fails due to an OS issue or if the hardware is removed from service, then the expected behavior outcome is + +- The Global DB connection is torn down +- Internal control plane connectivity to that LSI is broken which triggers topology recovergence to avoid use of any forwarding paths through that LSI. + +## 2.7.2 Loss of connectivity from working FSI to Global DB + +Loss of connectivity to the Global DB can prevent forwarding state from other FSIs from being propagated. To avoid traffic impact, The FSI must take defensive action to disconnect from the outside world (for example by ceasing protocol sessions) with neighbors to avoid any traffic flows through the FSI. + +## 2.7.3 SSI Device or OS failure + +Failure of the SSI at the very least results in loss of connectivity to the Global DB and the actions described in 2.7.2 take place on all FSIs leading to the entire system being disconnected from the outside world. + # 3 Testing Test coverage for the distributed VoQ architecture is achieved by extending the existing virtual switch based SWSS pytest infrastructure. @@ -246,8 +245,8 @@ More detailed test cases are covered in other HLDs. Dynamic system port support is required to support the following forwarding scenarios -* Addition of a new forwarding device into an existing running system -* Replacing a forwarding device with another device of a different hardware SKU (such as replacing a linecard with a new linecard of a different SKU in a chassis slot). +* Addition of a new forwarding module into an existing running system +* Replacing a forwarding module with another module of a different hardware SKU (such as replacing a linecard with a new linecard of a different SKU in a chassis slot). Both these scenarios can be supported smoothly as long as the global system port numbering scheme is maintained and the modifications to system ports can be performed without impacting the System Port IDs of the running system. @@ -269,19 +268,18 @@ In this mode, the standby supervisor has booted into the OS and is waiting to ta Warm standby can be supported in SWSS as follows - Gracefully handle the loss of connectivity to the SSI and terminate OrchAgent, syncd and all related containers -- Process device configuration and populate standby Chassis DB with static information -- Modify the ChassisDB address in DEVICE_META -- Start all the containers which will now connect to the standby Chassis DB and continue operation. +- Modify the Redis database address that the FSI needs to connect to +- Start all the containers which will now connect to the standby Global DB and continue operation. ### Hot Standby -In the hot standby mode, the standby supervisor has the control plane running in standby mode, such that it can take over with minimal (or no) disruption to forwarding device. +In the hot standby mode, the standby supervisor has the control plane running in standby mode, such that it can take over with minimal (or no) disruption to the forwarding module At a high level, hot standby mode requires -- Starting Chassis DB on standby SSI in standby mode where it mirrors the Chassis DB. -- Live sync of Chassis DB state between active and standby Chassis DB. +- Starting the Global DB on standby SSI in standby mode where it mirrors the active Global DB. +- Live sync of Global DB state between active and standby Global DB. - Graceful handling in OrchAgent of loss of connectivity to SSI and continuing to operate autonomously. -- Reconnecting to Chassis DB when Standby SSI is ready. -- Reconciling relevant Chassis DB state with SAI Asic DB state and modifying SAI state as appropriate to be in sync with Chassis DB. +- Reconnecting to Global DB when Standby SSI is ready. +- Reconciling relevant Global DB state with SAI Asic DB state and modifying SAI state as appropriate to be in sync with Global DB. From fcf7e0c7c0317c26e6764acf2cdad3403c91db30 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Tue, 8 Sep 2020 15:55:06 -0700 Subject: [PATCH 008/175] Moving VOQ arch documents to voq directory instead of chassis as per agreement in SONiC community --- doc/{chassis => voq}/architecture.md | 0 images/{chassis => voq}/architecture.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename doc/{chassis => voq}/architecture.md (100%) rename images/{chassis => voq}/architecture.png (100%) diff --git a/doc/chassis/architecture.md b/doc/voq/architecture.md similarity index 100% rename from doc/chassis/architecture.md rename to doc/voq/architecture.md diff --git a/images/chassis/architecture.png b/images/voq/architecture.png similarity index 100% rename from images/chassis/architecture.png rename to images/voq/architecture.png From 2190c9a5f6ff2b7843d45eed95ebd52fdd5e59e8 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Mon, 21 Sep 2020 18:01:44 -0700 Subject: [PATCH 009/175] Renaming Global DB to chassis db and misc cleanups --- doc/voq/architecture.md | 37 ++++++++++++++++++------------------ images/voq/architecture.png | Bin 56364 -> 56986 bytes 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/doc/voq/architecture.md b/doc/voq/architecture.md index b37b70ccbf5..96299f95ef0 100644 --- a/doc/voq/architecture.md +++ b/doc/voq/architecture.md @@ -1,7 +1,7 @@ # Distributed Forwarding in a Virtual Output Queue (VOQ) Architecture # High Level Design Document -#### Rev 2.0 +#### Rev 2.1 # Table of Contents * [List of Tables](#list-of-tables) @@ -9,16 +9,16 @@ * [Revision](#revision) * [About this Manual](#about-this-manual) * [Scope](#scope) -* [Definitions/Abbreviation](#definitionsabbreviation) * [1 Requirements](#1-requirements) * [2 Design](#2-design) * [3 Testing](#3-testing) +* [4 Future Work](#4-future-work) # List of Tables -* [Table 1: Abbreviations](#definitionsabbreviation) +* [Table 1: Abbreviations](#definitions-and-abbreviations) # List of Figures -* [Figure 1: VoQ Distributed Forwarding Architecture](#41-general-flow) +* [Figure 1: VoQ Distributed Forwarding Architecture](#23-state-sharing) ###### Revision | Rev | Date | Author | Change Description | @@ -27,6 +27,7 @@ | 0.2 | June-22 2020 | Kartik Chandran (Arista Networks) | First set of review comments from public review | | 1.0 | June-26 2020 | Kartik Chandran (Arista Networks) | Final set of review comments from public review | | 2.0 | Aug-5 2020 | Kartik Chandran (Arista Networks) | Revisions after further community review including description of global DB structure, removing sections on system ports, testing and future work to be covered in other documents | +| 2.1 | Sep-17 2020 | Kartik Chandran (Arista Networks) | Rename Global DB to Chassis DB | # About this Manual @@ -52,7 +53,7 @@ The initial target for this work is a VOQ chassis system in which linecards runn However, this architecture makes no hard assumptions about operating within a chassis and can be extended to other form factors with the same VOQ architecture. -# Definitions/Abbreviations +# Definitions and Abbreviations | | | | |------|--------------------|--------------------------------| @@ -106,13 +107,13 @@ Support for VOQ based forwarding in SONiC is dependent on the [SAI VOQ API](http ## 2.3 State Sharing -![](../../images/chassis/architecture.png) +![](../../images/voq/architecture.png) -All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called “Global DB”. This instance is accessible over the internal management network. FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. +All state of global interest to the entire system is stored in the SSI in a new Redis instance with a database called "Chassis DB". This instance is accessible over the internal management network. FSIs connect to this instance in addition to their own local Redis instance to access and act on this global state. -## 2.3.1 Global DB Organization +## 2.3.1 Chassis DB Organization -The Global DB is hosted in a new redis instance called `redis_global`. This new redis instance runs in a new container known as `docker-database-global`. This ensures both that the global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. +The Chassis DB is hosted in a new redis instance called `redis_chassis`. This new redis instance runs in a new container known as `docker-database-chassis`. This ensures both that the global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. ### 2.3.1.1 Starting redis_global in the SSI @@ -220,16 +221,16 @@ The details regarding the schemas, Orch agent logic changes and flows are descri If an FSI fails due to an OS issue or if the hardware is removed from service, then the expected behavior outcome is -- The Global DB connection is torn down +- The Chassis DB connection is torn down - Internal control plane connectivity to that LSI is broken which triggers topology recovergence to avoid use of any forwarding paths through that LSI. -## 2.7.2 Loss of connectivity from working FSI to Global DB +## 2.7.2 Loss of connectivity from working FSI to Chassis DB -Loss of connectivity to the Global DB can prevent forwarding state from other FSIs from being propagated. To avoid traffic impact, The FSI must take defensive action to disconnect from the outside world (for example by ceasing protocol sessions) with neighbors to avoid any traffic flows through the FSI. +Loss of connectivity to the Chassis DB can prevent forwarding state from other FSIs from being propagated. To avoid traffic impact, The FSI must take defensive action to disconnect from the outside world (for example by ceasing protocol sessions) with neighbors to avoid any traffic flows through the FSI. ## 2.7.3 SSI Device or OS failure -Failure of the SSI at the very least results in loss of connectivity to the Global DB and the actions described in 2.7.2 take place on all FSIs leading to the entire system being disconnected from the outside world. +Failure of the SSI at the very least results in loss of connectivity to the Chassis DB and the actions described in 2.7.2 take place on all FSIs leading to the entire system being disconnected from the outside world. # 3 Testing @@ -269,7 +270,7 @@ Warm standby can be supported in SWSS as follows - Gracefully handle the loss of connectivity to the SSI and terminate OrchAgent, syncd and all related containers - Modify the Redis database address that the FSI needs to connect to -- Start all the containers which will now connect to the standby Global DB and continue operation. +- Start all the containers which will now connect to the standby Chassis DB and continue operation. ### Hot Standby @@ -277,9 +278,9 @@ In the hot standby mode, the standby supervisor has the control plane running in At a high level, hot standby mode requires -- Starting the Global DB on standby SSI in standby mode where it mirrors the active Global DB. -- Live sync of Global DB state between active and standby Global DB. +- Starting the Chassis DB on standby SSI in standby mode where it mirrors the active Chassis DB. +- Live sync of Chassis DB state between active and standby Chassis DB. - Graceful handling in OrchAgent of loss of connectivity to SSI and continuing to operate autonomously. -- Reconnecting to Global DB when Standby SSI is ready. -- Reconciling relevant Global DB state with SAI Asic DB state and modifying SAI state as appropriate to be in sync with Global DB. +- Reconnecting to Chassis DB when Standby SSI is ready. +- Reconciling relevant Chassis DB state with SAI Asic DB state and modifying SAI state as appropriate to be in sync with Chassis DB. diff --git a/images/voq/architecture.png b/images/voq/architecture.png index cdf9b75be51387db11fa60b95e12ec873737163b..45e14de31c618485906de47da700f2f1758d7bc2 100644 GIT binary patch literal 56986 zcmce;^Bi${Cln96ll1g`Xs5l_q(nAi- zJLvO$&-n|^eE4Z%@3q!md&RY`o2aMi%ESb>2mk;eR#j2d0sw3%0ALwF@G$SZ^$KbQ)xp7xjH*WIgq}^I1Jhyjxzyb5 zTGjy^K0C1X#`@>~<5%+6*V07~V_q>CRR`329;`a&elK5ej{l;&Sw<}^a!vVrl|wc8 z=8uQlQsmbc!vhvW&y9;h!=>)rZ&H_sQfprwB_zIn`7r4CE&tZ2Yj+=ai>Z*vK?^I& zrK&s5eUpaYr9rREYu9mVwfT3=$mLO-*#8z(wiIc;{;9olbjNu5SE1U>g=&gPu6njf zAp!LjvOq3mLva7+4jJmpeSgu#23=OZ1rJQrlk4ISp#sB*q8}bLA zemxoDqDD0YuPnmx`)A<+?RUC;gN}yzFUDn_Fh0e@*OAIL{gLFQW?ziv^vVqO zbPWHfPV?%Qh!<#u5nTT+cgcIu@^4k0_eMhY@x_K;e#^YIvCY1#CZ*~=RIF2Sf)2?P z{nVlM*Pg1btlvQ|bjz-g-G+ueeI^>EUT$6cE7$Ua*$?XftwW{p9%~aLw)sbSz5TD> zGgkU9-L`{quXVxc|Gu!ONt@+9eC;s%b^SrcPT$yvuacLCGM}vf+hOmsKu*x?_(!87 z8C^b|r_w6HHTCqi{Q*5T!5b6*gwSf_F0>#2bnxo&NvD&yiL^y4%Xl8=Uxf>NXtfo8 zmKmdSSsAKR22T{9T&ZYW8_kmb=MS1+9e?pZI@n3!%zbC;z4@!;l)=;Hf1h=7gslh* zUy)bZI`n60w4#c6*p)6GF&X~b^$|z*RQ(Z)LiLtl#z7P^XR5-j@X_w0e;?u(aw5&n zTN3Xyn5+i8UkNHG47~X9#dtjGKe0l;yE`E3_iYE7*<+;JjEsza&%tYgg7TQJ91^5A zXhw3jOB*(Lz1OlNc80ifMkClrx6NvX=lG1Tj+z6Vj_%adPNr}-;ELGQzAV1nt zsp3ALJ=&g`nv=Q8^*$P(ER$&TEZ!VzI@d(ggYHz5?uL0Hzyo}={HOsSuDRgvF+UOw z{N|j?mz{IfGIv?UGGu3QruJhOQoZ02J zw!=kq2#aYeMljO!zFn-jhJj|I*Dq%hMpO=1WHv@k!1?#`E^(et_3(V~CVsefMLZdA zS_BE>pY)I(VHcs>Q8-XXLUZnaegJ5yJp~)BM+*> z1Sso|1_RNj$Z&rW!4DFmN&%<bV9ZWL>_Jp}+C9!pavq@Z3WaD2 z%eJ-JPgds@_at0v?qHvirLpY&neo2vMO9n7G@{5#Q0`<(;jf&_RxWWzNImF@%5!~# zS087evA05^mtCu|d8(Z*-#>&ip@k_q`N}LS4=tFc0H%gnD8gWe(3e)uS&1VN(oT#XoChPKQ_I?X z`1 zY9ZNP80_L3iXRmD*PStjPsJir%rFp%ryr_W-U$XG^ww($t32v(KAEya05abkt-qdPw;csI%K;VIomd@eL;|( zAL*(8+oAwO#*inrBre|bumr#nw=gGs*iR@+#3;CY=X452nADFl(&dQ{5*L&V5Jyo_ zBMd&iS&0JZlHBA0>f(DegRlFDW!w3l{qy6S1EP@)E_4j3BUrZVq>%mS)FsVTocfv) z0Wj$G|2nQfm1nJjgr2pXh(UNr01z(`2N^(1q)-*QKYz6xtVr;X5~1?f)R-$_1hheF zY_?I+n#*of4}5Spea5&^yby9L|1L6jFXD2XqoSsGW&A%fj7d z$wooYh1d9L%fw)^cOh9xE|KrQrj))~t;w8_B%j*BLovfNXR;2aLVCxex*Z)@fjRU3r4o$Pen5qyvjxZ*#HvnnD|F8Zz=D)#Yr+Y~2*6~7zLkuTU-mU=)l| z7FA%dZgN~PO#vfe#C9e$17B5|`|Nvi07A}>$qd*)khS@Xte*abw`dUiER5{JR;IKK z!6O4$2~s!G*c66`EH?j^Vq0Su*UXRdtmDjM0F>Nc{+}zMBHy$5DsLnb7Je^JvF%h) zuzD}GoHQRDYG=t|to029sS2@H%t!T|7<4nVN(e57jOU@CF0ka;jENBPe8X|GvGR@47^7RE_&pgdSm z2q~D=B*{)Pp%8V8{4))ae#+kkC=egI)cS zD$XI5=#TTw55GLP|6+O5=D)qe=qPLD!mQ5oOV}e^fO6tbvGme+5kODt@!=z(@FH<*q*R zc)Mzs9cqoP_VDwIM`x~eIDlZ1Tx;`LS()|&o`GN8i_RKvWVtyHt*yg`%kwHrtIh9) zvyf~_%iv65E5&M8ha9{ELBaYFw+5O!jY0!(x=y-^1MVmLJw85TY|gzqbG4f6`>u;~Hja zVQ|18qewTJ;T?|nbAuMRXzd$x*wJB=%QK;;-$sSxJ_CwR05*&_bmjG6v7^>s^HsIA z!>EhyKTm#nVmn^CEr*>y(nz^Qn)pT^D_;w(!}}<3@8V#xPI}c6+lknSUuQ(V=T8Gd z==w+Qr06^2nl0&owQoqfh$zq0{ndQY!rMKXS>Dgn-znw9wvPbTXGX?VNW+S)r$7*QF57Oal3FMSM79;1xH zg7IZ>pc{=Cd+b|m&Fv~X;aeKs3#=FWh|;on45IZBghW{VOotIE1x(V`jy@~nxHJfT znURibz}iTdfG>;njtmd499wWJC1owaMQ}y~6#3WJA5D;(C^-u~6AY(&jmwK5goe0K zzO!B&&105FnE{*xQOO1G@v)ag!tFyxSi7homsonizE4`Cq2>VFUkw+HLcJ4XUZrEb zfs%$iB?}>nWsGGeVru_PMZ%`K2jU2Qwm=P1qJsiY%g6n){Y!U}0L6cnSANJtlp3au z@i4;V1|bvFGqRXr6N1&gcQ~JRGB`Mun#bcPxlTTtiYh-bGI}dtfdl<}4L|uv-Ac{I z*u^H>02y;;n7gG^!CM6f6Z*0vHdH%(b zLL8r`1nH{nZ$j9A*LupAN4j$>5*k?ABpBF#Hov)gL5h8pc{)6@3e74Uu4b#(7D2GP z%jpxLAxxymFW3G#9Tr7O|p7fMO7Ef05fz-@(A?)^w z75}CuMR5`h(ypYZS9v?Mf-9(;)(0 zYMq%@I);B_I^O@f(q1LO+w}`KqyEVKmp@yNwtlufVUg-5{k`nHL)zR^ebx$J)~0Us~X8=4Wejpn01EA7m*kV#v%nD=b0t=zAtGu$&WqfJ~q6S5K_ zQbiH7=&Dl*=zR8>{$oz}yeRkk&!HB(VE^MJ-PuSrs-=|80QV6t^hrIZ)4r{OX_b_=oGVN}wD4`(8J4kgmL(dnqyd~=Y>23tb zefz9?P)F0J6&5}AtdZ5{A!IDNhm5;XENb-&&*LzGMrMr?e`^O|_OG;IB4;R~oZbFdUX|fp2tqTb0S=e}8*M{@Om~RW9m6@?T8l`Lr){5?^B4 zRNr8E;e&3AXHq>kqYvZ=B^n{Y-``7JR%_?YDYDsh-gGjXuiW_M>bx6xk26-??G`G0 zxd_0Pc?I z`hgh>jCoBqYxi@X$aE*Z_Jya(Pc&PQseKMSyk&S}{Il)IY1_GYv9CL_%-!DkB;~gH zI6u+%WTFGCRDfrd!E%`LsP8>xejNtdtIZ~zOGysrUNA^M+@T-$#=<7-n*g7bAiwD5 z%i`iSUmw0ZKO9v@Zwr`3y|@m#+$cZaw;y>p-R)PMu469Vpd0gXO_u@zxzU{f_B%e0 z*y5?(SM&6{%y&x$|5SKx)K?khtoWhpM@>b&f*YK6><-bxU?7vm)>y9$?nhNau|_O+my23mhZ^I?TkV;BrK zySSh{nv0)3>ArV6j@UwsK-49gYk(QoYEZSr5L zyR)+h51jcLmEJ&je&_}Emd;vpK*SDbOI|;_q?HN$RhFOpz|1e$$I@EL^LSpFVBESpj)yN(IXytSn^e>&CBuxf;VCWo``mclNJks^J-#;!Yl~K%vb) z8}vu8Iuy)$5|lJvnyj9A?WC@uHEX>M{^_?bLlXO41Jb56@IxIP?$(jmHvL7}+yt+#E|`oSxkFJ@~7lt_+%{_6`SQ5%b6 z_f?6KI)_&g+BpK{`)zz0cG&GHq+eV_ik|e6^ccDJG;UpPosgE9ZIxyOgvlJ&+Y&aV zcOJ8D#Yp$miPN0B@*gjql#J}2vx1}Pe^3W=-W+uF3#xRJxG`+JI=r6T`Tn#!o5L^s zs~fC-^UJs;mO?bczzcb8CUtJUlD)1oC@fDGDJu>aYCFT4KO658R z?#C*s&IWar^wLy!TF^xEkvLF1;4rGeIdhZsD2jMMN}LWs)=Z5<*U0VDR${(D-4JjH zArv-TgmQIg@s{#T?)$b;(`n5MpYzvk2TviIItR_Xu`ZX|XHr2?4&aLXqy&O*d$=8LiZwUN9h9sSz3 z&=DVJMab=mh|ycJ*deK!E=0QTIEt*PyRqe&2cL6`sbUUM6D#s4PDSEYHE~(kN{|cD ze8?5H$>K}wM?S|}q#r9;${8Ghs9)F=%xV8Bz|?}@9!RZR!P%{^BGa+HH4STX7mD2h z6p=XSD3R5AN{0Kc_BFfnUL}T^&Kh)uNqvMopX(TtCBOym!tI@a_Un?Wr*v06A$#X& z^FcfuGv_G;i5o6Jeh}?K1iQtUf-IL|HR4b4x7zGT(4_+`4>R35`$17=FmC7=5Nc0J z0)=V2xdTzSRYl67crlcRBF0eJuAx@tE}X|A8m8|pvSImC%d6e<9Mr2UnZ}fzECIzOa8B{71v{c3K>zm z`@P^PL17^i{He;5phjl8V#f|2+o1O1lNh()jCLSWLsq&%?$IhDYwCmTtJPO|STuQ0 zVg8LKuo@Sj;;DpeN=wqaS8I0TU(Kek5W9o`|LF5FTop)@$XKMW;&Dnh}p zYewAC&8C(AhB%(rN4-*frr%!Nzkt;7>J_Rt_m&G$nr7D@O_zdM;u#>SdO`>8a*t3( zy|GVjDSspiwbuJL+tok|AfB4(cb%5@GYM^cg!khjg5Lzpx5mn0lex(lBrNo)h$6^Ih+FZX z);*j=5hvFTPIYbEoY@)-|-$P>WY^rrUaC>R~t&+#|-} zX-kfPGNS;cBG#=#&K#kURJdm9nl;VI=hu970>{#2|C27Qs0LMNVjEjj>Sqe;JX#+Y zn+pU(Sh+d$qSpJeuq&O~u)Hm6)NzF;5LoRdA60DfXAp8O@8y&}2{FF(V3@aHIR;al zs5v3Fou^(gC=L5cp(tQ9=ZX)~OevAp=gZ1PVh$TQ#tovjE$))l&)0tmH1RkAIK72I z3zN4YPibsu4#{bcct)Ej|CS?q1!IcNAb@-;Pc@N=@qAa5rQ)J|t`)H6)A#=MH(hMI11&7ZAVqW#Q-h13MME#WRC_ z`V9von~Uy~!hAX|Pc)>4Jl7{jG`{;D5!ck7de3ggI5CZmKu)+m$w2_otu#Zoc#(0jaLsIe6anho{)ddwL)C#piB1 znTJ)|64@ppOBycdSr6@;%LNSd=La>uXK$n><4>`}oxrp)4EvUGemH4Qc%&O^=oMlrTu5>Q0X`}H49=)9g& z)9GYRzUg9_>nGE6Ibw5u>6@cFj>vL&V2$5wBaB$1y+i%w_uID6P+yswc8-ZS;nn{qdqyK8ztG}Qs^5!?;%VhGAj-kxNc*h4r>HfC)4 zd7Zz}8T{{V3j;#r-7ejR+a{NI#Fr2WnGeFhQ}U-vbJ6TL%-fQlp6Hj8zCVu*E|e^M zQb^@VluFLHnW^`M{k%7KyqZsxOy-u9y_*()S37N0zIKv7!5eVi3j1{CYuEoTiR%DV$j4finc}@SXHb6Ea#_)1X77$>X`V zpnCh4_v6R3b8giA=?Q02OY0p5yU4;S(ji`b(GH@WP|dEv$1(#_mQjbh?P-7XNN&)~ z0xIl8l%g#VN+8G)=(QE_D))Z&(=V61fjrhS>hiBpW_ww`v)psaaDHMckIRp)_vYya z<{DTS%>IW0*t%(Q;qSZ%QPNM{P{APkV;S_Q(9eUdV-}%-hP~wyY-kY6GV2s4eI81)&*g>@=4ts0u~8%T@YOq)_V8o*1nl z1{CodY@~Sj2_x+eH#P$x`g-bQz(N@&<&TF;7rAhTc-p+VSiwR@)4j`eFxBZV^YrFq z`xRnOo?5x=j4#coP5r8Kmi7_i+-yw$Irw=qeRg@+X{J3J?v@hDIIije^zm>+serQ4(-To<{)>~00G_4 zI*(&;sEQWo4+R0gfC!){z{?7E@s!7U2mloh&@;}9sIk~e{K<=|ftUO4S*6o#VEdGC z5i`)BFJ&b#a4=5-sR{-q3&?f{$@TrZWiIZJEPz%C^gJ3$#!Z|K1q~;lXGk57*rxyp zdjy>`U52O-^Sk!zRIt*;sI{X-;=!%Vg*TOzbRQxqvXi*p@I5o2>sBvVvZR`lsKd(? z%GkUm{Gzc%{ZY8v3>{Y^X)Kk$c`NP|iVXA&2nQLcJ|-}vY9U_+mU{>(c)%PJGJANg zbApF;NKPqVu0Ud+PRNHjVJzmdaPH5>RUcYPF(f6S3JBu`D` z@Xl~%DLGDO6tihnZ@S3iP{9x#+{6pI>pJ=~Iy$;Dx;;FeWd)0^h?vpB_Rur(V=4?J zRN-!w>cSN1u=rchpjNMu=JY=Nk^I9wh9q+V6?F;d0+OJB9F8|?Nn|vura5QcN@<bGNSj71X5(+hNy)8? z3Xl8b=&$$kRr4dxq6U7-P%_9CbmEbTaP%DSn%i7bT2m@eLU2^b@*HLH@z`52#5_`8 z-^UZ+r#3;2FBoY%C`oC67b#*`=?K^NbUBgB#{_wEyre(!T5vyU>3x@g;%-l&rS=OL z{JV5_;;A=hzGk?y?Np(Qa_e0wi)y(QMm*aV{THv?sbh986;A@S{$8G?5dM6b=EGt! z^a(F)BNvP8lMOMalBufCinHsXhWs|_0eMV<_j}`!=AEth>}j5&t4?gig0bBf7@0tcn@){gO{b?dPV@6>7xk|h zYU&%1FZZvVXAV9$T<)C15C9vgR2}jf*C0poq5@EqxS6PeBB`2wVn+U20d$Xaz*!P@ zkMrDR3D{!$xsRK7l$*t*F0DEP1*L_w(x)5Rn)a{sZ=I@F?(*bpM~+zsved30+cJv- z$%Y5c2Z7cTh53PV@5*p$Kx{R4o5Xm|L9(BHZz3Kh3g0wD$uzRPAj?jvvdOXhAyA(H zLhxo`h{TzjG=U16|=(hj91$m3Pp}^{mSQ(+;XAhzh}BK%$}!w7cg> zJLG^#(tKABL*g{H_RPo$+b|g#%EO=7y?GgbXh?Z8jK&O7Zl+tD#0cnT%P@x5U1Ksr zY}}?&KN1kukCO>qP#tq;n!DqqFWuFUus_OmL$^7>h?WE?|JLpE$u*3E$&6(07O%cE zROa3{E3-HA?TIjWh(-46AV^(;9gA$`|JtKV0x^$!gTKuAf-8VT)3WAWP^fL}lUNOk zxI2gaS8r=VU()3X!&3ObH~^D`UE|cjS;S7Xs=hynwWMQ{8iy=xowknvx@^k>zL|vr zNjKKw`2@l_TK~y|-0*n#8rv#=%IBV-sHzg4u!=kvy#xd*dEBzn;W433f&e)7T8hlh zPe>>8bXLc)#t|*4YoS&5BK+VHThMnS_G`6zUS@u*UDA5N^7mU`!|V zmBk7E^Gi24FoqWD%b@+8Q5FfGC+Don|T(Xn|l1PU_#$d^_mR ztAyaJh(yLxChJ^>UAP=6a(5BL{A{0Lwe6JnD}cjynlWdcSk!t1xG(HR*_I}31C+>t zOM%Dj9#F>bGdwdsA1ZZIv@Z*V4MimrRr z1Cde^;(Yv)DO`vQD~pO2A?OyTnKM^T4`qcAaB#Udg|1TJ$=0%*W{>h;(1pGtVtz2K z5Dvn_bddhUyXl^>^W4FChhxLprGBq@cZM@W*pHPl-3SM!hF!p>?rqHS;W50s6~IE! zrA>0fZ~)lwW!e5LJd82fzIA_ko>^)dLm0JV2nxHj1oI0bKHZ{fCOLtC$=WU3mp&8g zuyq+%1#vhls&9t0KU=G%+aJSHQO}`@r{uX8;{e6sWn^a4NJjgXE@&miztWHLq$y)2 zfqDfIGA!z4<)&{Br29kU)@q)o%&^3;VTwh!ueT$z`s-eVMhW*Kypwhrq|ZgQ>jS%S zpagANe@kDGN~mF+JA=g4;_2E9rWFW$qn3cdN-=}R#<8|b$Z&Y|i0Ko90H));?N+W`=p)1KI-#XXji1 z(1n5io6z-S!PGzgwj#on=j<*fRYu>~L|}C?hs2qVi5H}4)RxqP%LH?#n91XW%$+`EiH)aG4gzzQ8mB~~rX$*i*T8bS)8uf$xD>0;>S@t@!8GjO97jlYX&b zE`VhyrJQK z40R-+$0h5e0Uu6c_hmLu;g&8TyIH73(!Nnrl;AB?{-E1RD)wLVaC~UKm~@|oV#(t` zaTB7rVJ~ht%BC?i%xov$3vGDF+En(g;uzS6*#>STf zhs)&uS)J_T!=JGruuiwNTZyL{roMx~d59Ir&l^jz%-H^d3J_V63CYZ4gxrM8>DxNlizkSvY<4=MG+G3piNNaVyE6=HVKrb(e@byc#aW-HlloVz zH3iJnFr>3!RWNhN^G@hBX$i z)JTtT&pK*fVN(Ye-ncA8Hkn+OZk=->?I~~jdz8~Xho8N1+jDbYa>Pa$@S?6dnDJ#J zYicqgFntdU6smHx?VTisM=Z;qz@EG?yw`z@z=n)k%Dzg<(T>y-1b6Ps2&%BZUcc{p zg<*!W6~rthrdutTR`h~|G>GzEMmgQ4?t($bd}L8+3lG_;1Y5>OD7sLLvqcFG1})7k zcimp@YZFLhxXGS8#(FEt$~ka|-Du%sv(Dg{pgZ2|vk4{&e$8k6OZSUTUk9dtxJhqO z8CNF@@S4SVU#H)l12gS)BGZ_0n5h3$liF&-)Y{OX85}c;X}LIV?ny9$`}Qb#Bkzcv zSUZ~eBQ<-1oUcX29L{vj8mddk5jcv?xE3Ib#2U@J>>ZxZCcj5$CDAb_u*YK}C^se` z%DNQ?WAZBzuzybw0FjGShxFK|Qj9`!Gdq4QHI=JE*mcV)v&h?d_p!*JVObQ2+eI8l zE+gt+0jt7bLvZM_7!Dz+CI`^>+*CM>sEb1Ok60|60Wl#`ol$Xzk#CYn15fg^Ug=g@ zF@~n^x_f#1Gb7o#dL;;-FV%AH&IPVw@_iga;;q>kbJ`aDevsx(RJHmLwFH0DxD{Q& zKGSu1<|lq~E%fSg|F)#f@bze$3wIF28#VVdf}H8QNVX zfw@%Yla|x>a!Y)BpASXpUd{o>YoWYdjn_>AOTz2d+1pd5Vf!ohN&jX)3dzf>OWGia zM21hD`PKSt4_wg9OFByc5Gn&Rlc%kjiVX>1v+<8)iM9y@U2MdMf)X*rGT4i&nCawp zdU`BDlwD#b$R@GKa{OcO6x5PY1576WFjq0UD8BHOJ>LCrhWw~lwx!ptE+c&4P9i^E z9Uj#a&pbKVX zya}9(-s6+oBd%h1jgp=Q&i6;@H)vj-QJ*!nU|<-h)i*+Lmtuut48djZNNNJd-7i`@ zi$NAvWhf#BM?qQobxi{Q@`e_vWScL$_$Fl$HNl=5js`o(HL$GX=??|T%l(yn<&%}T zVwy_})Qr2a{4xSy8mtXi2bVA; z%Qlk`2NH!RD=vLL=d+nTX-1knTPLjsuOZ)`KezK&2e3RQ{4HgGJ6dlNKq^l;R>5nZ zAahP;Z`#9SI~_Y%Ts9Mi-uZT4?86#^+NgciC0#H_YaF*+{ z$zojiowcjwZ%jLdFE^)WY6d-My*8IIS9AI9#;r=GUnMku8LIbj9EQK8G-sCEQfB2k;HWIf!7Ub{#wNzMslm@n16MED7vF0L5g^dx6i*(JJckq#E6i6QF=y0D% zcd%r+s+lIiFeyq+-3zR37)q6ATX??X__l4g9dJ5KP8|IH>U!YZBAEx+Oc&5Qb#`4^ zi|k8z#Wob^YasVZSd^ND4j;W(W^ld2fWdXz8ZVapJhtY+&u+6bKT%z2$0QJr;w7b6 zkNXbeULDor~}k%|5+Xp7pZ9N^~a?DgJ-hnP%>49Cv&qL(M)18DU` z&n}N=m1ndW((A&ixa!Q-yip;NYu}!4TXN9UIoAzM3^!#5j@ux&Fde`8j9=+)tEJQN zmx1Y3Q*iWMak<1Z_&e>fVSaI*)Xw zI?(wHIa9p|^2UITvzu;CYdfWu`6(B^>Qbjv-lvIb0j1CufiRvpf8CEkVi>Ah6Z-p7 zpXU4PFH)uY=_ET_dUvMn{c|wT4WQVq#|uDEmbzuP3kjjHMnBg)VEKDq2qm*DhCiL^ zgXuYx&M>nLlYWq)<7gaGi- z7JIP?=FvKnmQiN~xm{JcH6G9vUXWQX+uLrI+171Jzim8 zCry4c+@V0E+C2MJX;>9d`<*9_;hcP(i~GK(Y5lQFzCcTVh-!&av$Ba-q2%sGsWkrE zgNuUoKBwvVHX-`c?y4VOE%##sz*1}}7)l4O6ofD4A&H9ci!H=ess0*?vMmV>Xst2j6;?nj1VH z4=3$z^*K9dFI8^*92N^*ULjV)1C3(lgsDGAWFV|Q^3p^0;%R?X#tO3l(aJ`?{?q8V z{8UEr!4%PL$5JvF1E#n}PQY8ko0umZh+r6;A~87ndqrx2?Onpvxp#_pR-S{vne!w4 zC*dPM+Ai4fSW-WC_1ZI&w*qAEOzv);3{<{eU%5Xh*}lg!uBJMd#j7gBCwdToWB zjBNP%8WwaS!99*qM0zoRF?AU?aVtRQs1n_^`G&i5^@%2l%8P&to;%8_{L454>&yJ^N*z~W+R>&)>5;Hh4$g>#g`Kq zl$UXS0xOhHtgSFHRIQQWufCbbw`3?=I`T2Q(deRob-G-F|BV>-(_Ug(1o&MSjKN39 zF`l#)fq#X-iuF5?2JXlK3$VeDPERd!(p|)@NXS=r%PU*A9L%WVM`CyRr@p!6sE8zE zL%o_15P~3cgsQ5a90eBH* z9@`!_(m&Dzcs{nf%TgF_9PE)oTGHnbKs&Mu6rae)6dJ@?kq-(wrDFzF`nx5UKmL70gVZJlc0I2(X%S zivN(5wM4#M8l3ROG&|M6)6fDQ@N!%M^Qm2Mn-1ftsE`IE3`^_iJdF*HT0}&f_u{UJ zPCy5?PNE40K*gMw7NE-YX{1L6fwRE&mXR#hyOD_QkjAR(iiYhWgh~)WYjrSuIa!t= z=-I6aU=d*wt31jM5LiGe?Ms-^R4*++NZSaoB269c0a&e}*pNk7b%L90vd40RHg}EP zSXSzlnO&v4-D8b$#>AfVJD%B+UsXTa+l}9~_8m+sy6@hA#1uIgYUGVDfYt?DK{Sgf zjGz^$V{BDW2jr#kqE^#l<0FD8s?$!0RR9K^%=SMuorio}rh!z5@}YMa4u22CjF#1C z%OQun@wSOIKM?A`X~Tcgyw${@!h@s6KDT$ThAK?SDub}SAZE}hH(COk4?cAFp7nUr zkKH?1tW?MF9@6m_>b@aq;y@p=$!DVi5)&*(6Dbji*K)NK*Vx29k_b984HCQ@g7&Wf zI6ea0(Laj^!coYzCLaz{=4>PqIL8}UT+D{17YG9FM=p$|Q4ZDUF419Jh~a%fkjnmZ z%u_Er7gbXn)9BlQRM_{@dI~OF%q$K1Hi$PTJ`_$hc;1L}!@kDM4Ka}F4a#UZqxL!lcd>1B`smu1c+$=^5 z+?=a)F|;PRrth!!$JkAF&7>~p46u7M{YC4vGw*5LB>jJe{lr&nXG_rj6i%JBz_{>4 zHPrtdV#sgv$K_PN2f!`Z8sa5xuL780L*AHCc1XD!G|YDy-^8m-ByyEPD?xnQX` zh~2drgC(2uyLRyC&jc%mN!0&(DDpWuRu1JzqJKrfac5=bcR=1Es5wz5IK!iC` zP^>oq`vqyO3lY?MrZQ}@?0m6k#4plP3b3Z6>!~CKEL-3FgEcWvi%kcSUM`aIkg|R% z!DhMmWoxH5x|SEY!264R&Y#(MGj8D3<@xDGScx?U!&1_<{gamdp*pY1k)>8dmc+|o zG2Tfqs&#ZZ$ZRB1yl2Uiu7cmXfCd-Q*o4-U;a1^YMRfi)1Gs#Y9>a)Yv62zsO`jd~ z-Hcr+mMw-*k~6|<3>8-EG+DY06RfAUJRgz=9}S3k)i1?=$^XkC!sOu(!q zmhqv7NvQI>A-~@PWLzAMKi@U~i?JMahug{m4Fnk(8@Za#&i7Yt>RTsF$%vsiy{q2# z|G|{*nI&2KJjG3xV#^z=gR&QZA#gJX@RxolwY?(2CW{@KzoyHeD{S1sWVK6&A!s0m zf&4HHyZw*1UiO1e>-c=ZjAUP3$KN|@MEX`Bw9mjJqDFvaMzhXOKwf;Y?xis=4(2f( zY9&L@%@Y9~`m4SCo?YWbb%*bYmm-gD(53NG!yl$%XgzedeNdWZ4i?*%(}gbbWQ`=W zTkVZjCA|AlQ4f4MGm*aC29l3;uf*|g{=!99$}1syV#J$v;_n!ZWzGTvE>j0V5)Hb9 z=GAvl#oF;X{%ACnr>_`m&LnS;qJCqn4EH6;#at`AQ+BXRZJwe~xM7MMkm&G{nz4 z=2H`*s2@QI2t6xbQ?ccr5~DyE%#xLLX}3EdC>kvf+2xO;+3*8*4)>h8Pc;9I6vD=e zSv$TseYv$WP;=aSB48=hF77+{ROZJ{O$5oOAR5`sbbi;DBjO$R#jkL@S33Vcs=hj| zs&4C=PLYzXLrF-7G#okw>5y(|Bqa}xNDBx^OE)6jp>#-hclQAf@ojvbd*A!U1psr7(heI5&37#OT-lUQ+}BMtPg`eE-*a?`h%K-n8-FOMhb^Pyj? zdR*u(hJ{V6d)psoV*^f-;7RYWHD(??72yb?O-54v+8;bsduh?32?Sm*FUG$$Z1a@^ zWeGSb=F+1KZlD%JONP4D|1STK*MD?(-dNu^Zq-D9?cf4ihN=DbBe#Cy>K^Ge%^EmQx_Y?7p0}cP zkqjwcR$ZLN8fWYYfS!a#?!DbVHDsgP4K_KX^6}fZgpA?D|KgJ0iwx#2rnt+r*HFmO zU|+()o7R;j(TbKQehwq;?Y6sU`p6Akn5$t*K{Wjc5~6A?=zZpsA@l_+J~`ThWeLt4 zh`ccp9;pE|0_a?ww>Hb7nLi@~oD9FcUK+Ir!b(1;Q4T(>1IXb6 ze~uLr&z{A-nIgw=UGDsNwBXLF{#vQgIq22_dOL|snt=0ke2|ZiRxmbtZJR{)l;fSe z;{m!3c#oOhKYSV2U&chOm!Do(AzX&VVy~Kx35iQBbyi=TjI%e)YYDIXev`WDb=BI- zE3~PB?V~AyLJs{1^x{6Wx;!SHClG%GNei6WFJVg*4}Qaq`M&)1VlQQEi9;eL88OKG zP6H9A6X#srPy30C0W_5P#9X%msj}8?_S2;nq4aI#_dfAdMHQOWNqqT2?!wCk6aL}f zI4%YGU{e;N!Pe_nL<`)g%PM-6S%aL%*ebYh-GK<(;V#$q&ez)CU3NORudm#z#^yoP zxs7dSw8NYCsQF6o_~R`=N&8YeLgy{bCW=XHRHRRr3-p|6!cph)@{PDy)j7nejbwh} zZ-JT_bY!+Y`8N4@4Ms_q$KO#7z&XU>SDJumnyp5gU%7W!bou1_f~H$t-G?xgw*qV> zt+wO&>9&jcE&G#AnfrXkg=EgNiANFdr<+O~>wgWkof~=#{HS^AxoOFmd#vR<>Czmn z1hJ4n+SZoAVvaPQ{cmKD=>q{aFU232j*b9-z}_C~Dd2YN#Ia;;Rb zt>I9z)xl)QaB5XXJf%irMaxu%%v)`8zv3JL#GQUqZdQ_{ie(5yg1oyhp#~79)f9+M`a4(S>t!RD8 zd-pWg_iE6;iw8N3YBAn1#^gFH>Yrsxc(FIv+VZISjl(?rNS1s9YxPtCdBhO#jz_aY zC29zwQ;Tk2Y^UnuwygS@sLVTrzY+w-A_`H;HCjDR{I;MJ&CstBehK|gKPN_BK>>`a zMuC8N$1kB0ZN#KCMZ>cq@(7XoxaHbYt*b{-rPRgEX3D9;@sr;L*)b|ds)Fz1sfA)o z_CxnAz5Mw>k!O--UGzM({r;wvYMES^xavpdze7D~bnZmbzD0v1Fl+XURN18*eby+w z0Rb&^P1+egAg0yzKGdX-*C1?WF=&W98K>xJsA>YW=4}@ywd8$psh5M(^3l;(#{;FA zZDoGlZ5O?!ab*WJD#qpOVP z%$`G;oE^OOGwt5zg$Ozct1kaB8M)<{)2~!|#q)YgWE5Z#jHa;}Nmm{z=jc-kiOiQOQEWg@J~}v;pX%mld713YDr0VN z@wH2_x5Ky%v_o-z5t`XbN>q8e9b@Qz+MzJmaPf zrzr2);@AkD5!?3-*;Z9#vU{LO@z3$XQHa9zZy9h;KEATket(i%Cf$tiD<8@+#l*Q+ zfVR+FtCd#SZIdVjxDP_C6g-Y)%XCY4)Wh}Nxr5~8o-^;+8*`cct)cJ3k2v8kl*0;? z-AW{vJ#5Fu7nl6**R~n~^qdpUJnR>6c_6$kZ#CNTS*zKcj-R9XGw*N}=!-)Iw5v=1kDeoGJ3{hx1 zBRd?)OxZk9_VL~>*EW8I+i=N@lrXI?l=`W=qQlCi8*UNdlRkWv+m> z6P0?|kEaf52QQylF715R_luvAPPJwq>4XM|hm5W#Z!rj(R~xczCh;h4wgi5g{`Lli z#<_?r-`QT`Rvg#SzZgUD;W$?NY53+WlB+-Aqe{NdTCJuw7RBu+Q6FGt#jJ!|)y`cnr>}NM>a_~#fL4#~)uK3g)kj;p=@x{3H zxy|r@_)1OYolFy@$3Uf@z2npDh&T6Cc>3jLwdH-a&+L!mURRY2cjbo2NHGe}>($4-AVzsL z<`RHA0C<|vf?PiwtGQaA8-K}@)38zKc^}vOmy*j0jqJ|4gx3>cs`0rRljxUwK$j~? zM*OWf`Fp_MmYd$3`J1%sZ+U&F{gn7h>n{4t@)oQRpAdl{3Z$u?smR}hM1Owl!~3dR zPF|g1#K;`;E+r%)5SaT*CC1L8cRYsMxm+;>r#)Cz+GQ z8aMjX+BSIuiA*lKm&}@?jNjr;k1#3otUvQ#?dk9c0=bjg@MZR&NFLkyDpC}A3^mbIzCpB{6qGIa~- z*mfgK>}i-#_{Z!LW-6ppqY2ka`=Cs<(tyNARV3r85<8tc-e*YOFO@ z6m55;r}r15d{MC&6=$Is|5^HpjvOE5O{;Zw#mM)$URtOuK)>lye{&Ch!zw{bWu_!I z|AeIWiOiE?)(e$=wiF|x$CK2EY`*rte>ONSHQjYUJ%k_DzJ_7@9Ef^td&JY_WnJHi zK?nESwwsI>i-(Msc($XVuuBRbAVgMQE`OW7Rxv&{){5yHBaAn89UJ{rd7m)%EH0ud zEJA*_9-AL_@uAoHdR|3YtPPe9Hvf6aSy zSV-$JZy z--5I+>b>B_{kh1pq-<+Ue9IewGs8=>(tl=*b(1t3yLx&pTJ*TB_7RZ;kjhEa z37>-aeZ9L1mkkz<8g>;weT69t5jgR^HtVGkJa_!{_Rw@jGDL&pedP&szCk zt{m1q!k#1?wP9BcZLO!FbOc2l!fsT#0I|g9kpdtcF7o+5v;l$t4eSF6$#PgLLxtE& z-V$!Y#X{{J*}Gp`Vgl>h%muIH)pB;W9ep>wF6(#pxh%Md^NN8&%3IsFRX#T=-fjoi zi?Tu<{WyRS5`Z>HE!Fnl_UFnMjb3S%UVk>@G163;>)YMk&5WuyKlpl=JWvSi%Rf90 zgB!~Q1z$~;BENiD5&EbtxA++yOlp<%3OY2lUkT>m&n=f9?7h5pE55)S+GJGQo;PGtdC!gA%KQG)4=iTqpBMIf>;{hrQE9>DQlCsj{LvIZc zJ%k68efD`f^Xn>Y-$}v*Hbydjyl(lzvIfN~e|v=%v+9SeU>D#zRRbaDEf*5?H~f>P zhCN(3f&6fI^Q#k4-`4m)|6W->Y(KA7?2}wc(>NuUWpSL7%_e#6O z@~|TM#zgtEl#NpPwU#QPoL-TdhtaMTdm)p=;VvCcGWE(sYOJ59T9xrs9^7wo1%5Zclub)X#^ zb{{~rlxPC<*YqoC=v2#;EmNMd&`G>gjyBX`19B$ut4u{y-9^z%t@390)fVOn-a8Qk z1wQQGfnFGmv3py}d+ii1lD6D4I|Lt1e8q)*Ig+K3f4vYGF21)+8rTPILOv^IBy<3{ zr74SS{$!V24x+_hX}Tqn{h;-)g9Cm$QwFpavJYl_91ybz2a*P zdiKpoT-(1c76d21GgT{dnYxUJ$tw9YlF2H!YCjc{GyaG22YERv@*A-uxQ*`yO$(hV z-2S;OWPDpUbIZ*a@ypPRn{&kl9sXuF+lgt`zeWI10PQvhv~@mA5{y6Mf2KMiE6;qS zU34EXK(`8KY1)H2ypzdaOwAMuFYb{4k`E$T6f{loH0gKxO?e%Yem zTsR&?@45aQZ0LQVI^E!6HC<+_&F8w(ZYT1?^?gRgz3T|&qu$lX@y7yvzXpHS?U<0N zlZm~_2T$mtmu+^81vJ<;0iNlJT5S`Ml%l)JH&3-l_Jzu+)%p+QA!s2hK(hIFRC=sa zC|W4T@%k=<;oxhC?o#DZ6^+<-h%c<+GuvLKFFQL4*C5$q6+h}okQt@VX$y@v)dKCX z$w<0)?}zE~#UC&vE{+zjJ*Bo5mE+ddc8&_JM z&fd?=w9_7bw!Y6EmX&ZD*7sh^qK~&?EmwLA@MzQBHTQa71TmiKMstrfKYxz7gkq80 zd%(*b!JTcDWL`rrhF94mu)t?rOPH@aVJ?rNXx_{bP-8Hs$JLN(3+j2&LW8x%m0&qm zJ=zgKkF;J(RKF9$(&Ij^W5> z-FxTI_rUTU5NvJCv|sjn0l5IgU$J(k*}XG`wg>zCM0zY10Rh<`=Snmo#?GZHoTF() z>MqSkPfD#7zpf}mJx_p2B#u6><)CU0nTTs4YEY)wxzg1S3di5U=zi$|s-9?5{m7Vp zu2gV%=gCUMBDaNy>$1^<_*s8_3J^Hj^dz!p-avJ<+WN7;9E>Eh&;6=Uurx8TJFkEG zz(4bxiklb|#a?`rx)QY{uZ~=`rQK_O?fHD3uvwHlf%BFXexdf%>x|kuEWLidwy zK39*p!8$F(1c{)+1>25LdOh~%lq5o8pLRZ8mNXC3%U8W^__6swa_d)0VzoTY8tn;= zmX`ubIaJoffPCzd^>U@>sj9ItTp(w3Sb*8(&eG!kH$>EEfD&r4G^q_!&;(cy3VJMv z!tEg>7iqL(ZtUOqMjYGjZ}&xboZg7Tbtrb69rS&<=Oi3VUi~_R*v0FT?k>DUI{=pC zhpgbPio(e)pbFKt5S_O=VWka}Bgce4Qz2P-s$Bp0*^w^j9<@8TZOLewYr26V9-M1l zyZXNUq?<$bHL2roP85;v^S#fUn$Zp<*SH3Vp<)w9%WGeU#sdOk#6P3{>I~2!Vv^5b zR!4b;f~!x~^TW0e6D$+cxNtmjS*4^C`;j#8cQgF+l?3%`bsjhgG-8~d%MaM6rIm-N zB~~|w!J<`>Rsj~nBU~_`yG4j$9^GQC)yd~P!--u!-0IzR15MvB6*`!|_VSalnlH{n z;K>&v$c#u`E46%;T2n1WYfP7LtO>P95*i#{0?85};Om-@jYVAPvl~k-umwq;4){?o z4u{SjL-rh0YiEdj&cBh6>i{t|QCp?fL1CQNDvPLJEdK&UVo8~%QNwFwHS(C$oTZFe zaTgX{swNYZJ<;DMVg=@%^L5!ASYn39@#uf)!;p^g;!M zS^AIOymh~S*<^&mznT|D3on;@hbtcuBJ-STn_07%=hbj)#qpYu5H1`Nz`+&Zk|gaS z?=^149+*c%kOf$z1Gq@2h_Oy8GW-xY-i~`X!uGI*NV#bWzXhlEm72J$cH@3HWOig~ zi=};GZ+9s;bg1Xd=_%T#d$}em=@^e0#uBf{- zW*%HE^T}x9sBJeenhbLW&eUux1O;qDd#yD*6;09?%PT2l{ep-PY}eGX1g7CL6Ci~{ z7mI0O0MnoeqS!&uH|<@D0}1@Z?AY*xDT7<8hPIX~?_Ctb>tHW}<(e$Z|J+J(Kwl*i!2G4LdmaeE1V-Ac4{-3JaPfAd5RlJi-py_-UjZK?r`* zhdv%y21yZXa4h#7x$WOQ#w_`I0IwMK)oIg>?J3v~fTLS|w>Z~xr028WPXiwdv<4z0 zKdBj-a*wu<`AzSOBK5y)#`NMrL&n(pwt)hQiv-v|;U8&OF8XTU9VwW=(=n*vzeP!N zHX1ZDp^UVKql*uqDi1`E<4J6Wh@a~rcSrzr&H}CF^H`u>)sp#pR{OPyi6-K}eV4?K zHA--A3WzT-*q(a=A015Dc&^+Q)7LDJ6dpa@g?Gr>(3%AoKi=>!{slYM*i86AJKW}h z>sVylKj56$%~%V5hjlc=OC;!^R>rndMs*mxfa|=0gBRwrtM0pkjxihlBU*4<99kFb9e;S@ElGb(K05d>b zOgQx4K|3VA(!9CPC@}i$4aa%XUe8OLw1CnX*;%5G`yqI{tA9A@1teHI7D1*IPty-B z_(xr7b@z$fwuwRILM46RH=@vf6J+#`9}#99Pb$>}gkaCwX1;F(i@~T2Xm(HLa0x`Q z`icFTkK{e*JLssOty7LJAyPQbN;DOT5lpb%YNTAp8BZZb9DsT zQ#+t`E8^CAo}Iqe_m$qnOz4Zl1f^aC_Gn3oZ-z0!ERQdJWL!#;Es-&3MEDf-i6C-7 znRT*Q^HGtUA&Y?=qLYDyBDgA*R8IkPgq#8_w;-iQl_Rg>Jkr( z;1nJ{S~ldBVb^0vu_;TK_DTfZ`K^=?HejN*YagqW0tKhx$TtZCEk+>Iebz~)MO~<( z?wbRNkJ{wE+Ek)jVJRc{f=HkDbUHr4b57|J@eIl<*Ilk=1X=^y(w`_$SI{#VIrKFu z`q}zzdG8B@*QKESxWsOh3wVF*ay>(Lw>lQfBX9*ig zVtdMVJryN$kZ?+hgRR>8+qkA>m47?GML|lMu+Nt7z|axzt@=>)I^Ka=S71|EXGV>~ zyqE(HfzfGb^~>F+WiuHh__I^Bu{2{7;ZZid9jeH4ID;#@mTXwuQx`|aN?n9WN9?O_ zN}L5QA((G}oK#r5fS>Vq9{W2GOa!`g>SV^|>M%$9aoC|;M40R|g#HxHfJ5SFw=N*n z$UUU9Tu(R70Sl8y?tP1k`PyX&D3zb`>#!l4lEIQ?yMqg8g?kXYGDn$&lnqgY(a< zHY1TFYm?UzE3jZIhiK6J8E@GRAFOwdOT@3_2b(F$Kf`cE`#=@jXJX&2XUAuB#F|*eN4EE!|&Jpq*C3|Y=3oi)_h<` zAIDhkIkKpCrrf1G_ws&8&UdZUIYLn6<8XbxDT3l6c(Anb8WjVIdW^nJ{a*BrQrgQQ zX~xlsNnRcUR3_o|s`HjChS33th5rRdJb0X4kJwRnWy1ae`D|3<4o4O~n)=jB28D6?@l-eM4CsQHVG_-0FA_Q+n$s*_g(=<&I9 zD6u`!8Xb6$zbRG3C$d|=Zg51L=P(^)BL|>K5F<@k$#B;}7XJZ8w&+YYvIBJ-{Bf8Y@RsU5i1o&`^ z#i19zZ1evO{DC7)ztrBesLQw4!kb5WKYtHpe5@wpv;5I?-AP@3se5S9g|G4ffa|Jg zATx=+kKoF4S*0Lyg(6dz)VDFULT%2D|Bub>IAP-w-Q^`A^zB04OHL zBYD|Bq8=rE^k`t)hMqwFto=+XpGLl4=v`f3;8k~Ys$2A_^LAQ%UANz-y|9W%wVwez z=<_jz$h~bf!*7lLvBhco5c=Rf6FcBHe-`=LNV7=)a%8hV5!R@b!nGd*C*R=XBc{G- zW63rT4VeJq*Z)jiEYc+4V_dikMqH@BcL4M+Ctq)Dr_YWCyCR@Qv3NQHjb|DQPK%xX znM-$rVu`Hpu3!-<1jm@Z(Ao&#ZOUTjfT;9uJd6aAN2B!QvzaPAWFz4j69FPQ=u@iI z2}reWdF?jTEhK#6egrg>%Gxx`^bX5_DDO;60hopVT>ZjQT28a3cye(;NZCmaY8{tT%6E8s~LYn5FA zOi8{u@>}I{;^ap&FUsZROsexPrQQEAx0t z>}3@uT$M?$2@K<^}6(RBO&1d9vJc3 z-m^dKGs^U-h}L(#A%7Xj)290msISp)2h9#L7zjwBMA6Bk(+k(eHP?dCGGZ&8p1$Vr z-=B#ivQus~dK}W4$;9Ud<1fXqVjo7&-Wx<%g~$(ah?R{zi7=~?`;R0M7q6!^c= zF|A4^iYkO`*J6L##ZtDu?ugsd&iuPK9y43G14@1PR3+rh<<!wbYG{dc%9Or8LgNJtTB~_4?6ctL5R& zp=m^z{J9gvg?~g~+e0+-IPCmjM7J9@;AQ}oz81-Xyans`CSk!i%p&tVzu-tL9AYzu zuMj4f&K=!6f7Gs6TK8rI1tY3-9>XICBdo2lbxsy*X(OkR_u@G2XNfr9z4%xp$#7bx zCjA&sOAohn%s?ta-4zX%^bQdr`L$)Mjz>w(0!aLRi8E;I9p16-)2n~mDyI;CJU$lwsom-W<2%tt z5m>44VphO{s1pQHMFKt>;u!|nd943@o+(CsG-F4Bw20|3h5e>BjuFXGgn-Xs$1S_|MC{h2+Cjw zQTs{?Y_gpShCU;vaVdydUsgdrt_|A5Rx8uHj9D}Q`wjNT10rT$_VPtR0Yv$BgwPH$7$$cnTIn zBBE^1Eo1Rg>W$XEYjBqy*i{2*zt$eG1J4GCIc0OVF{U5j0SL=p#r%5^8u5#x_G4IT3PzTXqDD4sX-74G{Tkf8VuP8u{b@&pWGayT}gvC1yfa*cW z-M$joLpssNgp{ka8xsWSh!{%?K93&X{=+1H%f3b2{u~qYF%KX`ux$VGx|33^rsUa& zb%DwDPsxMa?Rr}E;7+QuNO4-Q_Y7R&c}G8F)1yGM)gvm|Q3hq0m`fpG8m9`+m=n=8 zf$|tA;(V#COeNJ4{ySdKE%zU2(Xxj@wV5xgufK=bL;BDN)xLd8=pB+&f!Zo1b-;~p zMI=Iw7~;A|5W<=-LLi!h^UFV#^dPx6tnX?U>R#YTz*E2Yi!B{l#?{`_qR&MNC>c#F zBRXD=1_rb_nSG1a+F4uwg{iekOm5cxnGrRID%_GqN#6wb`5l1~_J!LUq+lff?CEMI zlW)<=@vL!p-pEMMLKKNv)9etG0md8|+y=^0$@rg) z1TT>X^uQOefba-sq3CHL|#d+n#Jl{9}Z3%W?q5xk{LluOrUVTl^Dif@3U+a!Qjn)Q8DvnNp%dg?7tfV zaK_-Zd?;cA&$@gL?fgF3F=v(z~A)T@1M=) zNq(U5{od?vSK#Bn9Vj^rJM6LA_+Aa090|N?fp&1#9A}EQZ4e*??#MdZ&b$@l5;L(V zza05#eVK>24|v6YaUBB<;scgQqXu1nevR@SOhmg)5Av!^oqkaT>^(O_=;wA$VhuB6 zI|DIe@@KYHquYbFAX||_k6?%ncDL$y{IYRFB|_i?y}@~ag-CT`^h?lLF0#_Jk4{_9 z)G?~)E3-@-k@n^4b-8F;0!{GA&F*nX+0x5!{axs!4%EyY{^s_#JUS*tvSekW+dlLB z6zi+22IuFOBy-N?qXF0j_DgjFee1|bsxi!>t;`r|X(LqJ#wIUW_Ae17IzgcG|9g*c zL~*E*E4+IsWTqINsTi`uL-Wj#Gh9}cZv(N%#Mn+Lh>I|Ce-2F>9qrbb7&^_Q8;ysP zHZU`xG7_Knoivs!J(ik!cZVktI9T;%QHlIg z`o(*5CAtO=?~X&{;CIRe9xjfQ$b|>jX;cwC+p`c{dRa8IvHZyKZ9zS-7K(WICT#lNBI%Pb$ z$|qpXhVa)T-tG?CI#7eWUNTL*1rcE4V*8d>RldW%b-Rsz1wbs>i(bj_w_o7{`YUWb z3=wkFivd?N)v|WEV;xZbS^Sn{*di^zHVcaQYm;9F`_9dzg%D@oc9R~|xU)zJ|A+Tg zBjX~YYNKfHAVOd&_CnVLx|vIX3DHpN>^9zt7(d0YH(7Dnv$$r1cDbw5?A?BQZON%(8VA0 zg;OsJwXqS>0)np+9mYin?5L&$6BXcQQ)cZKImZQBHb)-`JCHA|6NjfbPjS9Gu2S|G z>&!kDrwT%gs6wOowR)4MW+GG7soYhv?;6=6Uuw18zwZ(hyXI{o124|WKlS}J(m>ne zMX47hK0$U4LAcsZN2B3X4K1dXN?mvW<&2|F3wWwRNdx!!fy?Ff5&3kGr}4Y3j5^8( zp+3<9w{#41Ia&GGm!ZD0&nQ^L?q4gm4hlNVmP^YJRe!IighsF(y#7w0|4QjSIVS3g%tmLbe9TnoB>=oBZ%!c2{aAxV--L)ntaT`RkikEz|RjM zXA}9o_7v7ZWRO~VV~{;R`ySl^E)FX*;M1K%Xw{vOq#oTUp^@9MxcUqgl%!rKF@>Kp zinV0L-inzT6h=)4Lsey&B303S(@5z^$G(*=n^DLImaa4qKJ$%CB11zj&&!h`Dw@x! zM94AX3&zVN8QaI<Lu(zHZW-x-}7|{<6^jn9;FI$xaTq!ZSL%7?vsn%dwC;9K!}Uv?#nB$nha72f zM_E@%S=9@-Ne^cW(`fJUUDNPzW0FAA=B?mf)g+g_k-iir9YwZZUf1@85-<6T_6S%r7LsL%_-mzhFU%EJ z0AgoMVOcpAa%B<2+d8sF?3hw{Po_UOf`~qhiEgX0KwG_`;@lBUr zl!pBIpJ!sAQQv$JJWmx~{2AioyLTjU#CLY zgAijm1k`VQfKsmhBbL%4GGRw~r*^E~mBBR}K8LCiUyz2JUs7Ka^paA%1-0uSkL_iYuapQj}P3;&-N zc?+z*Ap&wY_y5KFr>Pw*A6lRX{LJt7-HSrqlBLn5hyKK=)8{%CUJT?L%tvFtpH`g{ zo;F07e{BB&2WO}$FD0&lut!8nUNUm7R-irEfEpTHWDBoPX1AO`4FKeaUY;Kb*iW0m znyzey5kPh(Q1>CyMum1ozoVM^X4{V+|Md@n``SnHx8>_U_&MdV&Nz2^R@&sh6y)jg ziZQ9@m&ONeXE?GS3boSsqCQKE9d#lRvq*}}6jUTEoz0p_@DoOrW%s2yHf%BD3maY@ zbiTW-!!9}>HjFPV=XEzNZFE0g=@`2TQ66iSwmpSb6p4mGAYNw&)%FuvK%EFJ1xWqm zzC3=L-rDj83}lmv16?kx8H@Z;$xplsAS*HO*S_NL)JGstY;;qJ_CQm*(15#<(T&%+ zrOcDLVPnY2^I%E7KuoXTl#|^2`Z``N{InGQSCJh%Dsr&ni7L(9Eo zFn?}dzSi5%c*$j`$^&PY^X9h)zqmde(0y!B^q^O^P6++&9gB}f*u62A*F?!gMr{EENeFLHHL?55o}IDEWN<+WyE6S}|Shhz9_pLA`#zk#GZ9T$zvoG>&HFUsnj z2)m?=RDWqmiAHb-1=9C=bKg^0di8;6`!C_A>WRtM*VhW)L*JP9W;rFwtVQm=S0oK5 zxb;bJ)gwjj2C^BQWSm^72oei42xs@F>mOWhU1yhn7DYhr*l2?g-%G%+0_hgClds25 z$#hBBFtaa4&><7|c1gm^XWb$OuQ4P6DQhm<2Zdb{;v5=r*3>$+8de-W4;Wic1IQ3@ z&s6{P7=q|``~t_|8?X(Iv=9+U8mi6Z<7~kHqI4)cqZ%~_+To%{Y;(i=3WYa0)-xkp zzQ+oW0bP^c;hlQg&$d1zf+{MUlRCzqN|d`_XW!$OLkLI0z?CUjZJb@NfqT7|6f(hJAH>K^{ZG zCtZHGC)6Jl)Zhh$atRA7fr4xS(g z+4%=){_z&9l(WA8aK)K=OU=9BH!<+V9 zkJpNe5HI?(mMn;8G^7%j`rnKf+i2!`3t3w>9e;}Nv0+j~j24f@pO0G|pY!W8`Ly#b z6y>l8&`kuBY_EY@0G=4Ho{hOb`)GDEov4S@@@QHD;6tA9`L#+qa}g)!2M$rgr(@F_ z_=ZaBxVdc&(;N#J>@!ixPS4?ii}B6v*`^JN*yTeCIy&HCpYX&b9QZYv$XKlk69V2MGJWN(VD-e8|_oG zyYA&=eA|SfpMqnExJL%1n^Aerg`GFJkh_tB@9~N%qpd+9{aRSzHBLYp_WF}WuFGyA z`oCiyKt>9(xPT?UwyK&adS_&KOi(JAR*fq62Mj0;iX&=FARZU_Q4O8kPe^amrHmU!co4EwP{-Mi%Xv*HB*dL6PVPxa zDp$N1Y{XoCuoU_18ec`BI%%Zn=c|1`=JJQqaSw{GHku{h@^{j3-Zp7bGO=1oQhr$EovIH_ zfGGaJ*>$y3;Nl-RUWNajLM+hKK+O5$C|9o_S)#Y75@33!`e%H?&IIrEv^uyQeKqpa&9IqMqQC@^#De5{!kxd+yIxzPA5hS>1l=mU zbqenuOs3y<@Xb5ov>2cy;r9#=;oD+O8t|a3&w~(e28|!$J#A;o(K3BLnrBCoiub_@ zFX~Wo{f&*IWr7r1aoVZRQp z-9-kua{n8KZ_vV+A^!V-#-6MdKQ0kb&gs_+(3R}24{`}jXlR>3^_a;iWts!8U*O;e zxR(6v`(ojykx&dTPABCUq+{JMnm%6T^Z&T|%DAYu?{8;lP#9W}7)k*NB_tFWLP?SC z5@`gaM9Bd`2Bf8>q&r0#1S#nbNeO9?ZhZEj_x^wPdE*N{!r5oX+G~Adozoa<;x*G} z_!RN5xdfC?<(ix1KWv0Abf8>U;GH1y0s|+{R0ijQ)aTW*O&DRjk7vjRDq@TTW+cz} z>w(QE!@iz0dq_e zPZ+?%!u;KT9m}NaD1f~Hj~I(q8T<3#J} z0sg8&8#9Qwqc~Xt&H-+wJFLQ}^R35@N}DFzWgh%b{nUnwy2%acf8(Za=Z)KO9NN$W z2$$Zb5}6Hl8EX6{I>1JXb6hKxu5tFalR5#BS?keRO&-yzP4 z9?ZX+VT&9l#T!OqT7)zz4$a00?0FaA<3~**rIKHyK19Yb3) zVi=)CK+Rp#fqZD%OAzJ$&BTo>kQOEF@`%)|=AUCky?1vbw;%WwKpNLI{fJ@dIzafF zZv2#r(exffJ0Uhbm5!JxZSi3Ll%|WM!bC+a-v>SWf3g83L?EV0#+{VWPLx@`UW0mu zBvsbbFt5o9n{6=ECw0FG7ZvR*pFCZ$$H*3h>{8Im-fS89Jd{XfMWvh&K?3VCj+!|b zTAXEQ%g#|FYY05Bek-L|H zNlb*oLHfSlUJE4&J{d*$%MFwwS%cf*W z;FD>=n_9L(Y6#{R`nb3znCFP+Q)wj=Lay$!Iu^DTd8ERHc}%x^U@%n6nQzoU>g(Iv zd7DLMB~7B5Js!E4w-RY9WU6Z?)pL)II@XE~)Yb$oSdyfafZRke30%kMwfeISZ7~MQ zf|eio7d9PfXXTHlrqY7mGUQ?n)F7L5XCCeb7e7b4?{blHL3j2OZHd(La91WLeLINK*P z>7_J8o7XWD^W}QGcMVQ|gQK}@PqZ9iJV++cM71iU@v2s=X~&o$Mwv2|c}kOlh6Oun zJU?jd?lTPoUOnxtcPnoD^?pJ`Ao{rvy<{~Tg z*Do#};B^1l!~nhXl@3xJ+)f>RTVh0W4bne~vF3(_-LZP@K8OBLg=s<ENuT9fj zogt8Kp`Z!0`ZD7ZH(nOdbccQpChiJvhZ;Q%U+j7gta_HjzJ%^m` zJ~G+2vK+50QMfJ~`Ns6m)&tU$5dG>5>rid0*BlKgI5{B`IAws zr(%s#hon;Ug$gS&H^yf6fEy7A~$8cV^qIj<~f$hjfHEqWa}pW-9!v zbZ|+!xurca0erQj%i*~)7Ut3;i0}eV%dcrx`1L*0O`Wa%9S981@?3$yzrMkF4X6F5 zs-0^c5(!B=ku#AB>ORD)vjalBd48w_E{GZEjN&2G2kIaN|5fXf3?F~}>r*#ber-CV z82)=7KisR)@(wpS%G|{|BiU|?dF?V_EyOr+%&?0R{uX$6eB>e=-QacY!`5KwLpG8D zfk^O2|G5g6ye(bsE=%u0O1)8SXN%vsh{HY@{?3jL-(0kT`kbb?pWTr5;vx%6SlGYl ziRHP~yNpJY{)u6P5Pq8Ld(W`h(+$Lh!w45SApK=VAAe1`eu)0axf1th;8;)|Hg*kk zmH8J*L=7VJ{Y!q)Jp9RePnxeO9O~oa+~wdG_en{>XIJ+S5@1-YpnrPSW~h3Jc2eTD zhl&3HoI1<@Jh=yBs+)n@l`0%2)3!n+ra8E?YJn=){CO~BrR8!znL5UZO{-!UZ)yw| zTs9!$M&=_^E-;)y8Xy5)0Q_j12O=)+Fhc3Yv2DBDg4Ky z_*}O_;l~QJlx_EMT$!*#ICmB{%jg?2HQK_;_8SaYQI&Oud$!*jzb4{u@5Hn%m$ z{5H=q`nIR{3sqI1J}W8x1Ym@Jm&o8IJd3wTw&1(7$?#i!+gl8qO+NfLhTIY~CGX+O z^o#2g{c?hM!)Kk}hFp)do`@!88z|Ex>U4utzuaKA9*ogFpc3+o)gdD8UyHU&EIQz& z!+|rhFu)c+Oed`!B+%7B=%5G%X|`wjB*hOk`BX5FI6$WkOWj`v~d zuC>TQ3n6!B3vY$OeqtK3G6s2-`relv9U`x@mmxM^8Q*Fx%q?$Bm2y4HAbFSK>A}3) zL-zp+@Tk?P&Qja0#mDR?-p+ytU-mZ?DZ{>(uSRAgBf0cX8n)?g;fR3QmFYjeBcji) zk^SoiI}TPe!`bQxM!<(~R_E1`n8G?A)AI@cg;q_kk1}N5k5}3<-1@GN?|*R%JREsG zBZQAS1$Q;1sKhPQcGdiQe>%-X3D+xxQi$`jTcIjz&K*(Z$aFeAQ{Ggbr)KFo$(p$_ zOjym+hf~T>m0Y!)Uf`TRctYq3j#^l1*|TpXIZE|sZ0J$^U@SEoend{(c*XU3mjZuE zX3#?K1+O*glT@yQ^q(Z+*mqYID?dLJV`d}aNgi93(4E4OcKDw z^~ET%AIRTcy=5hm53~RTQeu16!}lq_<(m$w*`PQf+SQgxI&=d3jBQmndqX;+au=^c z8n>tvkjfFzi1S!l>gz|>{?6;l0O+q!>XrN!y|{|=&EcIqcZD^QJPuxO=gi%vHGHj~ z*{#j-|5w7Wn-~06vR@xPW_CXkl$~*&WV{>Y!G{OW}y&OwZwsBnf!ntA9Z ze%)5UUa(bidW)lj6vxZ@a*1kZH!Uw1g|N~$%+HcmCkHDw<3y(k(+xt>{Z-RuwKz{G zV7NF2X^I7<(QiMdVdrh|0@Uy|p*2K25ht2~rVs{bfREVezE}&}JBuCXqlszKLch=v zB=Ad>%|tr7*Gl(=hfZ9FIE0PZR{vB^<-Lo{SRXF`*xRsAo)-`CuF>Dx)yR*Tildxz z5H@tP7K*sH^*(@?WMSCWTjf?tz3aKR$mzGaW@go4mq=fv1)f#|k8&a13@1aQc=HJTkr%8HC?bwn5=XaLnt-sU;=WDP zASP!2Z3W^FnkO_DB1YJ^bSG#z;V{D5R!RB|rE>VliiS+qK+A$MZ|efemrMg8XGJ{? zXo9G$51&~rA;+Pm8S=fWebxJhUR@n?v;H8?vYBkZ9()w+S*VgTaAy@8tJzeq!QsiZ zKC?DX71iT=-E<1@jMVM-Px8c1iu?PmTn(>I65p-b8?VR=wRkS_LgyhroSNZ{w9Evh zuxz=NXP~CR=FM>8yAh>k@8X5J^waxC;8m5-(g$}HuNjEdILUC@Dd<=b!ydGKCh)Jw zTdd6Kw>nCw-+!v()+&fmk8p64EF*YHs*U#?vB8gKr>Ve6WD^#;jD z?9IpV4>$o_t)l!U^NCm*_JPMKQIz=8G#0C!8zlE#;yCo`#0L)O)JcAA4&N6l7AS>& zD-osGzinNy8RM5X9kH_gZfO6-MpB*R5E`necYh7=b++Em&(TC~lttGQEjHbI>+h{& zHmmo|eR`oqHbyeBreS(|5TR1*I_g>px_oQCQpHX62{@w`-I$oxLzx|tw>hM(I+&Pj zdarCJ>50kKpD8T)ToKYi{CcgK{VSVpogx50Rq_LY!Gz>t=i0i%Ym&-UcWFBXTMA1w zWwz?QtxmsuWDsI*eh&4aWyP0+aG zJ1~(8^8+k9+UO3Ecq8IEMi@YNO+h6`5*1eeF_+ij!w7fwrH#02nIqXL^!jj zq0vyg2Gl5tV#X$)s_6zY?b>OD;s6#|W(P|`H|2agw?rn%( z5DkSD+nrHM6)k!(kJO0wK8zGVWMf}lh*#pQZ;p>UeJg$7VNe3x8DsTbvf;J;srD_8 zhrZ2O4&;_cN2DaAB7=;1A!INVwgEkUM{t>DU5Qg}_qmI{%=<9$MxpeUAgGVmDNq8` z$RUQ(R6pFi3n{lc-&6T;FM@`io8Hvq1wsmU+Z7@n$e#IKA4uvyx$nqY0&#~I(dMxA zRq{7biF}pDUoqxokDaZfQDiC$z#g1mZytO@BnNvqBo>Q+SDmH)?l9xkM|f2Ctt#0S z{MC%^Tk%hdBZ3f*;5o;`NTZqp+&CsIlYE#3ED0)}w!@J`3uf}3xu z)2d2-K06*cKE_9Z?;%q<&sRAY5t|DzN}admX5^5;M2}|QK$~#T>5?a3_KZ?T)NSti zdiA)s`||qGz#d{MhY`M79sIsij86HVqG#4Mwuo#dDxv&r=|ifSU6pNS&TId0`Iv41 zY4H_{7IK(ENuHU`Dt$hF7cszbuB9ul7%=z|hh58~)MA#j8&o}$5QHx%p0THmmSALMM6?&zKY5dP0)!#86HUPGL@#IpON{fzLMg zW_k+pS0fHRm?QMMROJ0eFxHUi_qJcLyv4mqM?n%sW*tK>f z7xO4Wu-Ma9MK8p8kmQ!^GDwz*aVNH#T?l6&J2-bNUM^7F3JD||iuc8rnh z4QFH;F*bg5@wJ&Bo`ftoq+DBn9GCvTZ>stbvFCX8OaIK*8#6e3Pd-)Td?>?`>UGaB zZ{(=~OCx81faOT_CNlW$#BLVcC0(VTtaE&=oQklR)`~R?>>&$t zqo+}|)U1XB+8}?%@Q-HT?<$`LqX7lCRHm#Bd0NB$`0?Vt$8=@Lj~8jhGeR!m82G3q zJQ={)vKz}@9u!vi+4&>ztXEP?TZ9|;<(u0rLcI#mWU>MMh{)wal@Z|9*BnU#&(NQt z9o|51ZeloAp7Ph5JojzG+YV2@^rm_)vC@&jH1Tj5T`mzqcd*u2zJJbOZ+yfE;G`>e z#33c|#Pdo<}o+xGBJF3Qpc89T@kaCNsWJHW+AY(fJcaTU zWSB9sp^4E0kM~!ls`xn?bW=`fQY^P7ilfTP@JcpNxveWzyAg9i8af*DZJued?8c1X zV%h1hjwO-@f?8HX2fH1=)i73Z+GA0mF`#t&9+2gl!NLxP^EB$zv&_1GCy6?w(*RAv zCXEO?QBQJA!%U?(E`uTt)HoA8raZTU_GmwXjNaQtsG`u`-=FPf{%eA%i?Pi&|KJbmIp8QmiD%?AmmF151EW!oYefE*)zfAKOUjpSu1 z#FhG8(5@IA%Xppy+`2eg%u%Jef=(D-78{>9_<;XD zbaP$85k>6E94jIrDWfb1bgF?8)k+A))sfu&S)v#&`(Kiv8YT1D$HSX5Ecgy;iO>^O zP&%f^dIh(n&G|7F_CYoc8EkI0p^xw?o~mCdsMs~G4dU}Ydm=vI zT^;i4X?SiHj#;H~BF^?rid#2x$RsK8+V|7eMm&1Oi2(Dh;`H-L!qFj5hWu8FgAxMu zo{{Xxn$rXm>qon;v{?AK{W~>YghIIWlluDuc`v#^L{V3H!qWAYqh{j|gTAgc5AyN{}tg z_=Xge;QlzqB^+{>Qt>%V9z-vg1nOC1Isx#>$pfh64_X1hqaK``cL14|``@4aT=P-< zKR5=L!8cNi(g_H>{$QqnmS9MiG4jFg!e3H^I&37mER>HLbhcz>$P+v`=p4)%u9w6i zAiT*67q4^6 zYplUuOJsw;Zwpax`|g+sQvdU$SvnykaLb|71(<|_{N$cgz;&vPXs8NV0BZ=6`PR)` z$VFCLNSq?##gj^bNhX{yPz8eP0lcpz9z8`4_+6D9K@~9QOSlRAkx6K}A;Y!K_n4Ub zFl!PLH7TR-mG-69-P9kTJDZu0txnftuOIIRkVboqaB9Kj=jMi9e=gKw2pG)F*}tz* zpt2TxnlxGZ&^Rq^xV+dB%4*Tz)i)-ywii6{mPq#!Snm| zRBNNUn{6X6Cx7RTmvL@kd_Ld*O5|7@`nmAoAGGOmc?J=X6Hp(C$RS$&{PQ;Y(;j`B z4TJ5UB}PWlKnFmVwG~P-W+n;A;hos0Upd<5Yqk8vtG0zl_~Dc$Dr^m*lU?xeV6TZ0Dt?S;kB4xo}dRdIxqwc_AB98fml|ly*l%w$(6Vu0M(Xj5cQ0J}Sf`I%;_D4xa zREYDn_8slAA)b*N6-+E$taoH~C5FDTl8r#2_D!XV^cbxhGNYx=oFi#}flFM5X3K=0 zT8;FZzMCq(A)i<{v5xUjbV0fVCG; zctjdm_I+`+R@Pf1(A3_7(Bac%>L{Q8tg~u7?6dVm<2)v&rMe{$n8ai2pDK|+RbU7B zxT`8JIDXZ_Pz zMQG|^>hp(APCDc#9Ewc{m5Z!@q}bi^J5=y zh=ipOh2|#N&aF)^$Wqga^?LQ9G;cYjTWS;F78Y4ctXEO|Jw9l_nGmZ#v?V~64$u@z zp;S4=LC|ebkPPmx&TRtLkISHKR{xObTM@4QlXrPoEx;ePtpf#*E$0w_@FJAer&k^v zRjpPLV=7*As){w-zlE{rLI30Q8*`?=qIs{F_k~+lm)|z#9tts5S zV?a9V{u&S942Q>G%J)9ioLr}6XuJ@l2*wXq#V7sWnWY}G%QkD;VTO21St$1fANK8H z7#oqna04l>J$qB%go`UBnf26i=N)|3y*kE!v;Qd>Y_g`%upc226nw2bUF&eYco+rq z@f$5TY%AZlZW1b=U2x_EQU9OdLn8;ewyJZ(Tu5Pjux5mCQQ_2eDJCr0!)-+G)%h>F z^zU|!W(x_b08r(Tk28PrK(OZ(XS&+Ba407%?n`~8z=O8q{H%?K-(&4N^mL1+PDJ-y zC)4(=8>@bKUO%i@()kBP2jN=qs*~8^VUc$JOn4y)h_-)@G}u6IMG)UVd3yg#9-z+_ zky!)vb&^N_dk^&70)o3tg?OM~`=1LV3%Cp;J{dEiI`xK;AuX7GoOA1*!U$Nb-**bM7yC+j_v|MLes0Taan zyiNXRA?aYW|F>Q{EH+bID?1LF==<*vK>;G7D3C6)7@P3@cMiaj{D+44cVg(B5Yo4t z@Y^LlD_zxJ7HKgw7S-MCPI@Kbep_>-C^#0=ke=T1u#2}8WMKQR?U8?}R0iKlVzky0 zh)0zXrQ;Q@<$Sring+JxDkG1i+B077F1$-;J{IK+j>UDq>2Lfj!|lVpf&8bERUXSQ zoNxcWtUxz%5f944t1C!7T*!%&skjKA3BI)Ds}*qx3=Rq@{iS?i5?zYG(Y`^Ps@2OFIb-hcL{ zv4+xbd%!f0;>$R=*ZMlGHaFJbkY}A9AGM<~-hZfLFkWo4`lhQ|A!oEJw$L5pJdING z4l=@N5mYRlh>3&N^?xW{un)(_>e(d0hHuQn!aQfzI{l#yPb{?A{Yk?|`X}JvGMGJU zjT9oe%kv%lm(jVDsojC%z6TL+%>Kj%@Up&G%du}`piSa6S=;os!dlFK4m8+A+ZJc% z)*Y8z2~F|8Dk*Tv^x)`=)Bb2n=KoBrAhtELO;(;*$I!1jCOcyv9fZ$0|Dj&feZQQZ zA4h%Vu{p!dp;Xc=OgR12m;6*_Mky}2IO5MQ|9z9Y0;610Q9Ar*i_cphbs+Jy?l}55 zxo>AM^20A>eSgC5-{;xBCA=C{HP~kV%Z|kJ;-}>6k_|_YaDUzGg(ddV>i-7S2FT*T z(9j3NSI|$6{C3AJ^O+yBGg8m>_%$U?2tS|lO0ANs6#qRBf1_Zw@v;OJcfBH;X?o|POP4i;D&%97I??!Si` zdqQ4sl#eVfz0EmJo#wWr$;<2EKeZE7K?J^50B5^UW?wyzSek8pUJ^y zoX1&oZ9hI#vp@xyiCTC6cp@*C82!%}v%6NhLSUftDlmPkI6$Gq%kHkj*`KG{%d4uvQ{-RQ%w_5;GhHVJ zJFoOyq{C{K#AJ5;WmJBxWe!I4z&}ijpnafS=9_{{F-NjtUVRV-O5A zkAQL{aGzyh5QhPOQQl&Zb{Saf%MAj?jh?WJVC8#gGJ0qkFk)3up6n;|EU;FpV%RqB z=5S|ekVkP5mr6w;q~AFF-fM@D#Y$qP9ZrcEVH=$gQ{15OcSCs7UX1d?EPPD&%{kC!9YClZ)}d$2uvfyH6}$kspM5E!&gC#p?X&BafX zWM;At&Uw}s{RI$>~cy--xX|TtTk-VJN?N5 z*D(%c|BnI2_7;4Leu8bP+PQn!i1Vpg(AoUOzH#CW32(QmS%B_od$KvJFhM+OGw8(d+=vsp7{ z-@aTlS|J=?wCV6)X#nnWDj^QFg8Ow|j=<{3c*pexr2v0*GgkVYRJH4nIPw|<=;zO( z?veLR^~t^W-^=M#iDBjx$*KrFCiq}e)6hMU-KaV?EdXw!hNH zD4Tq%6H8*#9&pwR4SdeWIdI{oS3cF6X*-Duuxem&q$ljCueawJ74Su#`8Y~- zc)I-1@zXi>eWr?FvOfgsdjb0L`IJ%|9-SeU%} zD{M~0;fSZNj1D*NVPRgwED4%(oZqWDz;ACnde!Mvuhkk^uVqFo{O_DRkU%s^;OJmV za&Ng?KP1c zN*EG8fAb1$b6OQI&Npuzfck7KQ~Br+KNzJQ+#rXohwje5QW$@iS42p;X2A9{D9S?!_@Dt5N^t}-!us`tiN z@AXEo-<}uKmb2@?;Z%Zj6ZV8C{K5j3mLnY{i%_V`q`$$4G8resQNTIzWAv=#_p5GM zS>Ew!$M(IVI+rA;pcan5e%jv=Wp!UT;TaV%0kEugqiiK`(PHk;^I6-qpGVTxgfpRU z+h-pL-g?*fN6G^Z|C|!q6JF%xsSn7@2(&vY4w>>uGK+`GTHuZccQga0E8OljmVEN) zD-qyBCe*{|$FHMh(`+3tfzz~F8-F+8UyVCt8%YGlI`q-79z+v<~>JNw8BUetX;md*I-FW^TFc!R66luv$_En0511+np>=m0t#t9$glU1|cLeh-TS7`G-6uMGb<654uI%O*X$*N#81eh5A7anOx#T)Uyz`zSaTb3zIl@HO!}H;Z}6YzIrUuVRXjM!rsgA=!+m*j ztb8e{kqE?4$@yNsfmVU!7!U(|DBhZ0cTG+L;Y90K2Zd^X5h5-xmPQmeD8@8ZLGVX{ zA1<_>4jH)`>9g9(-w7JTL`!p;_ld){Lg{1H?%plUG7uTxT)W-S**qPAN(^kYnaUoRa*yrjCI9*%lpB%)HNM35TV z=o!ZJ?5pJZGct<0ph!+PEGf!C&>H{=g0j8f@{gxeGjGa_K!FZSLlQCpFaAFl6 z=#3rc_3Vm1OU3H6R|a7I`q@-b(aTHK7r=e#U1$H zhpxbdq`6~0aO7S`T}!2hVMuBBVPIkiPgc~6<$tY{RDi1sOBj1R7TJwfBpo!W5d|G9 zAZ)S_@ig)0y|MhjiTAhAYrYF#%mvPCp?KVQSwz>>1#C8B9oA23V{%hG1Ry7qd5Vdt zKg7+U!wl{_kO2HGtpW|Vh(Q;ucnyJ~xO~85zkxbWt>{T}h2dkfvDu~r{V~LztYM~D zypT&fRcfv$p8qv|dkh;}l?le$i!NXz9NrnV9?dm98#v_#R3>xvq_ zs{%DhhvjcVAm!`R_ZV){CLy6Q$r(gcQx1IUas_t8EfN?YcLjs^pzNTY&KWlhybms2ip{P&me~SORH&?l|2dI8$IUUX>!3_il5- zKV*TD^W#Sckm-GZ8gtTM;h{wQ)PfEOhhOyZZQErDNE*Uu*nY1nuWz#JcOP z_u6U*os6>!a_5XnU)DKYx8PXaK4?S)4N0dPrhZe3xuh zjAzTcx2_V7&x`-azS80F{Zc8-u^sIv8c?UUjesR_}mi$En@lOl}RR#R=L@YdG6j5PqLel{Wd0_ zXz>21@*&|0%wPZ>=qF0g;sLCOV9}f1p*t6IEpj*a)N0T_K!bQP0Z8bEXX8gJBib>$ zVh*h`@eH=tc`wFDS!BnP7%==F$_!h14ixByv6s5UWK%4Vx4U$)k^D+(!dAK3nt{=-%8fl%F%A{ zx8OpJe~r+1?lj(jL3q^N5_&kT>HGwoIN$~hB@jm}V04yz_0L=)_?%pg{5d{Xa(|ccVUzf5oqMjf{K}}EOu&f7*!_9(Otz4agw;|v3m`uR z1mhi?i<@%`(|ndg#o$1`!@RUm!BZOiqeDwDu*qt$ffYao=Oj=|Kmd*Tpm$jn=%q5d zza|iA=}3|H9Xs&N{My6TC&4jqgX3BIc{`U1v!uBKR$lHhRzC647V*LcPcWWr4+p?O zJaq0M6pGGuW!fvn->4-MJrftk#JKK<)hTRjTn99I*Kqq6?trpu|LpL_y}zXsEBtqo zE5B6-M~BaQU@prvgYkYfuLsPX)#kDlg9KB1{009)**hG;BLT@hCXYP1Z@h0SazmgqGXfO6;O zg6w#*gCKn&_cZ6mT5?37K|xI;c@+*1eI6bMU&0vrdLuDeIB&u>Ym3~ z(sHmpFDf2ZJrA+2J-2|%RsS<(#YnWbuiLeS8n!fq1j5%C*H8h6m8B4!&=}!*tH3i) za5j?&R;9T(bRx~4N&eY{pda5<=W(dl?V>~cXfw{__dv7BMo0+l#@|i?DNZh1u>NtC z9WW?JbTBT(=ZYm9LEO23s8MVxD-u?gB^e3Og+Z>xp}FYhs5~M7MIx z8a87rb{u*IQW%z&sOLv&+v@zZ%PZbZ4ovpbmtH01 z{5Gm@wsvhsG`)})_!pgRJd(q1rYka(zBz=ZLcSsOu3e}2D234`oT@1&>#-RYdauAx z>G4gW*#CXWR|!Z9ThH^f{E29;epO@Bflq?t5lJ~ChE=DDG!I-PGn>1k#3kQ;LpDm9 zj%C~DYCuW)MDEBKtnZbQkV&b<^VF!I-cL!?BkFzrWXseXo`F;MgQO3~*~YANx*0!-M$AsXu=Y zY8*+VSOJ!hmYUKZFQKn{_)Qp0=F3ne zW~aleX2H%`I*jv&d84|Yg9C$9lu0<@*N>Q>PvsHVgmlKLjBt1x*OW@{A#FqY=clyM zF0?`)fW=IVV?GJ~c(mb6wa_N#J})zCWwI{X69{_e-iC93wqn_8Zn2-;6o3BVj<{?6 z9tln|xUn3>fTihzs_Y#6FK+ntd~5qYWA8;^0Mo>9lVaWbys{m@?(mch#>ov7Q#Mq$ z9Aq%QTnJaIgdwlT6jU%^5%iM*6^)fBD?L!o==|{l)gLk9Y|=@|WGMobU+>>H{a(H{ z>EYJNfRDlh?Kxf2khN~dpA#;?R}9peSmBRKkjS89zQ@&v%WO+x7u8B2OSpywbZT%C z$GJE6+2we7pMK220**c97j%GD*bxV9w8+BHa)C$ttKX8?R0UrhUJ=#%By*Ol5rwnV z>-b9+gp5O`6vZh=Kvt_D0H#gthKbqv{@J{`Tx27`tAclyrCpRvh1sqd3&T4J$we2tx)w;?hixE~-svKJ((e0FQfL{l z;t_{wuFk))fZ7*$JaKWcFCIa>WsL5zf$j*sl3yQX`|Qu98$JC!hmTr?daVZPh|ZT>EpWWw*^iV9NvBL1x#joinLY{oyYG`=$tF0@ym<`u`na<2rxD{C_j73314P14oW9u zhNI$Vg;pQ$y&Q@F20uGncU?}VxukgKw@u=@n)JtmBT=_rD{NEP$c)0#5tq)K>0+Uhxc=9P)8G(g;W zr#^;KmJ{sr$KaJI0A@y;udWI;@9Jr@dl8}6_9lR5^Z9KBOibSA3_Ct_%ww5;&2*5) zx|AbY<(S&cWxuY4Vbx}3D73NIz&|HLb>w;YsNn{iy1V=ERZSogo}Y~bFtW@g3pLko zspWZixGpFMu`fZw@x7@DaWRpC@KU6Wg$%0kK{}>b$>UKc&_XrE1yu)4eF*6cqrO7S zE`v~-@ID16rlq6u@yxBvIcE*x6Of>%d;Nmt99cZe8)I)F4fZ!uuj{Do3GMNCS}EVP9VNb6 zM>zO%Zc>o45aUHc61lvz{9XyQ?$WRz`wlq4iHgH}IX~xAs{$jr4aEzjZE#X)L6>aG zAwGSfLpGe$%jgLTQd9ta@91leSO%s zoe*|C_ZzxRh`5A;(8CpYb);6fqnTcW&W6pfw)m-WG7BbHzWRrR14>V>%3<;GzQ<)s zfCfcf#KMH#%oO4z(Lq`Vv9oH{BMyS%CE-~)Ghcp-n*W#{oeWQ50?HEPtYBy#M9F*qzCmr_G zq3KKeI+i#&c038V^!ixP3+X;lQcwA{ej<)FIzVuM*m23lKJ?%#P{~;By`)@Yl@Ks{ z#F9h0I0HVq!o&6*nR@}O@xwe)>2SzhE?qmxWEe-9VSoT$dz51Zi`nEW%ZU^1?Si@Y z&)AKgU>B9|^KzOoGH z4Am*8yMLYkWk&-m{3j`lHVQ$DD;&IL<^$pi%~g8-M-RpGTOgL&up*o8UF6i+P_*%J4hp^J8uJl3S5h%VF0>O zv%$u`fcZR&v0a40x`E$4lGVb#522&tVz!`*5s{3vfZtvFoZvSg2w;bgwxN}a+Zx-aVdf}rf>(6PdsSx=cQoh(x^#oMSU}tUDOP5;>w|<0A1?6Z> zbHGtn3c>P9y$n=3&`(GNSy0(CDkjQTNrwHE0C7iE&sI-I`V1G^;C!2`n_gSQfRg~V zn{<5xWFNz1H%9>QuwRh<;v`hW0MaD+j<~q#7%S@8+X#Fz z&+oaAZ}RLrX?OVHaBy8$7Yg9Y0HML+lAUNe@+>06PmNFd_x)7&v-`B2GY!~(cx!`G z)-}Va-ws;K%U;UpTf6#~?%@wq5=q`b3Fz&$%x1jyAolI3E+*z^=B3e(0vP?s4$nb1 zD+$!=qpunADnP%NoK5cMrdBwoy6*z`8gQFZgaPkrB<3>IfsekKr@5I5>f=hval=|R zKWmx)fbmZ?m&9_ZiMxL>zi`C|CK1@s>=ZB-|I6v~2oQf3vCP z4%G|=q>2cG4<8=enW21vi59-&jg1@`KvI>!uo@lLp22Zl>DQdN@&!^4hp&g0Oq*F# z|MB+C*+Y41>|(f*9j*W|=ffULt^Q>>X8sF>zy)3r3w=+PUb(y<`#&D|s@*AdWf8Pj z2SxF`ei_Ljm-v3^z+RQfWZ~#3&&wTF?J5uPkW2mc_6HtEMWUedVzH2Sv1D8XBQ5ek z3!lUef7M*>zVq!=%*@pO4tO&^4pFZM@Y&w+25B5sdK$j_8pFB6Dt)(_$-D8pnJ>+S zh(uQ&m!}bE)FBcJ=glD>*VDM6qM72c?r~N)Q9m*F6Uwk`s%JxMG%)H2>l@5-PoMSJ z^1QG>odhga$=XMIz^`kWlfBpO%oKUvJYJsXdlf%Asm?Xq6cvO+ATtg=>1u9ime^#|^X@#YO#z*vOJyJ4(?n0$hOS0HcAtfTyd!GDphBadAyGzteim%dou`L^ zRv?twZ0UK1M5pzYGBSw zO@(AGATF8veXN=H68**TB4uK^pZ%Y7_!}I{twaxIK!)g=fwbsJtYuKW*{#Ajkp69u z$K*&$yWaLgt=m2!%hy2pWRKgRy9l%KncC~m!@F}^hN_HA#?9n89z7IcTU&Zz=eqAr zmvnD0Oyjf-RX2FNR#!~7iv)Hs@YNXLWE`%(VLmX7_AoZMx>umhuA2s;5%ZH;(}|zu zY&wOj1lm3)dwyVvbDLI~XaLNt<{vX-tIzd)N8qgy`pgsv2?`ItCOyLXt^GE%l-Z_G zC+QCFKqhFz9rh|4nQeh9mEQO)l=iSlXaCd?Nb493Ja9@W#?uPTa+-pNFsa+VpVA z77QvoPn~-X+ZUT2a-G!l`Y#=e_RdD~4OV_D&$JqTH3%++-M%q4vz8s_Odc0a0+TDp z?!B&qX>Juhjb2%bwB6I3w>LcMTn~!3RF(QRhUJsXDwevF3@lpbKAuWb)E4yGi+Rp> z#CTSu#rdF4%gq((41amfG)M~Kz_18UA3T3GjeU*(-RX4EM70@c<` zkBckF1q1Kptvy>RN+M;0U|vC{M8zucGfYq!c^cNdOnkpedb~TpPfUpj{6O1(Re80K z&vAm2_VHBpzJi`!LRGFZ>0pU9w_|T?z|Zh1g07~7a&Tx@YmJGN&MMyzgH1<04Bl7s5e@I(4BNK3p#rwuFtNIXlj$X7Xww3oZF^FMs96 zq3DS=?tE48A47aRYCIQdyKbDEnzh{;}?W8r^7`*xO!Dc zt6dR2{7B#9d$m`t_~!pCDJhBL&mDcBlGciKi_~uIY_NDpxxoS!zrXPArBbT*Ys*t< z2_Ynz=1KjGyT>~Zu18tHWf*(WoZrVpal2uxDMJml-n8v5TO#dykLCE8+C-mkCf*r- zORjzp==}LpS7${>HSg%Aj!N*8POrZp9-NPU%1!?eJBiK}#`4O#yU3uAQ$J1k#1YpgM^=7C%pjZR2L zMLA!`wd>U$cHgHCK1V+%A1%APIqkM?#AD@_g;qdH%u*+QGEDdXJyV+ zogFPS!A-R{xjJua8Dl}gt)~oobViFH6C~rl5g10=bcE8%=D;$e$HEIvtrQnd9$s zsNxP3uI|gR=3B(DVns)DPQ-$)^OTV{@H=#Vdj+}P!(1uRotd2W3i; zA&YTBK3U{R?1C3PJ#t>ZrAKP;DQ!ofkH&+jjYM@Lp|w-HjIh z0BiHS^hoam&kbbxdLkt*{K}OSEn;%Snf~_y4U7h(jf(890moGB8@H}ci0ggD4t_4_ z9!VeHM}B8g^r|1>%+2jWec=ff?ahcB-fpcU?67(I=cRV1*c3DPCRh4*%WYKaW$DGH z_^igp^xTyT%53RUigh?Y##=f#tMYnuynjhx?bVB9wOBq?wR>y31{bejsH+Se<>B1- zsq8G7l*E$1ff#B}Dr2f?HXwoGUb%u9hT^ud$y-wDeD_KepPqe%i~e2clVS|(85W6) zG3cniZ3b+o->u3|;^EA+3mHe;07-!oF1$YDPU?6N?>=(bQ@{x`7sq5Sza%SZ-e77& zqh^!mHh3C+TG)>oX89lDKP2f76%@_lpfZ@7K3G?-Kz!MCudTXd(WdOJPlqneJLNDK z)I?go{($}Mq1Su*#WqL8r^UjTjdD~x%Px;s36g}JB`Rtj+gZjK9b?1%XaruUnOwn( z)-NXG+dE&;Bl5$DYC;hbJ5`LShyK6vuKbCE+S+OhwKR&hLB-y&RaL~6G{K~#5nJqgka?%yKjZuUc%SDz=iJY^ zXL;^(@8_oMSj1W`rgIGDIXd9;s8(l*WeT1Q1Rwz50Qigd`qlA&K6vuP03=Ypp-i3e zKZiE69Kt8Fr8H)HZep69ek(8}OM5~S@uO(F4%cQ-ww_=Pd9KB3**`*hq`0G8Ki&m?{r&z9V5N;Amw zMjGM*uJ~Z6HU}Vtf${MqH%?l8-{OwS#9diDd5^N`x;7?**&cqg?L5y-R*!%CjU^AS z5z2two)mddBw#~4mSY;uENhWj&#X^Y859!y0Y08@4Rfyz9$+l^mPBr+?|26UeQU_1 z5@C;ocQoL60~2b3)A_84M!nC*7xiMM-klYe#bm!wp^saGr<8m5ws;q$PDKEIU^&2a zS6s?wi8uQk%jMo9!|Fk-ZtLF$i$_5VB2X6{f?>YHSY7#qg+v5v-I(t2)K^pk z?SPSy8&3H1qnd@N#(!x|RAbnbHeC~5dhMn3K_Z08BIegN;$HKM-v~8WNllF$UTDmH z2*3|o0e}YX{(29y(yP|EeNjbqgE{v%Cv%i&LB8XOK^%DMpeJ~7Nkle8Z(=#>?vy`> zCx53zulJ8~gUk$HX#J$FfoYuU*MfDtWq%~jb_o;)2OQf{Q&ab!XNm#9?%ZnM-2R5# z#K%^z!K5Hjov3KYM9- zAUQYahW05r0N8S)zI~qFC?=Vp1ARA}D=F3RA>^|ReZ0A5bcAG>n<p9)Wgx2MaR0CJ=n_eJ{*xuzYMg3|Cqjf!sjs~OPW=kx#Pdet@J>Nho*p-yV)T)$5 zR&1cq=S%5ZRQ*;d!Z0n}%&;$i2CrH*y;@k#blcd?l_NvLVW%X(QbxUfY0vr2nJv+L zW*a#k^;+r(T9mfnVP=2h){Y)lsj%*o`RMf~;@z}s$ddj*T4|yb)Ds0o4gZ8y?>9gw z_;49xrEE7=vTv$$E6;L#)r01od|u)pTVbGRm3Cxi|?EYd15dNaOFtcr6CZk7P7O56u^ z-tmk?j)Ee;eoTBu+7$vEOlNH_T;SJFJ;9`%J&ixEJKw(-H8E05hAswi7#Ow8cmU9~ zM+XOw4K%41*vCU_gCbT9SeI5W@ZTaF^i{_|*<(<0ISp*6}FIKg; zc6Ph*#z@pB-)_kORyR|^(ILH%u&MhI4~zb;stUe2BEV7E6wHhPfO}W&ITt)uh9*=- z>pT>HIXiT_ux@NTW=HWP2>d6*tBF%hWj^~)6C@Chc%<@7TI`hf(Eh>Bj7HGMwRPf} zU+z1|D}06)GAVK7+Ib014mGRS3;;Aw%S{d+s|-aqKI;ON!Ye15mPdZugwft|?M5bU zNds2X4)&isxv8B$H_Idbgf};aFZRri1cC4LUZXp%#R7orUu%N-$`A-Pf=j@p8MJ}; zxc?WiEo(8?TW(c($lRO}0W{W1W;@nGuf=e`jD|0{iNNF$!dJLoS0<{#1kRlEE^dje za>*lk3jwkgH5oAvXe{$Hdj8)R_M*F|rSQiIgSv}*iLL942EQ;_%ds5qmnfLavtC00 zn79P{{JpEQQ?)nCBuHII^I?(hdkZqZj1<-%XpnWODUIpV< zd}3H9L~P{|FEFLoCz{yZa$(%}#`^jT9Wz4026^aCe?N(w}OqB z<9$rAOx+8h)|5$~Le@`qz~(lyz&R=TI?DU6U{udQm<<1jkSrtigCp&W4U1MZ{pJmy z@#&m6WY`xO$1?It*5S_I?}7cWd_>mo@11At{7ql5hF!}n(!feJvONU)l+N~+urrHS vGm8sx|2dM79oyubSTxNA{+~bDTl)uut);(jK7BCo9}brgb~aUT-+TW8RwO&D literal 56364 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 AV*mgE From e7169072edd19a93130f51817fe82ef7a13d6533 Mon Sep 17 00:00:00 2001 From: Kartik Chandran Date: Sun, 27 Sep 2020 18:11:16 -0700 Subject: [PATCH 010/175] Complete all the renaming of global to chassis --- doc/voq/architecture.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/voq/architecture.md b/doc/voq/architecture.md index 96299f95ef0..38c81c21f95 100644 --- a/doc/voq/architecture.md +++ b/doc/voq/architecture.md @@ -115,43 +115,43 @@ All state of global interest to the entire system is stored in the SSI in a new The Chassis DB is hosted in a new redis instance called `redis_chassis`. This new redis instance runs in a new container known as `docker-database-chassis`. This ensures both that the global state is isolated from the rest of the databases in the instance and can also be conditionally started only on the SSI. -### 2.3.1.1 Starting redis_global in the SSI +### 2.3.1.1 Starting redis_chassis in the SSI -To detect if the `docker-database-global` container needs to be started, a new configuration file called `globaldb.conf` is introduced at `/usr/share/sonic/device//globaldb.conf`. +To detect if the `docker-database-chassis` container needs to be started, a new configuration file called `chassisdb.conf` is introduced at `/usr/share/sonic/device//chassis.conf`. The contents of this file will be ``` -start_global_db=1 -global_db_address= +start_chassis_db=1 +chassis_db_address= ``` Since this is a per-platform file, the IP address to host the redis instance can be platform specific and the platform implementation is expected to provide connectivity to this IP address for all the sonic instances running within the system. -A new systemd service `config-globaldb` starts the docker-database-global container in the SSI by inspecting the contents of the `globaldb.conf` file. +A new systemd service `config-chassisdb` starts the docker-database-chassis container in the SSI by inspecting the contents of the `chassisdb.conf` file. -### 2.3.1.2 Connecting to redis_global from FSI -In the FSI, the contents of `/usr/share/sonic/device//globaldb.conf` are +### 2.3.1.2 Connecting to redis_chassis from FSI +In the FSI, the contents of `/usr/share/sonic/device//chassisdb.conf` are ``` -global_db_address= +chassis_db_address= ``` -The `docker-database-global` container does not have to start in the FSI. However, the FSIs do need to connect to the `redis_global` redis instance that is running in the SSI. To achieve this, the `config-globaldb` service in the FSI read the contents of `globaldb.conf` and populate `/etc/hosts` with the IP address for the `redis_global.server` host. The per-ASIC database_config.json includes the redis_global instance information so that orchagent in FSI can connect to the global DB. The server name `redis_global.server` is used here to describe the reachability of the redis_global redis instance. +The `docker-database-chassis` container does not have to start in the FSI. However, the FSIs do need to connect to the `redis_chassis` redis instance that is running in the SSI. To achieve this, the `config-chassisdb` service in the FSI read the contents of `chassisdb.conf` and populate `/etc/hosts` with the IP address for the `redis_chassis.server` host. The per-ASIC database_config.json includes the redis_chassis instance information so that orchagent in FSI can connect to the chassis DB. The server name `redis_chassis.server` is used here to describe the reachability of the redis_chassis redis instance. ``` database_config.json: - "redis_global":{ - "hostname" : "redis_global.server", + "redis_chassis":{ + "hostname" : "redis_chassis.server", "port": 6385, - "unix_socket_path": "/var/run/redis-global/redis_global.sock", + "unix_socket_path": "/var/run/redis-chassis/redis_chassis.sock", "unix_socket_perm" : 777 } - "GLOBAL_APP_DB" : { + "CHASSIS_APP_DB" : { "id" : 8, "separator": ":", - "instance" : "redis_global" + "instance" : "redis_chassis" } ``` -As described earlier, the platform implementation is responsible for providing IP connectivity to the redis_global.server throughout the system. For example, this IP address could be in a 127.1/16 subnet so that the traffic is limited to staying within the system. The exact mechanisms for this IP connectivity is outside the scope of this document. +As described earlier, the platform implementation is responsible for providing IP connectivity to the redis_chassis.server throughout the system. For example, this IP address could be in a 127.1/16 subnet so that the traffic is limited to staying within the system. The exact mechanisms for this IP connectivity is outside the scope of this document. ## 2.4 Chip Management There are two kinds of chips that are of interest From 7bc809c01864502d5031ac03e5c0b39650857382 Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Mon, 16 Nov 2020 10:15:19 -0800 Subject: [PATCH 011/175] MPLS HLD initial revision --- doc/mpls/MPLS_hld.md | 390 ++++++++++++++++++++++ doc/mpls/images/MPLS_overview_diagram.png | Bin 0 -> 54032 bytes 2 files changed, 390 insertions(+) create mode 100644 doc/mpls/MPLS_hld.md create mode 100644 doc/mpls/images/MPLS_overview_diagram.png diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md new file mode 100644 index 00000000000..11584e0c1a5 --- /dev/null +++ b/doc/mpls/MPLS_hld.md @@ -0,0 +1,390 @@ +# MPLS and Weighted ECMP Routes for SONiC High Level Design Document # + +## Table of Content +- [MPLS and Weighted ECMP Routes for SONiC High Level Design Document](#mpls-and-weighted-ecmp-routes-for-sonic-high-level-design-document) + - [Table of Content](#table-of-content) + - [Revision](#revision) + - [Scope](#scope) + - [Definitions/Abbreviations](#definitionsabbreviations) + - [Overview](#overview) + - [Requirements](#requirements) + - [Functional requirements](#functional-requirements) + - [Configuration and Management requirements](#configuration-and-management-requirements) + - [Scalability Requirements](#scalability-requirements) + - [Warm Boot Requirements](#warm-boot-requirements) + - [Future Requirements](#future-requirements) + - [Architecture Design](#architecture-design) + - [High-Level Design](#high-level-design) + - [Overview](#overview-1) + - [Database Changes](#database-changes) + - [APPL DB](#appl-db) + - [INTERFACE_TABLE](#interface_table) + - [ROUTE_TABLE](#route_table) + - [LABEL_ROUTE_TABLE](#label_route_table) + - [Software Modules](#software-modules) + - [NetLink](#netlink) + - [Functions](#functions) + - [IntfMgr](#intfmgr) + - [FPM Syncd](#fpm-syncd) + - [Functions](#functions-1) + - [IntfsOrch](#intfsorch) + - [Functions](#functions-2) + - [RouteOrch](#routeorch) + - [Functions](#functions-3) + - [NeighOrch](#neighorch) + - [Functions](#functions-4) + - [Label/LabelStack](#labellabelstack) + - [NextHopKey](#nexthopkey) + - [Syncd](#syncd) + - [SAI API](#sai-api) + - [Router Interface](#router-interface) + - [MPLS](#mpls) + - [Next Hop](#next-hop) + - [Next Hop Group](#next-hop-group) + - [Configuration and management](#configuration-and-management) + - [CLI Enhancements](#cli-enhancements) + - [Config DB Enhancements](#config-db-enhancements) + - [INTERFACE](#interface) + - [PORTCHANNEL_INTERFACE](#portchannel_interface) + - [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) + - [Restrictions/Limitations](#restrictionslimitations) + - [Testing Requirements/Design](#testing-requirementsdesign) + - [Unit Test cases](#unit-test-cases) + - [System Test cases](#system-test-cases) + - [Open/Action items - if any](#openaction-items---if-any) +### Revision +| Rev | Date | Author | Change Description | +| :---: | :---: | :------: | ------------------ | +| 0.1 | | A Pokora | Initial version | + +### Scope + +This document provides general information about the MPLS feature implementation in SONiC. + +### Definitions/Abbreviations +| Abbreviation | Description | +| ------------ | ------------------------------------- | +| cRPD | Containerized Routing Protocol Daemon | +| ECMP | Equal Cost Multi-Path | +| MPLS | Multi-Label Packet Switching | + +### Overview + +This document provides general information about the MPLS feature implementation in SONiC. + +### Requirements + +This section describes the SONiC requirements for: +- MPLS routes feature. +- Weighted ECMP routes feature. + +#### Functional requirements +- Support to enable/disable MPLS per Interface. +- Support for MPLS Push, Pop, and Swap routes. +- Support for weighted ECMP routes for IPv4/IPv6 and MPLS. +- Integration with Juniper cRPD routing stack. +- Integration with Juniper SAI support. + +#### Configuration and Management requirements +- SONiC CLI support for MPLS enable/disable per Interface. +- cRPD CLI support for MPLS route configuration. +- cRPD CLI support for weighted ECMP route configuration. +- cRPD CLI support for operational commands. + +#### Scalability Requirements +- Up to max ASIC capable MPLS routes are supported. +- Error is logged in syslog for all attempted MPLS routes after max limit is reached. + +#### Warm Boot Requirements +- MPLS functionality continues across warm reboot. +- Weighted ECMP functionality continues across warm reboot. +- Support for planned system warm restart. +- Support for SWSS docker warm restart. + +#### Future Requirements +- Support for VRFs +- SONiC CLI support for operational commands. +- Integration with FRR routing stack. +- Integration with VS SAI. + +### Architecture Design + +The MPLS feature extends Route and Next Hop support in SONiC to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. +The weighted ECMP feature extends Next Hop Group support in SONiC to include optional weight in addition to the existing Next Hop Group Member information. + +### High-Level Design + +#### Overview +![Overview diagram](images/MPLS_overview_diagram.png "Overview of MPLS components") +**Figure 1: Overview of the data flow and related components of MPLS** + +#### Database Changes +This section describes the modifications to SONiC Databases to support MPLS and weighted ECMP routes. + +##### APPL DB +The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. + +###### INTERFACE_TABLE +``` rfc5234 +INTERFACE_TABLE|{{interface_name}} + "mpls":{{enable|disable}} (OPTIONAL) + +; Defines schema for MPLS configuration attribute +key = INTERFACE:ifname ; Interface name +; field = value +mpls = "enable" / "disable" ; Enable/disable MPLS function. Default disable +``` + +The existing ROUTE_TABLE for IPv4/IPv4 prefix routes is enhanced to accept: +- An optional MPLS label stack component in the existing "nexthop" attribute. +- An optional new "weight" attribute. +###### ROUTE_TABLE +``` rfc5234 +"ROUTE_TABLE":{{prefix}} + "nexthop":{{nexthop_list}} + "ifname":{{ifname_list}} + "weight":{{weight_list}} (OPTIONAL) + +; Defines schema for IPv4/IPv6 route table attributes +key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix +; field = value +nexthop = nexthop_list ; List of nexthops. +ifname = ifname_list ; List of interfaces. +weight = weight_list ; List of weights. +;value annotations +ifname = 1*64VCHAR ; name of the Interface (Port Channel) + +``` + +A new LABEL_ROUTE_TABLE is introduced for MPLS routes to accept the same attributes as ROUTE_TABLE: +- A "nexthop" attribute with optional MPLS label stack component. +- A "ifname" attribute. +- An optional new "weight" attribute. +###### LABEL_ROUTE_TABLE +``` rfc5234 +"LABEL_ROUTE_TABLE":{{mpls_label}} + "nexthop":{{nexthop_list}} + "ifname":{{ifname_list}} + "weight":{{weight_list}} (OPTIONAL) + +; Defines schema for MPLS label route table attributes +key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label +; field = value +nexthop = STRING ; Comma-separated list of nexthops. +ifname = STRING ; Comma-separated list of interfaces. +weight = STRING ; Comma-separated list of weights. +``` + +#### Software Modules +This section describes modifications to software modules to support MPLS and weighted ECMP routes. +##### NetLink +Netlink is an existing open source library imported to SONiC. +Modifications to the existing NetLink implementation were needed to support MPLS routes. +###### Functions +New accessors were added to retrieve the MPLS NH destination and TTL values: +``` + /* Accessor to retrieve MPLS destination */ + extern struct nl_addr * rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *); + /* Accessor to retrieve MPLS TTL */ + extern uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *); +``` +##### IntfMgr +IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG DB on INTERFACE and PORTCHANNEL_INTERFACE tables. +IntfMgr now additionally processes the "mpls" attribute and propagates this attribute to APPL DB. + +##### FPM Syncd +FPM Syncd is an existing daemon in BGP container that monitors NetLink messages from the SONiC routing stack. +FPM Syncd now additionally processes MPLS related Route and Next Hop information in the NetLink messages and sets this information in the APPL DB. +###### Functions +The following are new functions for fpmsyncd: +``` + /* Handler for rtnl messages with MPLS route */ + void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj); + /* Handler to process ECMP Weight information rtnl messages */ + string RouteSync::getNextHopWt(struct rtnl_route *route_obj); +``` +##### IntfsOrch +IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL DB and converts those operations into SAI commands to manage the Router Interface object. +###### Functions +The following are new functions for IntfsOrch: +``` + /* Handler to enable/disable MPLS per Interface */ + bool IntfsOrch::setRouterIntfMpls(Port& port) +``` +##### RouteOrch +RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL DB and converts those operations in SAI commands to manage Route and Inseg entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. +###### Functions +The following are new functions for RouteOrch: +``` + /* Consumer handler for all events in APPL_DB LABEL_ROUTE_TABLE */ + void RouteOrch::doLabelTask(Consumer& consumer); + /* Handler to process new MPLS route from LABEL_ROUTE_TABLE */ + bool RouteOrch::addLabelRoute(sai_object_id_t, Label, const NextHopGroupKey&); + /* Handler to process MPLS route removal from LABEL_ROUTE_TABLE */ + bool RouteOrch::removeLabelRoute(sai_object_id_t, Label); +``` +##### NeighOrch +NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. +###### Functions +The following are new functions for NeighOrch: + +##### Label/LabelStack +Label and LabelStack are new type utilities of the OrchAgent daemon in the SWSS container. +These types are used to represent the MPLS label or label stack when found in a route or next hop. +``` +typedef uint32_t Label; +class LabelStack +{ + ... class definition abbreviated ... +private: + std::set^9Nd5E~;;gGrf*Xp)#)(S-9i z`sng1W3(GFzc~{)&JZiMY+~zp*V1Rj$+rhsP2ID%)C4`oR%yEjc#KiCEZVE7WqU={ zCGjId?|3KQCw%;6EB~c!oc?B2iki<0vmTEbcV%eWS=>7#X zu@eyF9hTy22}w=rz>6~>2eSsVHZ}XVq`^B$M0dH}T4 z%EFSGBZTNupwE5D{{AMPmJeg+Xc)__WZ?BZs!-Bm6w7a5;Su`P3%aKo)U#_0lAiJs z+Xk}>Ks)OSxIp;EPmw|ir#0+cTX!&zy`{#;hTz_&M>C6BiP_gwhufMpTA#h6MTfo; zuPRj&-cT91o6r$O%~?3qq13XT|C|D6~Ahx zCy{CjXN#KhDN$!WaF5@*J-aYmsH4d9unPh;3Fy~n7x@Y3Yh;$6Jln-|BSa_Nl}1#y z#ZrlS1j(|W*t<`lxRQz!i2b%G6#tFRHz-+4VxKhFZrlIsE-@)TlhM}Aq?M<`#?U>` zo+?JA^AC3GKVBRQ6UiuThI+o9ydf?@$I5e?&Gg&%?twQSl}2=I3~0#k2@u>9O-zm| zT3xpCnJJs{h@iE%KmHd4Ge^$y=ZX@F&Gb)cSHlUjS|M!^CeRyvhO(tBNen`t=+AG8 z$EyxEP^&a)6UP>%N_o{mRIEJI#`lWPq?W&}GT|hPa~I-#MEC&5-rx0Xw3>~8{ivn` zYiVMJ5N%rLlIwRzCEy{bLr_f=Q1CDp1$JL5PYnCt6PyscRblm@M+wLK&CA$bLMgrX zMP&Xt5WNW!iHozez0^*1B(pI7Tl%;l@hwcxRiVgO9=YJ~9Bk8cnRDlG_Lb%D=!zgA zA3$XB;a$I^3A6im47dfy<4y;coF`Mdi1m5}RBO}$@D=rL+wdA0J_|Bcde2;D{byOO zMOONMu9Y5!u0?L9t|vGdk>Jf0b*|3i&mn?LWW%7>)+W^O7-rAr09U z5@R(R1|34!kA$9&;I_fTRV6fJO56~7I_u683r|Fi23$+S4}!d=?15DlYpV@j?as?k z{Gco6HFAS~qDqXjkf`NuJbm;7nd`kZ_~oTX!?$&Nz9A73ZODIq%_!Xjk}H?q{8Pgw z!ON6?=#huu5JikkqM*HATTCFk1F#>@P-%-1!c$R@CUih2^c=8w+R(eElR5 zrkDxK0mg~C6YfFJdamLa@Sv2PEYKVneEHh-f4hi>N+><;aD^X{lwmPs7133ZKRn=q zWG>&%K+?z%A#Z_tPvTX4rf649e*(=H(ANxeDgBleZIdcuqu{f$=_mW1E@?dW>8ZVe zOZgX3=1IsqZnQ!+l3qk7@xZ;Mwwcn*79>s=lI_dx`56PIl*Kusc+dOZr4841=O7>; zN5jXb2A+}wJkb4Z#E~H+U->`p*4gY84PsZ37V2Ls*)gYbsPX}Hu4>?rNFfiI(m$(W z=9$J{ij4l&ZYGVOch!GA5e%djZ#trCRO|dJ2f7U10{s>IPD}$x_{22%9CZQM{r)L1 zuZ*q=Jt^oyPhD@o;4yk@Ey($jit)m(n?0X#NM!ZTQct6{Zatq*4wGC=WF3)Uojimawlxn^2%S2Tsq&_h!dWrQ!O^yg)-+mSe|WH-tRnj@e-H$E+t&yG`L$uIr6w=aQVP_s>_)#LIbI z#ry+NMyUcRR%>8&0V*Udp2HlH;tNM=&{gjGx3`S? zF58RWZyfwtO7J<_>-5LQ8*~IPLM*h=Dm*DPxM#-$$o`WLGcWOK4n>B Date: Mon, 11 Jan 2021 12:27:07 -0800 Subject: [PATCH 012/175] updated with MPLS bulking support --- doc/mpls/MPLS_hld.md | 139 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 129 insertions(+), 10 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 11584e0c1a5..398a8a5fa35 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -82,6 +82,7 @@ This section describes the SONiC requirements for: - Support to enable/disable MPLS per Interface. - Support for MPLS Push, Pop, and Swap routes. - Support for weighted ECMP routes for IPv4/IPv6 and MPLS. +- Support for bulk MPLS route programming. - Integration with Juniper cRPD routing stack. - Integration with Juniper SAI support. @@ -116,12 +117,13 @@ The weighted ECMP feature extends Next Hop Group support in SONiC to include opt #### Overview ![Overview diagram](images/MPLS_overview_diagram.png "Overview of MPLS components") + **Figure 1: Overview of the data flow and related components of MPLS** #### Database Changes This section describes the modifications to SONiC Databases to support MPLS and weighted ECMP routes. -##### APPL DB +##### APPL_DB The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. ###### INTERFACE_TABLE @@ -204,7 +206,7 @@ The following are new functions for fpmsyncd: string RouteSync::getNextHopWt(struct rtnl_route *route_obj); ``` ##### IntfsOrch -IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL DB and converts those operations into SAI commands to manage the Router Interface object. +IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL_DB and converts those operations into SAI commands to manage the Router Interface object. ###### Functions The following are new functions for IntfsOrch: ``` @@ -219,12 +221,12 @@ The following are new functions for RouteOrch: /* Consumer handler for all events in APPL_DB LABEL_ROUTE_TABLE */ void RouteOrch::doLabelTask(Consumer& consumer); /* Handler to process new MPLS route from LABEL_ROUTE_TABLE */ - bool RouteOrch::addLabelRoute(sai_object_id_t, Label, const NextHopGroupKey&); + bool addLabelRoute(LabelRouteBulkContext& ctx, const NextHopGroupKey&); /* Handler to process MPLS route removal from LABEL_ROUTE_TABLE */ - bool RouteOrch::removeLabelRoute(sai_object_id_t, Label); + bool removeLabelRoute(LabelRouteBulkContext& ctx); ``` ##### NeighOrch -NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. +NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL_DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. ###### Functions The following are new functions for NeighOrch: @@ -255,8 +257,8 @@ struct NextHopKey }; ``` ##### Syncd -Syncd is an existing daemon of the Syncd container which handles all event driven by the ASIC_DB. -Modifications were made to fully support handling of the existing SAI MPLS API key: sai_inseg_entry_t. +Syncd is an existing daemon of the Syncd container which handles all events driven by the ASIC_DB. +Modifications were made to fully support sairedis handling of the existing SAI MPLS API key: sai_inseg_entry_t. ``` /** * @brief In segment entry @@ -284,7 +286,8 @@ This section describes SAI APIs used to support MPLS and weighted ECMP routes. #### Router Interface Full details about current SAI Router Interface API and attributes are described here: -https://github.com/opencomputeproject/SAI/blob/master/inc/sairouterinterface.h) +https://github.com/opencomputeproject/SAI/blob/master/inc/sairouterinterface.h + To facilitate MPLS functionality, the following update was made to the SAI Router Interface API: ``` /** @@ -299,12 +302,128 @@ To facilitate MPLS functionality, the following update was made to the SAI Route #### MPLS Full details about current SAI MPLS API and attributes are described here: https://github.com/opencomputeproject/SAI/blob/master/inc/saimpls.h -No modifications were made to the current SAI MPLS API definition. -The entirety of the SAI MPLS API definition is now introduced to SONiC orchagent to facilitate MPLS route functionality. + +The entirety of the existing SAI MPLS API definition is now introduced to SONiC orchagent to facilitate MPLS route functionality. + +Additionally, the following has been added to the SAI MPLS API defintion for to facilitate bulk MPLS route operations for capable platforms: +``` +/** + * @brief Bulk create In Segment entry + * + * @param[in] object_count Number of objects to create + * @param[in] inseg_entry List of object to create + * @param[in] attr_count List of attr_count. Caller passes the number + * of attribute for each object to create. + * @param[in] attr_list List of attributes for every object. + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are created or + * #SAI_STATUS_FAILURE when any of the objects fails to create. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_create_inseg_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk remove In Segment entry + * + * @param[in] object_count Number of objects to remove + * @param[in] inseg_entry List of objects to remove + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_remove_inseg_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk set attribute on In Segment entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] inseg_entry List of objects to set attribute + * @param[in] attr_list List of attributes to set on objects, one attribute per object + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_set_inseg_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk get attribute on In Segment entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] inseg_entry List of objects to set attribute + * @param[in] attr_count List of attr_count. Caller passes the number + * of attribute for each object to get + * @param[inout] attr_list List of attributes to set on objects, one attribute per object + * @param[in] mode Bulk operation error handling mode + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_get_inseg_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const uint32_t *attr_count, + _Inout_ sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); +``` +The existing sai_mpls_api_t structure has been expanded to accommodate the new MPLS bulking APIs: +``` +/** + * @brief MPLS methods table retrieved with sai_api_query() + */ +typedef struct _sai_mpls_api_t +{ + sai_create_inseg_entry_fn create_inseg_entry; + sai_remove_inseg_entry_fn remove_inseg_entry; + sai_set_inseg_entry_attribute_fn set_inseg_entry_attribute; + sai_get_inseg_entry_attribute_fn get_inseg_entry_attribute; + ++ sai_bulk_create_inseg_entry_fn create_inseg_entries; ++ sai_bulk_remove_inseg_entry_fn remove_inseg_entries; ++ sai_bulk_set_inseg_entry_attribute_fn set_inseg_entries_attribute; ++ sai_bulk_get_inseg_entry_attribute_fn get_inseg_entries_attribute; + +} sai_mpls_api_t; +``` #### Next Hop Full details about SAI Next Hop API and attributes are described here: https://github.com/opencomputeproject/SAI/blob/master/inc/sainexthop.h + No modifications were mode to the current SAI Next Hop API definition. + The following existing attribute is now introduced to SONiC orchagent to facilitate MPLS route functionality: ``` /** From 0324010df3977df136c0decbdecb7e318fce6663 Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Thu, 14 Jan 2021 07:51:12 -0800 Subject: [PATCH 013/175] updates for MPLS community review comments --- doc/mpls/MPLS_hld.md | 77 +++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 398a8a5fa35..06a082f46df 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -1,7 +1,7 @@ -# MPLS and Weighted ECMP Routes for SONiC High Level Design Document # +# MPLS for SONiC High Level Design Document # ## Table of Content -- [MPLS and Weighted ECMP Routes for SONiC High Level Design Document](#mpls-and-weighted-ecmp-routes-for-sonic-high-level-design-document) +- [MPLS for SONiC High Level Design Document](#mpls-for-sonic-high-level-design-document) - [Table of Content](#table-of-content) - [Revision](#revision) - [Scope](#scope) @@ -17,7 +17,7 @@ - [High-Level Design](#high-level-design) - [Overview](#overview-1) - [Database Changes](#database-changes) - - [APPL DB](#appl-db) + - [APPL_DB](#appl-db) - [INTERFACE_TABLE](#interface_table) - [ROUTE_TABLE](#route_table) - [LABEL_ROUTE_TABLE](#label_route_table) @@ -33,6 +33,8 @@ - [Functions](#functions-3) - [NeighOrch](#neighorch) - [Functions](#functions-4) + - [CrmOrch](#crmorch) + - [Functions](#functions-4) - [Label/LabelStack](#labellabelstack) - [NextHopKey](#nexthopkey) - [Syncd](#syncd) @@ -41,6 +43,7 @@ - [MPLS](#mpls) - [Next Hop](#next-hop) - [Next Hop Group](#next-hop-group) + - [Switch](#switch) - [Configuration and management](#configuration-and-management) - [CLI Enhancements](#cli-enhancements) - [Config DB Enhancements](#config-db-enhancements) @@ -65,7 +68,6 @@ This document provides general information about the MPLS feature implementation | Abbreviation | Description | | ------------ | ------------------------------------- | | cRPD | Containerized Routing Protocol Daemon | -| ECMP | Equal Cost Multi-Path | | MPLS | Multi-Label Packet Switching | ### Overview @@ -76,29 +78,24 @@ This document provides general information about the MPLS feature implementation This section describes the SONiC requirements for: - MPLS routes feature. -- Weighted ECMP routes feature. #### Functional requirements - Support to enable/disable MPLS per Interface. - Support for MPLS Push, Pop, and Swap routes. -- Support for weighted ECMP routes for IPv4/IPv6 and MPLS. -- Support for bulk MPLS route programming. -- Integration with Juniper cRPD routing stack. -- Integration with Juniper SAI support. +- Support for bulk MPLS in-segment entry programming. +- Support for CRM monitoring of MPLS in-segment used/available entries. #### Configuration and Management requirements - SONiC CLI support for MPLS enable/disable per Interface. -- cRPD CLI support for MPLS route configuration. -- cRPD CLI support for weighted ECMP route configuration. -- cRPD CLI support for operational commands. +- Configurable CRM thresholds for monitoring MPLS used/available. #### Scalability Requirements - Up to max ASIC capable MPLS routes are supported. - Error is logged in syslog for all attempted MPLS routes after max limit is reached. +- CRM alarms are triggered when thresholds are reached. #### Warm Boot Requirements - MPLS functionality continues across warm reboot. -- Weighted ECMP functionality continues across warm reboot. - Support for planned system warm restart. - Support for SWSS docker warm restart. @@ -111,7 +108,6 @@ This section describes the SONiC requirements for: ### Architecture Design The MPLS feature extends Route and Next Hop support in SONiC to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. -The weighted ECMP feature extends Next Hop Group support in SONiC to include optional weight in addition to the existing Next Hop Group Member information. ### High-Level Design @@ -121,7 +117,7 @@ The weighted ECMP feature extends Next Hop Group support in SONiC to include opt **Figure 1: Overview of the data flow and related components of MPLS** #### Database Changes -This section describes the modifications to SONiC Databases to support MPLS and weighted ECMP routes. +This section describes the modifications to SONiC Databases to support MPLS. ##### APPL_DB The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. @@ -191,22 +187,22 @@ New accessors were added to retrieve the MPLS NH destination and TTL values: extern uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *); ``` ##### IntfMgr -IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG DB on INTERFACE and PORTCHANNEL_INTERFACE tables. -IntfMgr now additionally processes the "mpls" attribute and propagates this attribute to APPL DB. +IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG_DB on INTERFACE and PORTCHANNEL_INTERFACE tables. +IntfMgr now additionally processes the "mpls" attribute and propagates this attribute to APPL_DB. ##### FPM Syncd FPM Syncd is an existing daemon in BGP container that monitors NetLink messages from the SONiC routing stack. -FPM Syncd now additionally processes MPLS related Route and Next Hop information in the NetLink messages and sets this information in the APPL DB. +New support has been added to FPM Syncd for MPLS to process MPLS related Route and Next Hop information in the NetLink messages and propagate this information in the APPL_DB. ###### Functions The following are new functions for fpmsyncd: ``` /* Handler for rtnl messages with MPLS route */ void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj); - /* Handler to process ECMP Weight information rtnl messages */ - string RouteSync::getNextHopWt(struct rtnl_route *route_obj); ``` ##### IntfsOrch IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL_DB and converts those operations into SAI commands to manage the Router Interface object. + +For MPLS, IntfsOrch has been extended to detect the new per-RIF MPLS enable/disable attribute in the APPL_DB and propagate this attribute to the ASIC_DB via SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE. This MPLS behavior parallels the existing IntfsOrch behavior for IPv4/IPv6 with SAI_ROUTER_INTERFACE_ATTR_ADMIN_IPV4_STATE and SAI_ROUTER_INTERFACE_ATTR_ADMIN_IPV6_STATE. ###### Functions The following are new functions for IntfsOrch: ``` @@ -214,7 +210,8 @@ The following are new functions for IntfsOrch: bool IntfsOrch::setRouterIntfMpls(Port& port) ``` ##### RouteOrch -RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL DB and converts those operations in SAI commands to manage Route and Inseg entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. +RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL_DB and converts those operations in SAI commands to manage Route and Inseg entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. + ###### Functions The following are new functions for RouteOrch: ``` @@ -227,8 +224,14 @@ The following are new functions for RouteOrch: ``` ##### NeighOrch NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL_DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. +For MPLS, NeighOrch has been extended to send create/remove SAI requests for MPLS NextHop objects (ie, NextHop objects that include non-empty LabelStack information) when associated Neighbor objects are created/removed. This MPLS NextHop behavior parallels the existing IPv4/IPv6 NextHop behavior in NeighOrch. ###### Functions The following are new functions for NeighOrch: +##### CrmOrch +CrmOrch is an existing component of the OrchAgent daemon in the SWSS container. CrmOrch monitors resource usage in the SONiC system and triggers alarms when configurable thresholds are reached. +For MPLS, CrmOrch has been extended to monitor the number of MPLS in-segment entries against the platform-specific number of entries available. To facilitate this, a new CRM resource type CRM_MPLS_INSEG has been added to CrmOrch and mapped to the SAI Switch attribute SAI_SWITCH_ATTR_AVAILABLE_MPLS_INSEG_ENTRY for querying. This MPLS behavior parallels the existing IPv4/IPv6 behavior with CRM_IPV4_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY and CRM_IPV6_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY. +###### Functions +No new functions were required for CrmOrch MPLS support. ##### Label/LabelStack Label and LabelStack are new type utilities of the OrchAgent daemon in the SWSS container. @@ -422,9 +425,9 @@ typedef struct _sai_mpls_api_t Full details about SAI Next Hop API and attributes are described here: https://github.com/opencomputeproject/SAI/blob/master/inc/sainexthop.h -No modifications were mode to the current SAI Next Hop API definition. +No modifications were made to the current SAI Next Hop API definition. -The following existing attribute is now introduced to SONiC orchagent to facilitate MPLS route functionality: +The following existing attribute is now introduced to SONiC orchagent to facilitate MPLS NextHop functionality: ``` /** * @brief Push label @@ -435,19 +438,19 @@ The following existing attribute is now introduced to SONiC orchagent to facilit */ SAI_NEXT_HOP_ATTR_LABELSTACK, ``` -#### Next Hop Group -Full details about SAI Next Hop Group API and attributes are described here: -https://github.com/opencomputeproject/SAI/blob/master/inc/sainexthopgroup.h -To facilitate weighted ECMP route functionality, the following update was made to the SAI Next Hop Group API: +#### Switch +Full details about SAI Switch API and attributes are described here: +https://github.com/opencomputeproject/SAI/blob/master/inc/saiswitch.h + +To facilitate CRM support for MPLS, the following update was made to the SAI Switch API: ``` /** - * @brief Member weights + * @brief Available MPLS in segment entries * * @type sai_uint32_t - * @flags CREATE_AND_SET - * @default 1 + * @flags READ_ONLY */ - SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT, + SAI_SWITCH_ATTR_AVAILABLE_MPLS_INSEG_ENTRY, ``` ### Configuration and management @@ -455,7 +458,7 @@ This section should have sub-sections for all types of configuration and managem #### CLI Enhancements -A new command is introduced to configure interfaces for MPLS. +A new SONiC CLI command is introduced to configure interfaces for MPLS. # Enable/disable MPLS per INTERFACE. config interface mpls add|remove @@ -494,15 +497,15 @@ mpls = "enable"/"disable" ; Enable/disable MPLS MPLS design will not affect warmboot or fastboot design. ### Restrictions/Limitations -In this document, MPLS support is only for static lsp route support. The scope of routing stack supporting dynamic creation of MPLS tunnel is not in the design. +In this document, MPLS support is only for static LSP route support. The scope of routing stack supporting dynamic creation of MPLS tunnel is not in the design. ### Testing Requirements/Design -Using external routing controller to set up static lsp route for push/pop/swap operation on MPLS traffic and verify traffic is passing. +Using external routing controller to set up static LSP route for push/pop/swap operation on MPLS traffic and verify traffic is passing. #### Unit Test cases -- Using Juniper cRPD set push operation lsp, observe ip traffic goes through router and egress side will have MPLS format with correct label. -- Using Juniper cRPD set pop operation lsp, observe mpls with single label traffic goes through router and egress side will have IP packets. -- Using Juniper cRPD set swap operation lsp, observe mpls traffic goes through router and egress side will have MPLS format with different label. +- Using Juniper cRPD set push operation LSP, observe ip traffic goes through router and egress side will have MPLS format with correct label. +- Using Juniper cRPD set pop operation LSP, observe mpls with single label traffic goes through router and egress side will have IP packets. +- Using Juniper cRPD set swap operation LSP, observe mpls traffic goes through router and egress side will have MPLS format with different label. #### System Test cases Not available ### Open/Action items - if any From 1ff614ef2247812b235caf8a4f5ea397cb5b71d2 Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Tue, 19 Jan 2021 13:06:48 -0800 Subject: [PATCH 014/175] updates from MPLS subgroup feedback --- doc/mpls/MPLS_hld.md | 128 +++++++++++----------- doc/mpls/images/MPLS_overview_diagram.png | Bin 54032 -> 51628 bytes 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 06a082f46df..1d388bb4b5f 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -8,8 +8,8 @@ - [Definitions/Abbreviations](#definitionsabbreviations) - [Overview](#overview) - [Requirements](#requirements) - - [Functional requirements](#functional-requirements) - - [Configuration and Management requirements](#configuration-and-management-requirements) + - [Functional Requirements](#functional-requirements) + - [Configuration and Management Requirements](#configuration-and-management-requirements) - [Scalability Requirements](#scalability-requirements) - [Warm Boot Requirements](#warm-boot-requirements) - [Future Requirements](#future-requirements) @@ -42,8 +42,6 @@ - [Router Interface](#router-interface) - [MPLS](#mpls) - [Next Hop](#next-hop) - - [Next Hop Group](#next-hop-group) - - [Switch](#switch) - [Configuration and management](#configuration-and-management) - [CLI Enhancements](#cli-enhancements) - [Config DB Enhancements](#config-db-enhancements) @@ -56,9 +54,10 @@ - [System Test cases](#system-test-cases) - [Open/Action items - if any](#openaction-items---if-any) ### Revision -| Rev | Date | Author | Change Description | -| :---: | :---: | :------: | ------------------ | -| 0.1 | | A Pokora | Initial version | +| Rev | Date | Author | Change Description | +| :---: | :---------: | :------: | ------------------ | +| 0.1 | Jan-10-2021 | A Pokora | Initial version | +| 0.2 | Jan-19-2021 | A Pokora | Updates from MPLS community review | ### Scope @@ -76,23 +75,22 @@ This document provides general information about the MPLS feature implementation ### Requirements -This section describes the SONiC requirements for: -- MPLS routes feature. +This section describes the SONiC requirements for the MPLS feature. #### Functional requirements - Support to enable/disable MPLS per Interface. - Support for MPLS Push, Pop, and Swap routes. -- Support for bulk MPLS in-segment entry programming. +- Support for bulk MPLS in-segment entry SAI programming. - Support for CRM monitoring of MPLS in-segment used/available entries. #### Configuration and Management requirements -- SONiC CLI support for MPLS enable/disable per Interface. -- Configurable CRM thresholds for monitoring MPLS used/available. +- SONiC CLI support for MPLS enable/disable per Router Interface. +- Configurable CRM thresholds for monitoring MPLS in-segment entries used/available. #### Scalability Requirements - Up to max ASIC capable MPLS routes are supported. - Error is logged in syslog for all attempted MPLS routes after max limit is reached. -- CRM alarms are triggered when thresholds are reached. +- CRM notification upon reaching configurable scaling thresholds. #### Warm Boot Requirements - MPLS functionality continues across warm reboot. @@ -106,7 +104,6 @@ This section describes the SONiC requirements for: - Integration with VS SAI. ### Architecture Design - The MPLS feature extends Route and Next Hop support in SONiC to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. ### High-Level Design @@ -120,9 +117,10 @@ The MPLS feature extends Route and Next Hop support in SONiC to include optional This section describes the modifications to SONiC Databases to support MPLS. ##### APPL_DB -The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. ###### INTERFACE_TABLE +The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. + ``` rfc5234 INTERFACE_TABLE|{{interface_name}} "mpls":{{enable|disable}} (OPTIONAL) @@ -133,51 +131,46 @@ key = INTERFACE:ifname ; Interface name mpls = "enable" / "disable" ; Enable/disable MPLS function. Default disable ``` -The existing ROUTE_TABLE for IPv4/IPv4 prefix routes is enhanced to accept: -- An optional MPLS label stack component in the existing "nexthop" attribute. -- An optional new "weight" attribute. ###### ROUTE_TABLE +The existing ROUTE_TABLE for IPv4/IPv6 prefix routes is enhanced to accept an optional MPLS label stack component in the existing "nexthop" formatted-string attribute. The new format of the nexthop attribute string with MPLS label stack is: "label0/.../labelN+ip-prefix". For IP-only next hops, the previous string format is retained and no preceding label stack information will be included. + ``` rfc5234 "ROUTE_TABLE":{{prefix}} "nexthop":{{nexthop_list}} "ifname":{{ifname_list}} - "weight":{{weight_list}} (OPTIONAL) ; Defines schema for IPv4/IPv6 route table attributes key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix ; field = value nexthop = nexthop_list ; List of nexthops. ifname = ifname_list ; List of interfaces. -weight = weight_list ; List of weights. ;value annotations ifname = 1*64VCHAR ; name of the Interface (Port Channel) - ``` -A new LABEL_ROUTE_TABLE is introduced for MPLS routes to accept the same attributes as ROUTE_TABLE: -- A "nexthop" attribute with optional MPLS label stack component. -- A "ifname" attribute. -- An optional new "weight" attribute. ###### LABEL_ROUTE_TABLE +A new LABEL_ROUTE_TABLE is introduced for MPLS in-segment entries to accept the same attributes as ROUTE_TABLE: +- A "nexthop" formatted-string attribute with optional MPLS label stack component. +- A "ifname" attribute. + ``` rfc5234 "LABEL_ROUTE_TABLE":{{mpls_label}} "nexthop":{{nexthop_list}} "ifname":{{ifname_list}} - "weight":{{weight_list}} (OPTIONAL) ; Defines schema for MPLS label route table attributes key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label ; field = value nexthop = STRING ; Comma-separated list of nexthops. ifname = STRING ; Comma-separated list of interfaces. -weight = STRING ; Comma-separated list of weights. ``` #### Software Modules -This section describes modifications to software modules to support MPLS and weighted ECMP routes. +This section describes modifications to SONiC infrastructure software modules to support MPLS. + ##### NetLink Netlink is an existing open source library imported to SONiC. -Modifications to the existing NetLink implementation were needed to support MPLS routes. +Modifications to the existing NetLink MPLS implementation were needed to support MPLS attributes. ###### Functions New accessors were added to retrieve the MPLS NH destination and TTL values: ``` @@ -186,32 +179,39 @@ New accessors were added to retrieve the MPLS NH destination and TTL values: /* Accessor to retrieve MPLS TTL */ extern uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *); ``` + ##### IntfMgr IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG_DB on INTERFACE and PORTCHANNEL_INTERFACE tables. -IntfMgr now additionally processes the "mpls" attribute and propagates this attribute to APPL_DB. + +For MPLS, IntfMgr is modified to additionally process the "mpls" attribute and propagate this attribute to APPL_DB. ##### FPM Syncd -FPM Syncd is an existing daemon in BGP container that monitors NetLink messages from the SONiC routing stack. -New support has been added to FPM Syncd for MPLS to process MPLS related Route and Next Hop information in the NetLink messages and propagate this information in the APPL_DB. +FPM Syncd is an existing daemon in BGP container that monitors NetLink messages from the SONiC routing stack for Route and Next Hop information. + +New support has been added to FPM Syncd for MPLS to process MPLS related Route and Next Hop information in the received NetLink messages and propagate this information to the APPL_DB. ###### Functions The following are new functions for fpmsyncd: ``` /* Handler for rtnl messages with MPLS route */ void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj); ``` + ##### IntfsOrch IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL_DB and converts those operations into SAI commands to manage the Router Interface object. -For MPLS, IntfsOrch has been extended to detect the new per-RIF MPLS enable/disable attribute in the APPL_DB and propagate this attribute to the ASIC_DB via SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE. This MPLS behavior parallels the existing IntfsOrch behavior for IPv4/IPv6 with SAI_ROUTER_INTERFACE_ATTR_ADMIN_IPV4_STATE and SAI_ROUTER_INTERFACE_ATTR_ADMIN_IPV6_STATE. +For MPLS, IntfsOrch has been extended to detect the new per-RIF MPLS enable/disable attribute in the APPL_DB and propagate this attribute to the ASIC_DB via SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE. This MPLS behavior parallels the existing IntfsOrch behavior for IPv4/IPv6 with SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE and SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE. ###### Functions The following are new functions for IntfsOrch: ``` /* Handler to enable/disable MPLS per Interface */ bool IntfsOrch::setRouterIntfMpls(Port& port) ``` + ##### RouteOrch -RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL_DB and converts those operations in SAI commands to manage Route and Inseg entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. +RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL_DB and converts those operations in SAI commands to manage Route and In-Segment entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. +For MPLS, RouteOrch was modified to monitor updates to the new APPL_DB LABEL_ROUTE_TABLE. RouteOrch translates all updates to LABEL_ROUTE_TABLE to equivalent SAI requests for SAI MPLS API. +NextHop processing for updates from both the new LABEL_ROUTE_TABLE and the existing ROUTE_TABLE has been extended to detect possible MPLS LabelStack content and propagate this additional information to NeighOrch for SAI handling. ###### Functions The following are new functions for RouteOrch: ``` @@ -222,20 +222,29 @@ The following are new functions for RouteOrch: /* Handler to process MPLS route removal from LABEL_ROUTE_TABLE */ bool removeLabelRoute(LabelRouteBulkContext& ctx); ``` + ##### NeighOrch NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL_DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. + For MPLS, NeighOrch has been extended to send create/remove SAI requests for MPLS NextHop objects (ie, NextHop objects that include non-empty LabelStack information) when associated Neighbor objects are created/removed. This MPLS NextHop behavior parallels the existing IPv4/IPv6 NextHop behavior in NeighOrch. ###### Functions -The following are new functions for NeighOrch: +Existing functions from NeighOrch are updated to include NextHopKey parameter instead of IpAddress and visibility was raised to public for RouteOrch accessbility. +``` + bool hasNextHop(const NextHopKey&); + bool addNextHop(const NextHopKey&); + bool removeNextHop(const NextHopKey&); +``` + ##### CrmOrch -CrmOrch is an existing component of the OrchAgent daemon in the SWSS container. CrmOrch monitors resource usage in the SONiC system and triggers alarms when configurable thresholds are reached. -For MPLS, CrmOrch has been extended to monitor the number of MPLS in-segment entries against the platform-specific number of entries available. To facilitate this, a new CRM resource type CRM_MPLS_INSEG has been added to CrmOrch and mapped to the SAI Switch attribute SAI_SWITCH_ATTR_AVAILABLE_MPLS_INSEG_ENTRY for querying. This MPLS behavior parallels the existing IPv4/IPv6 behavior with CRM_IPV4_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY and CRM_IPV6_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY. +CrmOrch is an existing component of the OrchAgent daemon in the SWSS container. CrmOrch monitors resource usage in the SONiC system and triggers alarms when configurable thresholds are reached. + +For MPLS, CrmOrch has been extended to monitor the number of MPLS in-segment entries against the platform-specific number of entries available. To facilitate this, a new CRM resource type CRM_MPLS_INSEG has been added to CrmOrch and mapped to the existing SAI object type SAI_OBJECT_TYPE_INSEG_ENTRY for querying via sai_object_type_get_availability(). This MPLS behavior parallels the existing IPv4/IPv6 behavior with CRM_IPV4_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY and CRM_IPV6_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY. ###### Functions No new functions were required for CrmOrch MPLS support. ##### Label/LabelStack Label and LabelStack are new type utilities of the OrchAgent daemon in the SWSS container. -These types are used to represent the MPLS label or label stack when found in a route or next hop. +These types are introduced to represent the MPLS label or label stack when found in an in-segment entry or next hop. ``` typedef uint32_t Label; class LabelStack @@ -244,24 +253,25 @@ class LabelStack private: std::set^9Nd5E~;;gGrf*Xp)#)(S-9i z`sng1W3(GFzc~{)&JZiMY+~zp*V1Rj$+rhsP2ID%)C4`oR%yEjc#KiCEZVE7WqU={ zCGjId?|3KQCw%;6EB~c!oc?B2iki<0vmTEbcV%eWS=>7#X zu@eyF9hTy22}w=rz>6~>2eSsVHZ}XVq`^B$M0dH}T4 z%EFSGBZTNupwE5D{{AMPmJeg+Xc)__WZ?BZs!-Bm6w7a5;Su`P3%aKo)U#_0lAiJs z+Xk}>Ks)OSxIp;EPmw|ir#0+cTX!&zy`{#;hTz_&M>C6BiP_gwhufMpTA#h6MTfo; zuPRj&-cT91o6r$O%~?3qq13XT|C|D6~Ahx zCy{CjXN#KhDN$!WaF5@*J-aYmsH4d9unPh;3Fy~n7x@Y3Yh;$6Jln-|BSa_Nl}1#y z#ZrlS1j(|W*t<`lxRQz!i2b%G6#tFRHz-+4VxKhFZrlIsE-@)TlhM}Aq?M<`#?U>` zo+?JA^AC3GKVBRQ6UiuThI+o9ydf?@$I5e?&Gg&%?twQSl}2=I3~0#k2@u>9O-zm| zT3xpCnJJs{h@iE%KmHd4Ge^$y=ZX@F&Gb)cSHlUjS|M!^CeRyvhO(tBNen`t=+AG8 z$EyxEP^&a)6UP>%N_o{mRIEJI#`lWPq?W&}GT|hPa~I-#MEC&5-rx0Xw3>~8{ivn` zYiVMJ5N%rLlIwRzCEy{bLr_f=Q1CDp1$JL5PYnCt6PyscRblm@M+wLK&CA$bLMgrX zMP&Xt5WNW!iHozez0^*1B(pI7Tl%;l@hwcxRiVgO9=YJ~9Bk8cnRDlG_Lb%D=!zgA zA3$XB;a$I^3A6im47dfy<4y;coF`Mdi1m5}RBO}$@D=rL+wdA0J_|Bcde2;D{byOO zMOONMu9Y5!u0?L9t|vGdk>Jf0b*|3i&mn?LWW%7>)+W^O7-rAr09U z5@R(R1|34!kA$9&;I_fTRV6fJO56~7I_u683r|Fi23$+S4}!d=?15DlYpV@j?as?k z{Gco6HFAS~qDqXjkf`NuJbm;7nd`kZ_~oTX!?$&Nz9A73ZODIq%_!Xjk}H?q{8Pgw z!ON6?=#huu5JikkqM*HATTCFk1F#>@P-%-1!c$R@CUih2^c=8w+R(eElR5 zrkDxK0mg~C6YfFJdamLa@Sv2PEYKVneEHh-f4hi>N+><;aD^X{lwmPs7133ZKRn=q zWG>&%K+?z%A#Z_tPvTX4rf649e*(=H(ANxeDgBleZIdcuqu{f$=_mW1E@?dW>8ZVe zOZgX3=1IsqZnQ!+l3qk7@xZ;Mwwcn*79>s=lI_dx`56PIl*Kusc+dOZr4841=O7>; zN5jXb2A+}wJkb4Z#E~H+U->`p*4gY84PsZ37V2Ls*)gYbsPX}Hu4>?rNFfiI(m$(W z=9$J{ij4l&ZYGVOch!GA5e%djZ#trCRO|dJ2f7U10{s>IPD}$x_{22%9CZQM{r)L1 zuZ*q=Jt^oyPhD@o;4yk@Ey($jit)m(n?0X#NM!ZTQct6{Zatq*4wGC=WF3)Uojimawlxn^2%S2Tsq&_h!dWrQ!O^yg)-+mSe|WH-tRnj@e-H$E+t&yG`L$uIr6w=aQVP_s>_)#LIbI z#ry+NMyUcRR%>8&0V*Udp2HlH;tNM=&{gjGx3`S? zF58RWZyfwtO7J<_>-5LQ8*~IPLM*h=Dm*DPxM#-$$o`WLGcWOK4n>B Date: Wed, 24 Feb 2021 11:29:04 -0800 Subject: [PATCH 015/175] updates from github comments --- doc/mpls/MPLS_hld.md | 52 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 1d388bb4b5f..572e0aba4e8 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -34,8 +34,8 @@ - [NeighOrch](#neighorch) - [Functions](#functions-4) - [CrmOrch](#crmorch) - - [Functions](#functions-4) - - [Label/LabelStack](#labellabelstack) + - [Functions](#functions-5) + - [Label/LabelStack](#label-labelstack) - [NextHopKey](#nexthopkey) - [Syncd](#syncd) - [SAI API](#sai-api) @@ -47,6 +47,8 @@ - [Config DB Enhancements](#config-db-enhancements) - [INTERFACE](#interface) - [PORTCHANNEL_INTERFACE](#portchannel_interface) + - [VLAN_INTERFACE](#vlan_interface) + - [YANG Model Enhancements](#yang-model-enhancements) - [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) - [Restrictions/Limitations](#restrictionslimitations) - [Testing Requirements/Design](#testing-requirementsdesign) @@ -67,7 +69,8 @@ This document provides general information about the MPLS feature implementation | Abbreviation | Description | | ------------ | ------------------------------------- | | cRPD | Containerized Routing Protocol Daemon | -| MPLS | Multi-Label Packet Switching | +| LSP | Label-Switched Path | +| MPLS | Multi-Protocol Label Switching | ### Overview @@ -79,7 +82,7 @@ This section describes the SONiC requirements for the MPLS feature. #### Functional requirements - Support to enable/disable MPLS per Interface. -- Support for MPLS Push, Pop, and Swap routes. +- Support for MPLS Push, Pop, and Swap label operations. - Support for bulk MPLS in-segment entry SAI programming. - Support for CRM monitoring of MPLS in-segment used/available entries. @@ -142,16 +145,15 @@ The existing ROUTE_TABLE for IPv4/IPv6 prefix routes is enhanced to accept an op ; Defines schema for IPv4/IPv6 route table attributes key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix ; field = value -nexthop = nexthop_list ; List of nexthops. -ifname = ifname_list ; List of interfaces. -;value annotations -ifname = 1*64VCHAR ; name of the Interface (Port Channel) +nexthop = STRING ; Comma-separated list of nexthops. +ifname = STRING ; Comma-separated list of interfaces. ``` ###### LABEL_ROUTE_TABLE A new LABEL_ROUTE_TABLE is introduced for MPLS in-segment entries to accept the same attributes as ROUTE_TABLE: - A "nexthop" formatted-string attribute with optional MPLS label stack component. - A "ifname" attribute. +The LABEL_ROUTE_TABLE uses the incoming MPLS label as its lookup key, instead of the IP prefix used by the ROUTE_TABLE. ``` rfc5234 "LABEL_ROUTE_TABLE":{{mpls_label}} @@ -228,7 +230,7 @@ NeighOrch is an existing component of the OrchAgent daemon in the SWSS container For MPLS, NeighOrch has been extended to send create/remove SAI requests for MPLS NextHop objects (ie, NextHop objects that include non-empty LabelStack information) when associated Neighbor objects are created/removed. This MPLS NextHop behavior parallels the existing IPv4/IPv6 NextHop behavior in NeighOrch. ###### Functions -Existing functions from NeighOrch are updated to include NextHopKey parameter instead of IpAddress and visibility was raised to public for RouteOrch accessbility. +Existing functions from NeighOrch are updated to include NextHopKey parameter instead of IpAddress and visibility is raised to public for RouteOrch accessibility. ``` bool hasNextHop(const NextHopKey&); bool addNextHop(const NextHopKey&); @@ -491,6 +493,38 @@ ifname = 1*64VCHAR ; name of the Interfac mpls = "enable"/"disable" ; Enable/disable MPLS function. Default disable ``` +##### VLAN_INTERFACE +The existing VLAN_INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. + +``` rfc5234 +VLAN_INTERFACE|{{ifname}} + "mpls":{{enable|disable}} (OPTIONAL) + +; Defines schema for MPLS configuration attributes +key = VLAN_INTERFACE:ifname ; VLAN Interface name +;value annotations +ifname = 1*64VCHAR ; name of the Interface (VLAN) +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default disable +``` + +#### YANG Model Enhancements +The existing sonic-interface.yang model is enhanced to support a new "mpls" enable/disable attribute. + +``` rfc5234 + container sonic-interface { + container INTERFACE { + list INTERFACE_LIST { ++ leaf mpls { ++ type string { ++ pattern "enable|disable"; ++ } ++ } + } + } + } +``` + ### Warmboot and Fastboot Design Impact MPLS design will not affect warmboot or fastboot design. From c953f5d9b3436a1c4c32cf411824171ea7afa7bb Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Mon, 1 Mar 2021 11:40:20 -0800 Subject: [PATCH 016/175] CRM config update --- doc/mpls/MPLS_hld.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 572e0aba4e8..a9f42882a9a 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -48,6 +48,7 @@ - [INTERFACE](#interface) - [PORTCHANNEL_INTERFACE](#portchannel_interface) - [VLAN_INTERFACE](#vlan_interface) + - [CRM Config](#crm-config) - [YANG Model Enhancements](#yang-model-enhancements) - [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) - [Restrictions/Limitations](#restrictionslimitations) @@ -59,29 +60,30 @@ | Rev | Date | Author | Change Description | | :---: | :---------: | :------: | ------------------ | | 0.1 | Jan-10-2021 | A Pokora | Initial version | -| 0.2 | Jan-19-2021 | A Pokora | Updates from MPLS community review | +| 0.2 | Jan-19-2021 | A Pokora | Updates from MPLS sub-community review | ### Scope -This document provides general information about the MPLS feature implementation in SONiC. +This document provides general information about the initial support for MPLS in SONiC infrastructure. The focus of this support is to provide MPLS routing functionality in SONiC infrastructure equivalent to the current support for IPv4/IPv6 routing. ### Definitions/Abbreviations | Abbreviation | Description | | ------------ | ------------------------------------- | +| CRM | Critical Resource Monitoring | | cRPD | Containerized Routing Protocol Daemon | | LSP | Label-Switched Path | | MPLS | Multi-Protocol Label Switching | ### Overview -This document provides general information about the MPLS feature implementation in SONiC. +This document provides general information about the initial support for MPLS in SONiC infrastructure. ### Requirements This section describes the SONiC requirements for the MPLS feature. #### Functional requirements -- Support to enable/disable MPLS per Interface. +- Support for MPLS enable/disable per Router Interface. - Support for MPLS Push, Pop, and Swap label operations. - Support for bulk MPLS in-segment entry SAI programming. - Support for CRM monitoring of MPLS in-segment used/available entries. @@ -107,7 +109,7 @@ This section describes the SONiC requirements for the MPLS feature. - Integration with VS SAI. ### Architecture Design -The MPLS feature extends Route and Next Hop support in SONiC to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. +For MPLS, SONiC infrastructure Route and Next Hop support is extended to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. ### High-Level Design @@ -505,7 +507,23 @@ key = VLAN_INTERFACE:ifname ; VLAN Interface name ;value annotations ifname = 1*64VCHAR ; name of the Interface (VLAN) ; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default disable +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +``` +##### CRM Config +The existing CRM Config stanza is enhanced to include new MPLS CRM attributes. These attributes parallel existing CRM configuration for other resource types (eg, IPv4/IPv6 routes). + +``` rfc5234 +CRM + Config + "mpls_inseg_threshold_type":{{percentage|used|free}} (OPTIONAL) + "mpls_inseg_high_threshold":{{UINT32}} (OPTIONAL) + "mpls_inseg_low_threshold":{{UINT32}} (OPTIONAL) + +; Defines schema for CRM MPLS configuration attributes +; field = value +mpls_inseg_threshold_type = "percentage"/"used"/"free" ; Threshold type. Default "percentage" +mpls_inseg_high_threshold = UINT32 ; High threshold. Default value = 85 +mpls_inseg_low_threshold = UINT32 ; Low threshold. Default value = 70 ``` #### YANG Model Enhancements @@ -513,8 +531,8 @@ The existing sonic-interface.yang model is enhanced to support a new "mpls" enab ``` rfc5234 container sonic-interface { - container INTERFACE { - list INTERFACE_LIST { + container INTERFACE { + list INTERFACE_LIST { + leaf mpls { + type string { + pattern "enable|disable"; From 364fcae0438ed583270b56319dcfcb91e20b918a Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Mon, 8 Mar 2021 15:58:17 -0800 Subject: [PATCH 017/175] minor tweaks --- doc/mpls/MPLS_hld.md | 61 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index a9f42882a9a..19a95dcce00 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -64,7 +64,7 @@ ### Scope -This document provides general information about the initial support for MPLS in SONiC infrastructure. The focus of this support is to provide MPLS routing functionality in SONiC infrastructure equivalent to the current support for IPv4/IPv6 routing. +This document provides general information about the initial support for MPLS in SONiC infrastructure. The focus of this initial MPLS support is to expand existing SONiC infrastructure for IPv4/IPv6 routing to include equivalent MPLS functionality. The expected use case for this initial MPLS support is static LSP routing. ### Definitions/Abbreviations | Abbreviation | Description | @@ -80,17 +80,17 @@ This document provides general information about the initial support for MPLS in ### Requirements -This section describes the SONiC requirements for the MPLS feature. +This section describes the requirements for the initial support for MPLS in SONiC infrastructure. #### Functional requirements - Support for MPLS enable/disable per Router Interface. - Support for MPLS Push, Pop, and Swap label operations. - Support for bulk MPLS in-segment entry SAI programming. -- Support for CRM monitoring of MPLS in-segment used/available entries. +- Support in CRM for MPLS in-segment used/available entries. #### Configuration and Management requirements - SONiC CLI support for MPLS enable/disable per Router Interface. -- Configurable CRM thresholds for monitoring MPLS in-segment entries used/available. +- Configurable CRM thresholds for MPLS in-segment entries used/available. #### Scalability Requirements - Up to max ASIC capable MPLS routes are supported. @@ -104,8 +104,8 @@ This section describes the SONiC requirements for the MPLS feature. #### Future Requirements - Support for VRFs -- SONiC CLI support for operational commands. -- Integration with FRR routing stack. +- SONiC CLI support for MPLS operational commands. +- Integration with FRR routing stack MPLS support. - Integration with VS SAI. ### Architecture Design @@ -131,9 +131,9 @@ INTERFACE_TABLE|{{interface_name}} "mpls":{{enable|disable}} (OPTIONAL) ; Defines schema for MPLS configuration attribute -key = INTERFACE:ifname ; Interface name -; field = value -mpls = "enable" / "disable" ; Enable/disable MPLS function. Default disable +key = INTERFACE:ifname ; Interface name +; field = value +mpls = "enable" / "disable" ; Enable/disable MPLS function. Default "disable" ``` ###### ROUTE_TABLE @@ -145,10 +145,10 @@ The existing ROUTE_TABLE for IPv4/IPv6 prefix routes is enhanced to accept an op "ifname":{{ifname_list}} ; Defines schema for IPv4/IPv6 route table attributes -key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix -; field = value -nexthop = STRING ; Comma-separated list of nexthops. -ifname = STRING ; Comma-separated list of interfaces. +key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix +; field = value +nexthop = STRING ; Comma-separated list of nexthops. +ifname = STRING ; Comma-separated list of interfaces. ``` ###### LABEL_ROUTE_TABLE @@ -163,10 +163,10 @@ The LABEL_ROUTE_TABLE uses the incoming MPLS label as its lookup key, instead of "ifname":{{ifname_list}} ; Defines schema for MPLS label route table attributes -key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label -; field = value -nexthop = STRING ; Comma-separated list of nexthops. -ifname = STRING ; Comma-separated list of interfaces. +key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label +; field = value +nexthop = STRING ; Comma-separated list of nexthops. +ifname = STRING ; Comma-separated list of interfaces. ``` #### Software Modules @@ -473,11 +473,11 @@ INTERFACE|{{ifname}} "mpls":{{enable|disable}} (OPTIONAL) ; Defines schema for MPLS configuration attribute -key = INTERFACE:ifname ; Interface name +key = INTERFACE:ifname ; Interface name ; value annotations -ifname = 1*64VCHAR ; name of the Interface -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default is disable +ifname = 1*64VCHAR ; name of the Interface +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" ``` ##### PORTCHANNEL_INTERFACE @@ -488,11 +488,11 @@ PORTCHANNEL_INTERFACE|{{ifname}} "mpls":{{enable|disable}} (OPTIONAL) ; Defines schema for MPLS configuration attributes -key = PORTCHANNEL_INTERFACE:ifname ; Port Channel Interface name +key = PORTCHANNEL_INTERFACE:ifname ; Port Channel Interface name ;value annotations -ifname = 1*64VCHAR ; name of the Interface (Port Channel) -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default disable +ifname = 1*64VCHAR ; name of the Interface (Port Channel) +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" ``` ##### VLAN_INTERFACE @@ -503,11 +503,11 @@ VLAN_INTERFACE|{{ifname}} "mpls":{{enable|disable}} (OPTIONAL) ; Defines schema for MPLS configuration attributes -key = VLAN_INTERFACE:ifname ; VLAN Interface name +key = VLAN_INTERFACE:ifname ; VLAN Interface name ;value annotations -ifname = 1*64VCHAR ; name of the Interface (VLAN) -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +ifname = 1*64VCHAR ; name of the Interface (VLAN) +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" ``` ##### CRM Config The existing CRM Config stanza is enhanced to include new MPLS CRM attributes. These attributes parallel existing CRM configuration for other resource types (eg, IPv4/IPv6 routes). @@ -547,7 +547,8 @@ The existing sonic-interface.yang model is enhanced to support a new "mpls" enab MPLS design will not affect warmboot or fastboot design. ### Restrictions/Limitations -In this document, MPLS support is only for static LSP route support. The scope of routing stack supporting dynamic creation of MPLS tunnel is not in the design. +- No support for programming default MPLS routes for IPv4/IPv6 Explicit NULL from SONiC infrastructure. These default MPLS routes must be programmed/handled by vendor SAI implementation. +- Outermost ingress MPLS label will always be popped. ### Testing Requirements/Design Using external routing controller to set up static LSP route for push/pop/swap operation on MPLS traffic and verify traffic is passing. From 453ca2acb11ef551cd7b859705f7bf6234ad9b5f Mon Sep 17 00:00:00 2001 From: Mohanarajan Selvaraj Date: Mon, 19 Apr 2021 04:32:42 -0700 Subject: [PATCH 018/175] Updated few of the comments based on HLD review --- .../bum_storm_control_hld.md | 7 ++++--- .../images/storm_control_update_on_port.png | Bin 19513 -> 31154 bytes 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/bum_storm_control/bum_storm_control_hld.md b/doc/bum_storm_control/bum_storm_control_hld.md index dedae088a25..13ee2d28df7 100644 --- a/doc/bum_storm_control/bum_storm_control_hld.md +++ b/doc/bum_storm_control/bum_storm_control_hld.md @@ -98,7 +98,7 @@ Unknown-multicast traffic consists of all multicast traffic which donot match an 2. Support threshold rate configuration in kilo bits per second (kbps) in the range of 0 kbps to 100,000,000 kbps (100Gbps). ### 1.1.2 Configuration and Management Requirements -This feature will support Click CLI. +This feature supports Click, Klish, REST, gNMI interfaces. 1. Support a CLI to add or delete broadcast, unknown-unicast and unknown-multicast storm-control on a physical interface as described in "Configuration Commands" section below. 2. Support show commands to display the storm-control configuration as described in "Show Commands" section below. 3. Support debug commands as described in "Debug Commands" section below. @@ -145,7 +145,7 @@ Refer to section 1.1 BUM storm control - Configuration is not supported on VLAN and port-channel interfaces. User can configure on physical port which is part of a VLAN / port-channel. - Statistics is not supported. -- REST, gNMI and Klish CLI are not supported. +- User is expected to remove all storm-control configurations from interface before doing a breakout from Click CLI. @@ -230,10 +230,11 @@ The **set_port_attribute** SAI API is used to set the policer on an interface. ## 3.5 CLI ### 3.5.1 Data Models -Configuration is supported using Click CLI commands. +Configuration is supported using Click and Klish CLI commands. ### 3.5.2 Configuration Commands +This section lists down the Click commands. BUM storm-control can be configured only on physical interfaces. **switch# config interface storm-control {broadcast | unknown-unicast | unknown-multicast} {add|del} \ {\}** diff --git a/doc/bum_storm_control/images/storm_control_update_on_port.png b/doc/bum_storm_control/images/storm_control_update_on_port.png index f305183757da4db935d5d7f0841bb1b1b9067656..2007ddb89b8dd93976cfaed82d62eab040b1490a 100644 GIT binary patch literal 31154 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

!LHfq_lxH-^WQ8L!j0|(Xr>(A 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 Bid6sr literal 19513 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 Date: Tue, 8 Jun 2021 16:39:31 +0300 Subject: [PATCH 019/175] [cbf] Added CBF spec --- doc/cbf/cbf_hld.md | 214 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 doc/cbf/cbf_hld.md diff --git a/doc/cbf/cbf_hld.md b/doc/cbf/cbf_hld.md new file mode 100644 index 00000000000..85045ffc34f --- /dev/null +++ b/doc/cbf/cbf_hld.md @@ -0,0 +1,214 @@ + +# Class Based Forwarding Enhancement +#### Rev 0.1 + +# Table of Contents + * [Revision](#revision) + * [About This Manual](#about-this-manual) + * [1. Introduction](#1-introduction) + * [2. Requirements Overview](#2-requirement-overview) + * [2.1 Functional Requirements](#21-functional-requirements) + * [2.2 Configuration and Management Requirements](#22-configuration-and-management-requirements) + * [2.3 Scalability Requirements](#23-scalability-requirements) + * [2.4 Warm Boot Requirements](#24-warm-boot-requirements) + * [2.4 Restrictions](#25-restrictions) + * [3. Design](#3-design) + * [3.1 Overview](#31-overview) + * [3.2 DB Changes](#32-db-changes) + * [3.2.1 APPL DB](#321-appl-db) + * [3.2.2 CONFIG DB](#322-config-db) + * [3.3 Switch State Service Design](#33-switch-state-service-design) + * [3.3.1 Orchestration Agent](#331-orchestration-agent) + * [3.4 sairedis](#34-sairedis) + * [3.5 SAI](#35-sai) + * [3.6 CLI](#36-cli) + * [4. Warm Boot Support](#4-warm-boot-support) + * [4.1 Warm Upgrade](#31-warm-upgrade) + * [5. Unit Test](#5-unit-test) + + +# Revision +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:-----------------------:|--------------------------------------------| +| 0.1 | 03/06/2021 | Alexandru Banu | Initial version | + + +# About this Manual +This document provides general information about Class Based Forwarding which allows traffic to be steered through the network by policy, adding a layer of traffic engineering based on a Forwarding Class value which allows custom paths to be configured for a destination based on this value. + +Along this document the following abbreviations might be used: + +FC - Forwarding Class +CBF - Class Based Forwarding +NHG - Next Hop Group + +# 1 Introduction +Class Based Forwarding allows the routed traffic according to the IP/MPLS decision rules to be forwarded on different paths for the same destination depending on the Forwarding Class (different from the Traffic Class), which is determined by a mapping from the DSCP/EXP value of the packet to the Forwarding Class value. A packet coming in with a DSCP/EXP value of X will receive a Forwarding Class (FC) value of Y according to the mapping table provided at the start-of-day. This packet will then be routed, as mentioned earlier, using the traditional IP/MPLS lookup. If the chosen route uses Class Based Forwarding, the next hop will be chosen based on the Forwarding Class value. You can find a flow diagram describing this below: + +Packet is received A lookup is performed FC value X is assigned IP routing decision Routing lookup returns The next hop group Z is Packet is forwarded via +with DSCP value of -----> in the DSCP to FC map -----> to the packet -----> lookup is performed -----> next hop group Y, which -----> selected from the members -----> a member of the next hop +W for destination D table for DSCP W for destination D is a CBF group of Y, based on the FC group Z to the + value X destination D + +This feature enables opeartors, among other things, to send the important (foreground) traffic through the shortest path, while sending the background traffic through longer paths to still give it some bandwidth instead of using QoS queues which may block background traffic from getting bandwitdh. + +These new class based next hop groups are allowed thanks to the changes in https://github.com/opencomputeproject/SAI/pull/1193, which allow a next hop group object to also have other next hop group objects as members of the group along with the next hop objects. The way such a next hop group works is that a packet which has a Forwarding Class value of X will be matched against an appropriate member of this group, selected based on the Forwarding Class value thanks to the "class_map" property of the group. As an example, given the CBF group with members Nhg1, Nhg2 and Nhg3 and a class map of FC 0 -> Nhg1, FC 1 -> Nhg2 and FC 3 -> Nhg3, a packet which has an FC value of 0 will be forwarded using Nhg1. Note that multiple FC values can point to the same member, but a single FC value can't be mapped to more than one member. + +In order to support this mapping, 2 new mapping tables will be added to the CONFIG_DB for the DSCP/EXP to FC mapping and a new CLASS_BASED_NEXT_HOP_GROUP table will be added to APPL_DB to support the new FC-aware next hop groups. + +# 2 Requirement Overview +## 2.1 Functional Requirements + +Allow traffic to be forwarded through the network based on their DSCP/EXP values following these rules: +- If a packet is not matched against an FC value and the route for its destination does not reference a CBF NHG, the packet will use the route's NH +- If a packet is not matched against an FC value and the route for its destination references a CBF NHG, the packet will be dropped +- If a packet is matched against an FC value and the route for its destination does not reference a CBF NHG, the packet will use the route's NH +- If a packet is matched against an FC value and the route for its destination references a CBF NHG which maps the packet's FC value, the packet will use the mapped NHG +- If a packet is matched against an FC value and the route for its destination references a CBF NHG which doesn't map the packet's FC value, the packet will be dropped + +## 2.2 Configuration and Management Requirements +- DSCP/EXP to FC maps must be allowed to be configured via the 2 CONFIG_DB tables with no requirement to be configurable via CLI. + +## 2.3 Scalability Requirements +- Unchanged. + +## 2.4 Warm Boot Requirements +- Unchanged - the new class based next hop group table must be compatible with existing warm boot requirements. + +## 2.5 Restrictions +- fpmsyncd is not updated to use the new CLASS_BASED_NEXT_HOP_GROUP_TABLE as part of this enhancement. Anyone wishing to use this feature must use a modified version of fpmsyncd, or program the table directly. + +# 3 Design +## 3.1 Overview +This design directly changes CONFIG_DB, APPL_DB, orchagent and sairedis. + +## 3.2 DB Changes +### 3.2.1 APPL DB +Based on the next hop group split (https://github.com/Azure/SONiC/pull/712) on which this HLD is based on, a new CLASS_BASED_NEXT_HOP_GROUP table will be added to the APPL_DB with the following format: +``` +### CLASS_BASED_NEXT_HOP_GROUP_TABLE + ;Stores a list of FC-aware next hop groups. + ;Status: Mandatory + key = CLASS_BASED_NEXT_HOP_GROUP_TABLE:string ; arbitrary string identifying the class based next hop group, as determined by the programming application. + members = NEXT_HOP_GROUP_TABLE.key, ; one or more indexes within NEXT_HOP_GROUP_TABLE, separated by “,” + class_map = number:number, ; one or more mapping from Forwarding Class to index in "members" field to use as NHG, separated by "," +``` + +Example: + 127.0.0.1:6379[1]> hgetall "CLASS_BASED_NEXT_HOP_GROUP:CbfNhg1" + 1) "members" + 2) "Nhg1,Nhg2,Nhg3,Nhg4" + 3) "class_map" + 4) "0:0,1:0,2:1,3:1,4:2,5:2,6:3,7:3" + +The ROUTE_TABLE is updated to allow the "nexthop_group" to allow both keys from NEXT_HOP_GROUP_TABLE and from the new CLASS_BASED_NEXT_HOP_GROUP_TABLE. +``` +### ROUTE_TABLE + ;Stores a list of routes + ;Status: Mandatory + key = ROUTE_TABLE:prefix + nexthop = *prefix, ;IP addresses separated “,” (empty indicates no gateway) + ifname = *PORT_TABLE.key, ; zero or more separated by “,” (zero indicates no interface) + blackhole = BIT ; Set to 1 if this route is a blackhole (or null0) + nexthop_group = NEXT_HOP_GROUP_TABLE.key or CLASS_BASED_NEXT_HOP_GROUP_TABLE.key ; index within the NEXT_HOP_GROUP_TABLE or CLASS_BASED_NEXT_HOP_GROUP_TABLE, optionally used instead of nexthop and intf fields + ``` + + The LABEL_ROUTE_TABLE is updated to allow the "nexthop_group" to allow both keys from NEXT_HOP_GROUP_TABLE and from the new CLASS_BASED_NEXT_HOP_GROUP_TABLE. +``` +### LABEL_ROUTE_TABLE + ; Defines schema for MPLS label route table attributes + ;Status: Mandatory + key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label + nexthop = STRING ; Comma-separated list of nexthops. + ifname = STRING ; Comma-separated list of interfaces. + weight = STRING ; Comma-separated list of weights. + nexthop_group = NEXT_HOP_GROUP_TABLE.key or CLASS_BASED_NEXT_HOP_GROUP_TABLE.key ; index within the NEXT_HOP_GROUP_TABLE or CLASS_BASED_NEXT_HOP_GROUP_TABLE, optionally used instead of nexthop and intf fields + ``` + +### 3.2.2 CONFIG_DB +In order to store the DSCP/EXP to FC mappings, 2 new CONFIG_DB tables will be added: + +``` +### DSCP_TO_FC_MAP + ;Stores a mapping between DSCP values and FC values. qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_DSCP_TO_FC + ;Status: Mandatory + key = DSCP_TO_FC_MAP_TABLE:string ; arbitrary string identifying the name of the map. + dscp_value = 1*DIGIT + fc_value = 1*DIGIT +``` + +Example: + 127.0.0.1:6379> hgetall "DSCP_TO_FC_MAP_TABLE:AZURE" + 1) "3" ;dscp + 2) "3" ;fc + 3) "6" + 4) "5" + 5) "7" + 6) "5" + 7) "8" + 8) "7" + 9) "9" + 10) "8" + +``` +### EXP_TO_FC_MAP + ;Stores a mapping between EXP values and FC values. qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_EXP_TO_FC + ;Status: Mandatory + key = EXP_TO_FC_MAP_TABLE:string ; arbitrary string identifying the name of the map. + exp_value = 1*DIGIT + fc_value = 1*DIGIT +``` + +Example: + 127.0.0.1:6379> hgetall "EXP_TO_FC_MAP_TABLE:AZURE" + 1) "3" ;exp + 2) "3" ;fc + 3) "6" + 4) "5" + 5) "7" + 6) "5" + 7) "8" + 8) "7" + 9) "9" + 10) "8" + +## 3.3 Switch State Service Design +### 3.3.1 Orchestration Agent + +A new orchestration agent will be written to handle the requests to both NEXT_HOP_GROUP_TABLE and CLASS_BASED_NEXT_HOP_GROUP_TABLE while also providing a common API for the route orchestration agent to use when working with next hop groups stored in these tables. + +For a new entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will validate the data and create a new next hop group object in ASIC_DB of type SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED to which it will add the provided members as long as they have alreaedy been created in ASIC_DB. If an error occurs during this process and it's coming from the validation process, the task will be efectively removed from the process queue as an update to the entry would be needed in order to fix it; otherwise the task will be kept in the process queue for the event of the missing member(s) being created which would allow the class based next hop group to be created. + +If the dataplane doesn't have any more room for a new next hop group object, the task will remain in the process queue for the event of space being freed. + +There is a special scenario for creating the class based next hop groups, and that is when it references temporary next hop groups (as described in https://github.com/Azure/SONiC/pull/712), as these may be updated at some point which in turn will change their SAI ID. For this scenario, the class based next hop groups will keep a list of their temporary members and periodically check if it's SAI ID has been updated. If so, the SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID attribute of the class based next hop group member will be updated to the match the new value and if the next hop group was updated to a proper (;-temporary) next hop group object, it will be erased from the specified list. When all the temporary next hop groups have been updated to proper next hop groups, the class based one will stop checking periodically for the updates. + +For an updated entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will remove the group's previous members and add the updated ones. We do this due to the limitation of the SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX attribute which is CREATE_ONLY and so can't be updated. Instead of accounting for all the possibilities for the index of a member to be updated (by moving it to a different position in the list, removing a member that comes before it or adding a new one before it) which would be exhaustive to handle, we prefer this simpler and more robust solution. The class map will also be updated in ASIC_DB if necessary. + +For a removed entry from CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will remove the group from ASIC_DB only if it is not referenced anymore by other objects (such as routes). + +Thanks to the common API provided by the new next hop group orhcestration agent, the route orchestration agent will not need any major updates in order for routes to work with both class based next hop groups and normal next hop groups. In order for this common API to work properly, the application(s) programming the NEXT_HOP_GROUP_TABLE and CLASS_BASED_NEXT_HOP_GROUP_TABLE must ensure there is no clash between the keys of the two tables. If such a clash exists, the non-CBF next hop group will be used and returned to the route orchestration agent. + +The QoS orchestration agent is extended in order to process the DSCP_TO_FC_MAP_TABLE and EXP_TO_FC_MAP_TABLE entries. It's similar in functionality with the QoS task handling with the exception of the SAI_QOS_MAP_TYPE used for the entries created into ASIC_DB, being one of the SAI_QOS_MAP_TYPE_DSCP_TO_FORWARDING_CLASS or SAI_QOS_MAP_TYPE_MPLS_EXP_TO_FORWARDING_CLASS. + +## 3.4 sairedis +Sairedis support has been added for objects of type "sai_map_t" for validation, serialization and deserialization in order for the "class_map" property of the class based next hop groups to work properly and also "fc" has been added to "sai_qos_map_params_t" object to support the DSCP/EXP to FC mappings. + +## 3.5 SAI +The SAI changes are handled in https://github.com/opencomputeproject/SAI/pull/1193. + +## 3.6 CLI +There is no requirement for adding CLI support for this feature. + +# 4 Warm Boot Support +Unchanged. + +# 4.1 Warm Upgrade +Unchanged. + +# 5 Unit Test +Unit tests have been added to orchagent to test the mainline scenarios (create/delete) for the DSCP/EXP_TO_FC_MAP entries (update doesn't seem to be supported by CONFIG_DB tables) and mainline scenarios (create/update/delete) for the CLASS_BASED_NEXT_HOP_GROUP entries. Along with these mainline scenarios, different corner case scenarios have been tested as well, among which next hop group objects exhaustion has been tested to confirm the expected behaviour of class based next hop groups with limited resources available. + +A unit test has also been added to sairedis to test the serialization and deserialization of the "sai_map_t" objects. + +There are plans to complete the code coverage for the new orchagent code in the following month, as well as adding sonic-mgmt unit tests in the near future. From 496c6c385547588e47b485914f0120d73d1493aa Mon Sep 17 00:00:00 2001 From: abanu-ms Date: Tue, 8 Jun 2021 17:05:55 +0300 Subject: [PATCH 020/175] [cbf] Update flow diagram to fit --- doc/cbf/cbf_hld.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/cbf/cbf_hld.md b/doc/cbf/cbf_hld.md index 85045ffc34f..90453ba51bf 100644 --- a/doc/cbf/cbf_hld.md +++ b/doc/cbf/cbf_hld.md @@ -45,10 +45,10 @@ NHG - Next Hop Group # 1 Introduction Class Based Forwarding allows the routed traffic according to the IP/MPLS decision rules to be forwarded on different paths for the same destination depending on the Forwarding Class (different from the Traffic Class), which is determined by a mapping from the DSCP/EXP value of the packet to the Forwarding Class value. A packet coming in with a DSCP/EXP value of X will receive a Forwarding Class (FC) value of Y according to the mapping table provided at the start-of-day. This packet will then be routed, as mentioned earlier, using the traditional IP/MPLS lookup. If the chosen route uses Class Based Forwarding, the next hop will be chosen based on the Forwarding Class value. You can find a flow diagram describing this below: -Packet is received A lookup is performed FC value X is assigned IP routing decision Routing lookup returns The next hop group Z is Packet is forwarded via -with DSCP value of -----> in the DSCP to FC map -----> to the packet -----> lookup is performed -----> next hop group Y, which -----> selected from the members -----> a member of the next hop -W for destination D table for DSCP W for destination D is a CBF group of Y, based on the FC group Z to the - value X destination D +Packet is received with A lookup is performed FC value X is IP routing decision Routing lookup returns The next hop group Z is Packet is forwarded +DSCP/EXP value of W for --> in the DSCP/EXP to FC --> assigned to the --> lookup is performed --> next hop group Y, which --> selected from the members --> via group Z to the + destination D map table for W packet for destination D is a CBF group of Y based on the FC destination D + value X This feature enables opeartors, among other things, to send the important (foreground) traffic through the shortest path, while sending the background traffic through longer paths to still give it some bandwidth instead of using QoS queues which may block background traffic from getting bandwitdh. From e65d05a32761ea1c50c170008b22410879dce300 Mon Sep 17 00:00:00 2001 From: abanu-ms Date: Tue, 8 Jun 2021 17:13:31 +0300 Subject: [PATCH 021/175] Update markdown formatting --- doc/cbf/cbf_hld.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/cbf/cbf_hld.md b/doc/cbf/cbf_hld.md index 90453ba51bf..10b16925440 100644 --- a/doc/cbf/cbf_hld.md +++ b/doc/cbf/cbf_hld.md @@ -45,11 +45,12 @@ NHG - Next Hop Group # 1 Introduction Class Based Forwarding allows the routed traffic according to the IP/MPLS decision rules to be forwarded on different paths for the same destination depending on the Forwarding Class (different from the Traffic Class), which is determined by a mapping from the DSCP/EXP value of the packet to the Forwarding Class value. A packet coming in with a DSCP/EXP value of X will receive a Forwarding Class (FC) value of Y according to the mapping table provided at the start-of-day. This packet will then be routed, as mentioned earlier, using the traditional IP/MPLS lookup. If the chosen route uses Class Based Forwarding, the next hop will be chosen based on the Forwarding Class value. You can find a flow diagram describing this below: +``` Packet is received with A lookup is performed FC value X is IP routing decision Routing lookup returns The next hop group Z is Packet is forwarded DSCP/EXP value of W for --> in the DSCP/EXP to FC --> assigned to the --> lookup is performed --> next hop group Y, which --> selected from the members --> via group Z to the destination D map table for W packet for destination D is a CBF group of Y based on the FC destination D - value X - + value X +``` This feature enables opeartors, among other things, to send the important (foreground) traffic through the shortest path, while sending the background traffic through longer paths to still give it some bandwidth instead of using QoS queues which may block background traffic from getting bandwitdh. These new class based next hop groups are allowed thanks to the changes in https://github.com/opencomputeproject/SAI/pull/1193, which allow a next hop group object to also have other next hop group objects as members of the group along with the next hop objects. The way such a next hop group works is that a packet which has a Forwarding Class value of X will be matched against an appropriate member of this group, selected based on the Forwarding Class value thanks to the "class_map" property of the group. As an example, given the CBF group with members Nhg1, Nhg2 and Nhg3 and a class map of FC 0 -> Nhg1, FC 1 -> Nhg2 and FC 3 -> Nhg3, a packet which has an FC value of 0 will be forwarded using Nhg1. Note that multiple FC values can point to the same member, but a single FC value can't be mapped to more than one member. From dc4a7ae5be75e8e376f9e95692e678aee0fb5dac Mon Sep 17 00:00:00 2001 From: Ann Pokora Date: Mon, 14 Jun 2021 08:06:44 -0700 Subject: [PATCH 022/175] MPLs HLD updates from code-review --- doc/mpls/MPLS_hld.md | 481 ++++++++++++++++------ doc/mpls/images/MPLS_overview_diagram.png | Bin 51628 -> 58798 bytes 2 files changed, 347 insertions(+), 134 deletions(-) diff --git a/doc/mpls/MPLS_hld.md b/doc/mpls/MPLS_hld.md index 19a95dcce00..2a61ad8590b 100644 --- a/doc/mpls/MPLS_hld.md +++ b/doc/mpls/MPLS_hld.md @@ -17,50 +17,62 @@ - [High-Level Design](#high-level-design) - [Overview](#overview-1) - [Database Changes](#database-changes) - - [APPL_DB](#appl-db) - - [INTERFACE_TABLE](#interface_table) - - [ROUTE_TABLE](#route_table) - - [LABEL_ROUTE_TABLE](#label_route_table) + - [APPL DB](#appl-db) + - [INTF TABLE](#intf-table) + - [ROUTE TABLE](#route-table) + - [LABEL ROUTE TABLE](#label-route-table) + - [CONFIG DB](#config-db) + - [INTERFACE](#interface) + - [PORTCHANNEL INTERFACE](#portchannel-interface) + - [VLAN INTERFACE](#vlan-interface) + - [CRM Config](#crm-config) + - [ASIC DB](#asic-db) + - [ROUTER INTERFACE](#router-interface-1) + - [INSEG ENTRY](#inseg-entry) + - [NEXT HOP](#next-hop-2) - [Software Modules](#software-modules) - [NetLink](#netlink) - [Functions](#functions) - [IntfMgr](#intfmgr) - - [FPM Syncd](#fpm-syncd) - [Functions](#functions-1) - - [IntfsOrch](#intfsorch) + - [FPM Syncd](#fpm-syncd) - [Functions](#functions-2) - - [RouteOrch](#routeorch) + - [IntfsOrch](#intfsorch) - [Functions](#functions-3) - - [NeighOrch](#neighorch) + - [RouteOrch](#routeorch) - [Functions](#functions-4) - - [CrmOrch](#crmorch) + - [NeighOrch](#neighorch) - [Functions](#functions-5) + - [CrmOrch](#crmorch) + - [Functions](#functions-6) - [Label/LabelStack](#label-labelstack) - [NextHopKey](#nexthopkey) - [Syncd](#syncd) - [SAI API](#sai-api) - - [Router Interface](#router-interface) + - [Router Interface](#router-interface-1) - [MPLS](#mpls) - - [Next Hop](#next-hop) + - [Next Hop](#next-hop-2) - [Configuration and management](#configuration-and-management) - [CLI Enhancements](#cli-enhancements) - [Config DB Enhancements](#config-db-enhancements) - - [INTERFACE](#interface) - - [PORTCHANNEL_INTERFACE](#portchannel_interface) - - [VLAN_INTERFACE](#vlan_interface) - - [CRM Config](#crm-config) - [YANG Model Enhancements](#yang-model-enhancements) - - [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) + - [SONiC Interface](#sonic-interface) + - [SONiC VLAN](#sonic-vlan) + - [SONiC PortChannel](#sonic-portchannel) + - [SONiC CRM](#sonic-crm) + - [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) - [Restrictions/Limitations](#restrictionslimitations) - [Testing Requirements/Design](#testing-requirementsdesign) - [Unit Test cases](#unit-test-cases) - [System Test cases](#system-test-cases) - [Open/Action items - if any](#openaction-items---if-any) + ### Revision | Rev | Date | Author | Change Description | -| :---: | :---------: | :------: | ------------------ | +| :---: | :---------: | :------: | :----------------: | | 0.1 | Jan-10-2021 | A Pokora | Initial version | | 0.2 | Jan-19-2021 | A Pokora | Updates from MPLS sub-community review | +| 0.3 | Jun-14-2021 | A Pokora | Updates from MPLS sub-community code-review | ### Scope @@ -68,32 +80,34 @@ This document provides general information about the initial support for MPLS in ### Definitions/Abbreviations | Abbreviation | Description | -| ------------ | ------------------------------------- | +| :----------: | :-----------------------------------: | | CRM | Critical Resource Monitoring | | cRPD | Containerized Routing Protocol Daemon | | LSP | Label-Switched Path | | MPLS | Multi-Protocol Label Switching | ### Overview - This document provides general information about the initial support for MPLS in SONiC infrastructure. ### Requirements - This section describes the requirements for the initial support for MPLS in SONiC infrastructure. #### Functional requirements - Support for MPLS enable/disable per Router Interface. -- Support for MPLS Push, Pop, and Swap label operations. +- Support for MPLS Push, Pop, and Swap label operations, including MPLS implicit-null and explicit-null behavior. - Support for bulk MPLS in-segment entry SAI programming. -- Support in CRM for MPLS in-segment used/available entries. +- Support for MPLS type next-hop SAI programming. +- Support in CRM for MPLS in-segment entries and MPLS next-hops accounting. +- Support for VS platform SAI for test purposes. #### Configuration and Management requirements -- SONiC CLI support for MPLS enable/disable per Router Interface. -- Configurable CRM thresholds for MPLS in-segment entries used/available. +- SONiC CLI support for configuring MPLS enable/disable per Router Interface. +- SONiC CLI support for displaying MPLS state per Router Interface. +- SONiC CLI support for configuring CRM thresholds for MPLS in-segment entries and MPLS type next-hops. +- SONiC CLI support for displaying CRM thresholds and accouting for MPLS in-segment entries and MPLS type next-hops. #### Scalability Requirements -- Up to max ASIC capable MPLS routes are supported. +- Up to max ASIC capable MPLS in-segment entries are supported. - Error is logged in syslog for all attempted MPLS routes after max limit is reached. - CRM notification upon reaching configurable scaling thresholds. @@ -103,13 +117,12 @@ This section describes the requirements for the initial support for MPLS in SONi - Support for SWSS docker warm restart. #### Future Requirements -- Support for VRFs - SONiC CLI support for MPLS operational commands. -- Integration with FRR routing stack MPLS support. -- Integration with VS SAI. +- FRR Zebra FPM support for MPLS in-segment entries and MPLS next-hops. +- Support for VRFs ### Architecture Design -For MPLS, SONiC infrastructure Route and Next Hop support is extended to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. +For MPLS, SONiC SwSS infrastructure Route and Next Hop support is extended to include optional MPLS label stack in addition to the existing IPv4/IPv6 address information. ### High-Level Design @@ -121,13 +134,13 @@ For MPLS, SONiC infrastructure Route and Next Hop support is extended to include #### Database Changes This section describes the modifications to SONiC Databases to support MPLS. -##### APPL_DB +##### APPL DB -###### INTERFACE_TABLE -The existing INTERFACE_TABLE is enhanced to accept a new "mpls" enable/disable attribute. +###### INTF TABLE +The existing INTF_TABLE in the APPL_DB is enhanced to accept a new "mpls" enable/disable attribute. -``` rfc5234 -INTERFACE_TABLE|{{interface_name}} +``` +INTF_TABLE|{{interface_name}} "mpls":{{enable|disable}} (OPTIONAL) ; Defines schema for MPLS configuration attribute @@ -136,47 +149,153 @@ key = INTERFACE:ifname ; Interface name mpls = "enable" / "disable" ; Enable/disable MPLS function. Default "disable" ``` -###### ROUTE_TABLE -The existing ROUTE_TABLE for IPv4/IPv6 prefix routes is enhanced to accept an optional MPLS label stack component in the existing "nexthop" formatted-string attribute. The new format of the nexthop attribute string with MPLS label stack is: "label0/.../labelN+ip-prefix". For IP-only next hops, the previous string format is retained and no preceding label stack information will be included. +###### ROUTE TABLE +The existing ROUTE_TABLE for IPv4/IPv6 prefix routes in the APPL_DB is enhanced to accept an optional "mpls_nh" attribute that is applicable when a MPLS push operation is configured. The format of the "mpls_nh" attribute string for IPv4/IPv6 prefix routes is: "push+label0/.../labelN". + +For IP forward-only next-hops, the "mpls_nh" attribute is not applicable. If the IPv4/IPv6 prefix route is associated with a single IP forward-only next-hop or a next-hop group consisting only of these hext-hops, then the "mpls_nh" attribute will not be present. If the IPv4/IPv6 prefix route is associated with a next-hop group with a mix of MPLS push and IP forward-only next-hops, then each IP forward-only nexthop will be represented by "na" in the "mpls_nh" attribute. + +For all next-hop types, the formats of the "nexthop" and "ifname" attributes are unchanged from previous releases. -``` rfc5234 +``` "ROUTE_TABLE":{{prefix}} "nexthop":{{nexthop_list}} "ifname":{{ifname_list}} + "mpls_nh":{{mpls_nh_list}} ; Defines schema for IPv4/IPv6 route table attributes key = ROUTE_TABLE:prefix ; IPv4/IPv6 prefix ; field = value -nexthop = STRING ; Comma-separated list of nexthops. +nexthop = STRING ; Comma-separated list of IP gateways. ifname = STRING ; Comma-separated list of interfaces. +mpls_nh = STRING ; Comma-separated list of MPLS next-hop info. ``` -###### LABEL_ROUTE_TABLE -A new LABEL_ROUTE_TABLE is introduced for MPLS in-segment entries to accept the same attributes as ROUTE_TABLE: -- A "nexthop" formatted-string attribute with optional MPLS label stack component. -- A "ifname" attribute. -The LABEL_ROUTE_TABLE uses the incoming MPLS label as its lookup key, instead of the IP prefix used by the ROUTE_TABLE. +###### LABEL ROUTE TABLE +A new LABEL_ROUTE_TABLE is introduced to the APPL_DB for MPLS in-segment entries. The LABEL_ROUTE_TABLE uses the ingress MPLS label as its lookup key, instead of the IP prefix used by the ROUTE_TABLE. +The LABEL_ROUTE_TABLE accepts the same attributes as ROUTE_TABLE: +- A "nexthop" formatted-string attribute containing a list of IP gateways. +- A "ifname" attribute containing a list of interfaces. +- A "mpls_nh" attribute containing a list MPLS next-hop info. + +For MPLS in-segment routes, the "mpls_nh" attribute is applicable when a MPLS swap operation is configured. The format of the "mpls_nh" attribute for MPLS in-segment routes is: "swap+label0/../labelN". + +For MPLS pop and IP forward-only operations, the "mpls_nh" attribute is not applicable. If the MPLS in-segment entry is associated with a single MPLS pop or IP forward-only next-hop or a next-hop group consisting only of htese next-hops, then the "mpls_nh" attribute will not be present. If the MPLS in-segment etry is associated with a next-hop group with a mix of MPLS swap and MPLS pop/IP forward-only next-hops, then each MPLS pop/IP forward-only next-hop will be represented by "na" in the "mpls_nh" attribute. + +The LABEL_ROUTE_TABLE will contain an additional "mpls_pop" attribute for each MPLS in-segment entry. The value of "mpls_pop" will be "0" if the ingress MPLS label is to be retained (ie, IP forward-only next-hop). The value of "mpls_pop" will be "1" if the ingress MPLS label is to be removed (ie, MPLS pop or MPLS swap next-hop). + +For all next-hop types, the formats of the "nexthop" and "ifname" attributes are unchanged from previous releases. + +For MPLS "implicit-null" operations, the "mpls_nh" attribute is not present and the expected "mpls_pop" attribute value is "1" (ie, it is a MPLS pop next-hop) -``` rfc5234 +For MPLS "explicit-null" operations, the expected "mpls_nh" attribute value is "swap+0" and the expected "mpls_pop" attribute value is "1" (ie, it is a special case of a MPLS swap next-hop). + +``` "LABEL_ROUTE_TABLE":{{mpls_label}} "nexthop":{{nexthop_list}} "ifname":{{ifname_list}} + "mpls_nh":{{mpls_nh_list}} + "mpls_pop":{{mpls_pop}} ; Defines schema for MPLS label route table attributes key = LABEL_ROUTE_TABLE:mpls_label ; MPLS label ; field = value nexthop = STRING ; Comma-separated list of nexthops. ifname = STRING ; Comma-separated list of interfaces. +mpls_nh = STRING ; Comma-separated list of MPLS NH info. +mpls_pop = STRING ; Number of ingress MPLS labels to POP +``` + +##### CONFIG DB + +###### INTERFACE +The existing INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. + ``` +INTERFACE|{{ifname}} + "mpls":{{enable|disable}} (OPTIONAL) + +; Defines schema for MPLS configuration attribute +key = INTERFACE:ifname ; Interface name +; value annotations +ifname = 1*64VCHAR ; name of the Interface +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +``` + +###### PORTCHANNEL INTERFACE +The existing PORTCHANNEL_INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. + +``` +PORTCHANNEL_INTERFACE|{{ifname}} + "mpls":{{enable|disable}} (OPTIONAL) + +; Defines schema for MPLS configuration attributes +key = PORTCHANNEL_INTERFACE:ifname ; Port Channel Interface name +;value annotations +ifname = 1*64VCHAR ; name of the Interface (Port Channel) +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +``` + +###### VLAN INTERFACE +The existing VLAN_INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. + +``` +VLAN_INTERFACE|{{ifname}} + "mpls":{{enable|disable}} (OPTIONAL) + +; Defines schema for MPLS configuration attributes +key = VLAN_INTERFACE:ifname ; VLAN Interface name +;value annotations +ifname = 1*64VCHAR ; name of the Interface (VLAN) +; field = value +mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +``` + +###### CRM Config +The existing CRM Config stanza is enhanced to include new MPLS in-segment entry and MPLS next-hop attributes. These attributes parallel existing CRM configuration for other resource types (eg, IPv4/IPv6 routes and next-hops). + +``` +CRM + Config + "mpls_inseg_threshold_type":{{percentage|used|free}} (OPTIONAL) + "mpls_inseg_high_threshold":{{UINT32}} (OPTIONAL) + "mpls_inseg_low_threshold":{{UINT32}} (OPTIONAL) + + "mpls_nexthop_threshold_type":{{percentage|used|free}} (OPTIONAL) + "mpls_nexthop_high_threshold":{{UINT32}} (OPTIONAL) + "mpls_nexthop_low_threshold":{{UINT32}} (OPTIONAL) + +; Defines schema for CRM MPLS in-segment entry and MPLS next-hop configuration attributes +; field = value +mpls_inseg_threshold_type = "percentage"/"used"/"free" ; Threshold type. Default "percentage" +mpls_inseg_high_threshold = UINT32 ; High threshold. Default value = 85 +mpls_inseg_low_threshold = UINT32 ; Low threshold. Default value = 70 + +mpls_nexthop_threshold_type = "percentage"/"used"/"free" ; Threshold type. Default "percentage" +mpls_nexthop_high_threshold = UINT32 ; High threshold. Default value = 85 +mpls_nexthop_low_threshold = UINT32 ; Low threshold. Default value = 70 +``` + +#### ASIC DB + +##### ROUTER INTERFACE +Support for a new attribute is introduced to the ASIC_DB for the existing ROUTER_INTERFACE object type: + +##### INSEG ENTRY +Support for a new object type INSEG_ENTRY is introduced to the ASIC_DB: + +##### NEXT HOP +Support for new attributes are introduced to the ASIC_DB for the existing NEXT_HOP object type: #### Software Modules This section describes modifications to SONiC infrastructure software modules to support MPLS. -##### NetLink -Netlink is an existing open source library imported to SONiC. -Modifications to the existing NetLink MPLS implementation were needed to support MPLS attributes. +##### NetLink Library +The Netlink library (libnl3) is an existing open source library imported by SONiC to parse and format Netlink messages. +Modifications to the existing NetLink library MPLS implementation were needed to support MPLS attributes. ###### Functions -New accessors were added to retrieve the MPLS NH destination and TTL values: +New Netlink message next-hop accessors were added to retrieve attributes in a nested MPLS encapsulation (RTA_ENCAP_TYPE of LWTUNNEL_IPTUNNEL_MPLS) stanza. The following accessors retrieve the value for the attributes of MPLS next-hop destination (MPLS_IPTUNNEL_DST) and TTL (MPLS_IPTUNNEL_TTL): ``` /* Accessor to retrieve MPLS destination */ extern struct nl_addr * rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *); @@ -185,56 +304,66 @@ New accessors were added to retrieve the MPLS NH destination and TTL values: ``` ##### IntfMgr -IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG_DB on INTERFACE and PORTCHANNEL_INTERFACE tables. +IntfMgr is an existing daemon in SWSS container that monitors operations in CONFIG_DB on INTERFACE, PORTCHANNEL_INTERFACE, and VLAN_INTERFACE tables. -For MPLS, IntfMgr is modified to additionally process the "mpls" attribute and propagate this attribute to APPL_DB. +For MPLS, IntfMgr is modified to additionally process the "mpls" enable/disble attribute from the CONFIG_DB and propagate this attribute to APPL_DB. +###### Functions +The following are functions for IntfMgr: +``` + /* MPLS enable/disable per Interface */ + bool IntfMgr::setIntfMpls(const std::string &alias, const std::string &mpls); +``` +This function sets the Linux kernel variable net.mpls.interface.\ to enable/disable MPLS on the specified interface. ##### FPM Syncd -FPM Syncd is an existing daemon in BGP container that monitors NetLink messages from the SONiC routing stack for Route and Next Hop information. +FPM Syncd is an existing daemon in BGP container that monitors NetLink route messages (RTM_NEWROUTE and RTM_DELROUTE) from the SONiC routing stack FPM socket for route and next-hop information. -New support has been added to FPM Syncd for MPLS to process MPLS related Route and Next Hop information in the received NetLink messages and propagate this information to the APPL_DB. +New support has been added to FPM Syncd for MPLS to process MPLS related route and next-hop information in the received NetLink messages and propagate this information to the APPL_DB. ###### Functions The following are new functions for fpmsyncd: ``` - /* Handler for rtnl messages with MPLS route */ + /* Handler for rtnl messages with AF_MPLS route */ void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj); + /* Handler for rtnl messages with IP and/or MPLS next-hops */ + void RouteSync::getNextHopList(struct rtnl_route *route_obj, string& gw_list, + string& mpls_list, string& intf_list); + ``` ##### IntfsOrch IntfsOrch is an existing component of the OrchAgent daemon in the SWSS container. IntfsOrch monitors operations on Interface related tables in APPL_DB and converts those operations into SAI commands to manage the Router Interface object. -For MPLS, IntfsOrch has been extended to detect the new per-RIF MPLS enable/disable attribute in the APPL_DB and propagate this attribute to the ASIC_DB via SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE. This MPLS behavior parallels the existing IntfsOrch behavior for IPv4/IPv6 with SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE and SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE. +For MPLS, IntfsOrch has been extended to detect the new per-RIF "mpls" enable/disable attribute in the APPL_DB and propagate this configuration to the ASIC_DB via SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE. This MPLS behavior parallels the existing IntfsOrch behavior of SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE and SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE for IPv4/IPv6. ###### Functions The following are new functions for IntfsOrch: ``` /* Handler to enable/disable MPLS per Interface */ - bool IntfsOrch::setRouterIntfMpls(Port& port) + bool IntfsOrch::setRouterIntfMpls(const Port& port) ``` ##### RouteOrch -RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL_DB and converts those operations in SAI commands to manage Route and In-Segment entries. Additionally RouteOrch coordinates Next Hop object operations with NeighOrch and converts operations into SAI commands to manage Next Hop Group objects. +RouteOrch is an existing component of the OrchAgent daemon in the SWSS container. RouteOrch monitors operations on Route related tables in APPL_DB and converts those operations in SAI commands to manage IPv4/IPv6 route and MPLS in-segment entries. Additionally RouteOrch coordinates next-hop object operations with NeighOrch and converts operations into SAI commands to manage next-hop group objects. -For MPLS, RouteOrch was modified to monitor updates to the new APPL_DB LABEL_ROUTE_TABLE. RouteOrch translates all updates to LABEL_ROUTE_TABLE to equivalent SAI requests for SAI MPLS API. -NextHop processing for updates from both the new LABEL_ROUTE_TABLE and the existing ROUTE_TABLE has been extended to detect possible MPLS LabelStack content and propagate this additional information to NeighOrch for SAI handling. +For MPLS, RouteOrch was modified to monitor updates to the new APPL_DB LABEL_ROUTE_TABLE. RouteOrch translates all updates to LABEL_ROUTE_TABLE to equivalent SAI requests for SAI MPLS inseg API. +NextHop processing for updates from both the new LABEL_ROUTE_TABLE and the existing ROUTE_TABLE has been extended to detect possible MPLS attributes and propagate this additional information to NeighOrch for SAI handling. ###### Functions The following are new functions for RouteOrch: ``` /* Consumer handler for all events in APPL_DB LABEL_ROUTE_TABLE */ void RouteOrch::doLabelTask(Consumer& consumer); /* Handler to process new MPLS route from LABEL_ROUTE_TABLE */ - bool addLabelRoute(LabelRouteBulkContext& ctx, const NextHopGroupKey&); + bool RouteOrch::addLabelRoute(LabelRouteBulkContext& ctx, const NextHopGroupKey&); /* Handler to process MPLS route removal from LABEL_ROUTE_TABLE */ - bool removeLabelRoute(LabelRouteBulkContext& ctx); + bool RouteOrch::removeLabelRoute(LabelRouteBulkContext& ctx); ``` ##### NeighOrch -NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL_DB. Additionally NeighOrch coordinates Next Hop operations with RouteOrch and converts operations into SAI commands to manage Next Hop objects. +NeighOrch is an existing component of the OrchAgent daemon in the SWSS container. NeighOrch monitors operations on Neighbor related tables in APPL_DB. Additionally NeighOrch coordinates next-hop operations with RouteOrch and converts operations into SAI commands to manage next-hop objects. -For MPLS, NeighOrch has been extended to send create/remove SAI requests for MPLS NextHop objects (ie, NextHop objects that include non-empty LabelStack information) when associated Neighbor objects are created/removed. This MPLS NextHop behavior parallels the existing IPv4/IPv6 NextHop behavior in NeighOrch. +For MPLS, NeighOrch has been extended to send create/remove SAI requests for MPLS next-hop objects (ie, next-hop objects of type SAI_NEXT_HOP_TYPE_MPLS) when associated neighbor objects are created/removed. This MPLS next-hop behavior parallels the existing IPv4/IPv6 next-hop behavior in NeighOrch. ###### Functions Existing functions from NeighOrch are updated to include NextHopKey parameter instead of IpAddress and visibility is raised to public for RouteOrch accessibility. ``` - bool hasNextHop(const NextHopKey&); bool addNextHop(const NextHopKey&); bool removeNextHop(const NextHopKey&); ``` @@ -242,9 +371,11 @@ Existing functions from NeighOrch are updated to include NextHopKey parameter in ##### CrmOrch CrmOrch is an existing component of the OrchAgent daemon in the SWSS container. CrmOrch monitors resource usage in the SONiC system and triggers alarms when configurable thresholds are reached. -For MPLS, CrmOrch has been extended to monitor the number of MPLS in-segment entries against the platform-specific number of entries available. To facilitate this, a new CRM resource type CRM_MPLS_INSEG has been added to CrmOrch and mapped to the existing SAI object type SAI_OBJECT_TYPE_INSEG_ENTRY for querying via sai_object_type_get_availability(). This MPLS behavior parallels the existing IPv4/IPv6 behavior with CRM_IPV4_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY and CRM_IPV6_ROUTE/SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY. +For MPLS, CrmOrch has been extended to monitor the number of MPLS in-segment entries and MPLS next-hops against the platform-specific number of entries available. To facilitate this, new CRM resource types of CRM_MPLS_INSEG and CRM_MPLS_NEXTHOP have been added to CrmOrch. +CRM_MPLS_INSEG has been mapped to the existing SAI object type SAI_OBJECT_TYPE_INSEG_ENTRY for querying via sai_object_type_get_availability(). This MPLS behavior parallels the existing CRM_ROUTE_IPV4 behavior with SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY and CRM_IPV6_ROUTE behavior with SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY. +CRM_MPLS_NEXTHOP has been mapped to existing SAI object type SAI_OBJECT_TYPE_NEXT_HOP with SAI_NEXT_HOP_ATTR_TYPE of SAI_NEXT_HOP_TYPE_MPLS for querying via sai_object_type_get_availability(). This MPLS behavior parallels the existins CRM_NEXTHOP_IPV4 behavior with SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXT_HOPS and CRM_NEXTHOP_IPV6 behavior with SAI_SWITCH_AVAILABLE_IPV6_NEXT_HOPS. ###### Functions -No new functions were required for CrmOrch MPLS support. +No new functions were required for CrmOrch MPLS in-segment entry and next-hop support. ##### Label/LabelStack Label and LabelStack are new type utilities of the OrchAgent daemon in the SWSS container. @@ -259,19 +390,21 @@ private: }; ``` ##### NextHopKey -NextHopKey is an existing utility of the OrchAgent daemon in the SWSS container. NextHopKey is used by both RouteOrch and NeighOrch to coordinate Next Hop operations. +NextHopKey is an existing utility of the OrchAgent daemon in the SWSS container. NextHopKey is used by both RouteOrch and NeighOrch to coordinate next-hop operations. -For MPLS, the NextHopKey struct is modified to include a LabelStack field. +For MPLS, the NextHopKey struct is modified to include a sai_next_hop_type_t of SAI_NEXT_HOP_TYPE_MPLS, LabelStack field and sai_outseg_type_t field. ``` struct NextHopKey { - LabelStack label_stack; // MPLS label stack + sai_next_hop_type_t nh_type; // next-hop type IpAddress ip_address; // neighbor IP address string alias; // incoming interface alias + LabelStack label_stack; // MPLS label stack + sai_outseg_type_t outseg_type; // MPLS out-segment type (swap | push) ... struct definition abbreviated ... }; ``` -The LabelStack field in NextHopKey would contain an empty set of Labels for IPv4/IPv6 next hops and a non-empty set of Labels for MPLS. +The LabelStack and sai_outseg_type_t fields in NextHopKey are not applicable for NextHopKey with sai_next_hop_type_t value other than SAI_NEXT_HOP_TYPE_MPLS. ##### Syncd Syncd is an existing daemon of the Syncd container which handles all events driven by the ASIC_DB. @@ -442,7 +575,7 @@ https://github.com/opencomputeproject/SAI/blob/master/inc/sainexthop.h No modifications were made to the current SAI Next Hop API definition. -The following existing attribute is now introduced to SONiC orchagent to facilitate MPLS NextHop functionality: +The following existing attributes are now introduced to SONiC orchagent to facilitate MPLS NextHop functionality: ``` /** * @brief Push label @@ -452,88 +585,105 @@ The following existing attribute is now introduced to SONiC orchagent to facilit * @condition SAI_NEXT_HOP_ATTR_TYPE == SAI_NEXT_HOP_TYPE_MPLS */ SAI_NEXT_HOP_ATTR_LABELSTACK, + + /** + * @brief MPLS Outsegment type + * + * @type sai_outseg_type_t + * @flags CREATE_AND_SET + * @default SAI_OUTSEG_TYPE_SWAP + * @validonly SAI_NEXT_HOP_ATTR_TYPE == SAI_NEXT_HOP_TYPE_MPLS + */ + SAI_NEXT_HOP_ATTR_OUTSEG_TYPE, + ``` ### Configuration and management This section should have sub-sections for all types of configuration and management related design. Example sub-sections for "CLI" and "Config DB" are given below. Sub-sections related to data models (YANG, REST, gNMI, etc.,) should be added as required. #### CLI Enhancements + +##### Configuration CLI Commands A new SONiC CLI command is introduced to configure interfaces for MPLS. - # Enable/disable MPLS per INTERFACE. + # Enable/disable MPLS per INTERFACE/PORTCHANNEL_INTERFACE/VLAN_INTERFACE. config interface mpls add|remove -#### Config DB Enhancements +##### Show CLI Commands +A new SONiC CLI command is introduced to display the current MPLS configuraiton for interfaces. -##### INTERFACE -The existing INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. + # Show MPLS state per INTERFACE/PORT_CHANNEL_INTERFACE/VLAN_INTERFACE + show interface mpls [] -``` rfc5234 -INTERFACE|{{ifname}} - "mpls":{{enable|disable}} (OPTIONAL) - -; Defines schema for MPLS configuration attribute -key = INTERFACE:ifname ; Interface name -; value annotations -ifname = 1*64VCHAR ; name of the Interface -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +Example output from the above command: ``` + admin@sonic:~$ show interfaces mpls + Interface MPLS State + ----------- ------------ + Ethernet0 disable + Ethernet4 enable + Ethernet8 enable + Ethernet12 disable + Ethernet16 disable + Ethernet20 disable -##### PORTCHANNEL_INTERFACE -The existing PORTCHANNEL_INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. - -``` rfc5234 -PORTCHANNEL_INTERFACE|{{ifname}} - "mpls":{{enable|disable}} (OPTIONAL) + admin@sonic:~$ show interfaces mpls Ethernet4 + Interface MPLS State + ----------- ------------ + Ethernet4 enable -; Defines schema for MPLS configuration attributes -key = PORTCHANNEL_INTERFACE:ifname ; Port Channel Interface name -;value annotations -ifname = 1*64VCHAR ; name of the Interface (Port Channel) -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" ``` -##### VLAN_INTERFACE -The existing VLAN_INTERFACE table is enhanced to accept a new "mpls" enable/disable attribute. +#### Config DB Enhancements +For details please refer to [CONFIG_DB](#config-db) -``` rfc5234 -VLAN_INTERFACE|{{ifname}} - "mpls":{{enable|disable}} (OPTIONAL) +#### YANG Model Enhancements -; Defines schema for MPLS configuration attributes -key = VLAN_INTERFACE:ifname ; VLAN Interface name -;value annotations -ifname = 1*64VCHAR ; name of the Interface (VLAN) -; field = value -mpls = "enable"/"disable" ; Enable/disable MPLS function. Default "disable" +##### SONiC Interface +The existing sonic-interface.yang model is enhanced to support a new "mpls" enable/disable attribute. + +``` + container sonic-interface { + container INTERFACE { + list INTERFACE_LIST { ++ leaf mpls { ++ description "Enable/disable MPLS routing for the interface"; ++ type string { ++ pattern "enable|disable"; ++ } ++ } + } + } + } ``` -##### CRM Config -The existing CRM Config stanza is enhanced to include new MPLS CRM attributes. These attributes parallel existing CRM configuration for other resource types (eg, IPv4/IPv6 routes). -``` rfc5234 -CRM - Config - "mpls_inseg_threshold_type":{{percentage|used|free}} (OPTIONAL) - "mpls_inseg_high_threshold":{{UINT32}} (OPTIONAL) - "mpls_inseg_low_threshold":{{UINT32}} (OPTIONAL) +##### SONiC VLAN +The existing sonic-vlan.yang model is enhanced to support a new "mpls" enable/disable attribute. -; Defines schema for CRM MPLS configuration attributes -; field = value -mpls_inseg_threshold_type = "percentage"/"used"/"free" ; Threshold type. Default "percentage" -mpls_inseg_high_threshold = UINT32 ; High threshold. Default value = 85 -mpls_inseg_low_threshold = UINT32 ; Low threshold. Default value = 70 +``` + container sonic-vlan { + container VLAN_INTERFACE { + list VLAN_INTERFACE_LIST { ++ leaf mpls { ++ description "Enable/disable MPLS routing for the vlan interface"; ++ type string { ++ pattern "enable|disable"; ++ } ++ } + } + } + } ``` -#### YANG Model Enhancements -The existing sonic-interface.yang model is enhanced to support a new "mpls" enable/disable attribute. +##### SONiC PortChannel +The existing sonic-portchannel.yang model is enhanced to support a new "mpls" enable/disable attribute. -``` rfc5234 - container sonic-interface { - container INTERFACE { - list INTERFACE_LIST { +``` + container sonic-portchannel { + container PORTCHANNEL_INTERFACE { + list PORTCHANNEL_INTERFACE_LIST { + leaf mpls { ++ description "Enable/disable MPLS routing for the portchannel interface"; + type string { + pattern "enable|disable"; + } @@ -543,21 +693,84 @@ The existing sonic-interface.yang model is enhanced to support a new "mpls" enab } ``` +##### SONiC CRM +The existing sonic-crm.yang model is enhanced to support the new MPLS in-segment entry and MPLS next-hop CRM thresholds. + +``` +container sonic-crm { + container CRM { + container Config { ++ leaf mpls_inseg_threshold_type { ++ must "(((current()='PERCENTAGE' or current()='percentage') and ++ ../mpls_inseg_high_threshold<100 and ++ ../mpls_inseg_low_threshold<100) or ++ (current()!='PERCENTAGE' and current()!='percentage'))"; ++ type stypes:crm_threshold_type; ++ } + ++ leaf mpls_inseg_high_threshold { ++ must "(current() > ../mpls_inseg_low_threshold)" ++ { ++ error-message "high_threshold should be more than low_threshold"; ++ } ++ type threshold; ++ } + ++ leaf mpls_inseg_low_threshold { ++ type threshold; ++ } + ++ leaf mpls_nexthop_threshold_type { ++ must "(((current()='PERCENTAGE' or current()='percentage') and ++ ../mpls_nexthop_high_threshold<100 and ++ ../mpls_nexthop_low_threshold<100) or ++ (current()!='PERCENTAGE' and current()!='percentage'))"; ++ type stypes:crm_threshold_type; ++ } + ++ leaf mpls_nexthop_high_threshold { ++ must "(current() > ../mpls_nexthop_low_threshold)" ++ { ++ error-message "high_threshold should be more than low_threshold"; ++ } ++ type threshold; ++ } + ++ leaf mpls_nexthop_low_threshold { ++ type threshold; ++ } + + } + } +} +``` + ### Warmboot and Fastboot Design Impact -MPLS design will not affect warmboot or fastboot design. +This SONiC infrastructure support for MPLS is an enhancement of existing IPv4/IPv6 routing infrastructure which allows it to make use of existing warmboot and fastboot handling. For this reason, MPLS design will not affect warmboot or fastboot design. ### Restrictions/Limitations -- No support for programming default MPLS routes for IPv4/IPv6 Explicit NULL from SONiC infrastructure. These default MPLS routes must be programmed/handled by vendor SAI implementation. -- Outermost ingress MPLS label will always be popped. +- No support for programming default MPLS routes for IPv4/IPv6 Explicit NULL from SONiC infrastructure. These default MPLS routes must be programmed/handled by vendor SAI implementation. This limitation is due to lack of support for Route Table as valid Next Hop entity in SAI MPLS definition. +- Outermost ingress MPLS label will always be popped. This limitation is due to implicit pop in Linux/Netlink implementation. ### Testing Requirements/Design -Using external routing controller to set up static LSP route for push/pop/swap operation on MPLS traffic and verify traffic is passing. +An external routing controller is used to set up static LSP route for push/pop/swap operation on MPLS traffic and verify traffic is passing. #### Unit Test cases -- Using Juniper cRPD set push operation LSP, observe IP traffic goes through router and egress side will have MPLS format with correct label. -- Using Juniper cRPD set pop operation LSP, observe MPLS with single label traffic goes through router and egress side will have IP packets. -- Using Juniper cRPD set swap operation LSP, observe MPLS traffic goes through router and egress side will have MPLS format with different label. +- Add/remove IPv4 route entry with associated MPLS push next-hop. +- Add/remove MPLS in-segment entry with associated MPLS swap next-hop. +- Add/remove MPLS in-segment entry with associated MPLS implicit-null (pop) next-hop. +- Add/remove MPLS in-segment entry with associated MPLS explicit-null (swap) next-hop. +- Add/remove IPv4 route entry with associated next-hop group of two MPLS push next-hops. +- Add/remove MPLS in-segment entry with associated next-hop group of two MPLS swap next-hops. +- Add/remove MPLS in-segment entry with associated next-hop group of two MPLS implicit-null (pop) next-hops. +- Add/remove IPv4 route entry with associated next-hop group of one MPLS push and one IPv4 forward-only nexthop. +- Add/remove MPLS in-segment entry with associated next-hop group of one MPLS swap and one MPLS implicit-null (pop) nexthop. +- Add/remove MPLS in-segment entry with unresolved MPLS swap next-hop. Verify both in-segment and next-hop are not programmed until next-hop is resolved. + #### System Test cases -Not available +- Add IPv4 route entry with associated MPLS push next-hop. Verify ingress IP traffic and egress MPLS traffic with correct MPLS label. +- Add MPLS in-segment entry with associated MPLS implicit-null (pop) next-hop. Verify ingress MPLS traffic and egress IP traffic. +- Add MPLS in-segment entry with associated MPLS swap next-hop. Verify ingress MPLS traffic and egress MPLS traffic with correct MPLS label. + ### Open/Action items - if any None diff --git a/doc/mpls/images/MPLS_overview_diagram.png b/doc/mpls/images/MPLS_overview_diagram.png index eba369d57dd908187f356c2c9d84b96477e8e4f4..9483d2e127a22159895032d70aa6cb64ba2d049d 100644 GIT binary patch literal 58798 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 literal 51628 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 From 6d9cdf870919e14867ec2200ea3e6cb118ec4dab Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Thu, 24 Jun 2021 23:00:35 -0400 Subject: [PATCH 023/175] Initial version of PINS HLD --- doc/pins/images/pins_arch.png | Bin 0 -> 162127 bytes doc/pins/images/sai_p4.png | Bin 0 -> 76424 bytes doc/pins/pins_hld.md | 194 ++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 doc/pins/images/pins_arch.png create mode 100644 doc/pins/images/sai_p4.png create mode 100644 doc/pins/pins_hld.md diff --git a/doc/pins/images/pins_arch.png b/doc/pins/images/pins_arch.png new file mode 100644 index 0000000000000000000000000000000000000000..4c09410621ebbee3b0d1b8ee9885eb72c30515fd GIT binary patch literal 162127 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 literal 0 HcmV?d00001 diff --git a/doc/pins/images/sai_p4.png b/doc/pins/images/sai_p4.png new file mode 100644 index 0000000000000000000000000000000000000000..9f024b2f6898d540b8f3dff924e9d711b9d251b2 GIT binary patch literal 76424 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 literal 0 HcmV?d00001 diff --git a/doc/pins/pins_hld.md b/doc/pins/pins_hld.md new file mode 100644 index 00000000000..e328d21c23c --- /dev/null +++ b/doc/pins/pins_hld.md @@ -0,0 +1,194 @@ +# PINS HLD + +_Rev v0.1_ + +## Table of Contents + +* [Revisions](#revisions) +* [Scope](#scope) +* [Definitions/Abbreviations](#definitions-abbreviations) +* [Overview](#overview) + + [Open Source](#open-source) + + [Opt-In Path Towards SDN](#opt-in-path-towards-sdn) + + [Familiar Interface](#familiar-interface) + + [Unambiguous Documentation](#unambiguous-documentation) +* [Requirements](#requirements) +* [Architecture Design](#architecture-design) +* [High-Level Design](#high-level-design) + + [P4RT Application](#p4rt-application) + + [P4 Programs & P4 Info](#p4-programs---p4-info) + + [P4 APPL DB Tables](#p4-appl-db-tables) + + [P4 Orchagent](#p4-orchagent) + + [Application Level Responses](#application-level-responses) + + [Packet IO](#packet-io) + + [Repositories](#repositories) +* [SAI API](#sai-api) +* [Configuration and management](#configuration-and-management) + + [CLI/YANG model Enhancements](#cli-yang-model-enhancements) + + [Config DB Enhancements](#config-db-enhancements) +* [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) +* [Restrictions/Limitations](#restrictions-limitations) +* [Testing Requirements/Design](#testing-requirements-design) +* [Open/Action items - if any](#open-action-items---if-any) +* [Supplementary Documents](#supplementary-documents) + + + +## Revisions + +| Rev | RevDate | Author(s) | Change Description +|------|------------|--------------------|-------------------- +| v0.1 | 06/24/2021 | Google, ONF, Intel | Initial version + +## Scope +This document describes the high level design of PINS - P4 Integrated Network Stack. It provides a detailed explanation of the components that need to be added and modified in the SONiC framework to support a remote controller to program the forwarding tables. + +## Definitions/Abbreviations + +**P4**: Programming Protocol-independent Packet Processors (P4) is a domain-specific language for network devices, specifying how data plane devices (switches, NICs, routers, filters, etc.) process packets + +**P4RT**: P4Runtime (P4RT) is a control plane specification for controlling the data plane elements of a device defined or described by a P4 program. + +**PINS**: P4 Integrated Network Stack (PINS) is a project that provides additional components and changes to SONiC and allows the stack to be remotely controlled using P4 and P4Runtime. + +**SAI**: Switch Abstraction Interface (SAI) is a standardized interface which allows programming and managing different switch ASICs in a vendor-independent fashion. + +**SDN**: Software Defined Networking (SDN) is the practice of disaggregating the data, control, and management planes of networks, and implementing the control and management planes outside the switch. + + +## Overview +This document describes **PINS (P4 Integrated Network Stack)**, a P4Runtime (P4RT) based SDN interface for programming the forwarding tables through SAI APIs. P4Runtime for SAI is open sourceable, is opt-in, has familiar interfaces, enables rapid innovation, provides automated validation, and serves as unambiguous documentation. + +A canonical family of P4 programs (included in the repository) documents the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. + +### Open Source +The family of P4 programs, the P4RT server, the orchagent code to translate from P4RT to SAI, the validation framework, and any P4 compiler extensions will all be open sourced. The user and vendor specific aspects of a switch pipeline are cleanly separated into extension and configurable tables. + +### Opt-In Path Towards SDN +The P4RT Application is completely opt-in. If the P4RT interface is not used, the remaining parts of SONiC will continue to work the way it does today. This new interface allows interested operators to gradually move towards SDN without needing a full-fledged SDN controller right from the start. It is possible to continue relying on SONiC-provided protocols for some aspects, and to start using P4RT for others. + +### Familiar Interface +The family of P4 programs models the SAI forwarding pipeline, making the P4RT interface familiar to anyone who has worked with SONiC/SAI before. The P4RT interface provides essential networking features (L2 bridging, L3 routing, ACLs, etc.) allowing users to quickly get up to speed on how to use this new API. + +### Unambiguous Documentation +The SAI P4 programs will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. The P4 program for L3 routing will be modeled after the SAI pipeline for L3 (the full SAI pipeline is described [here](https://github.com/opencomputeproject/SAI/blob/master/doc/object-model/pipeline_object_model.pdf)). + +## Requirements +The following components are targeted for the SONiC 2021-11 Release +* P4RT application server that runs in its own container. +* P4RT-Orchagent that runs as part of SWSS +* P4 program + +The following functionality will be available +* P4RT clients can use P4Runtime to program IP route entries, next hop members and groups, and ACL entries to drop or punt packets to the control plane. +* P4RT clients can program ACLs to punt packets received in the ingress pipeline. These packets will be punted to the P4RT application running in the switch and will be forwarded to the client over grpc. +* Users can introduce custom private extensions to the pipeline by adding other elements to the P4 program. + +Additional functionality will be made available in future releases. + +## Architecture Design + +SONiC is structured into various containers that communicate through multiple logical databases via a shared Redis instance. To add SDN support, PINS introduces a few new components into the SONiC system: +* P4RT: An application that receives P4 programming requests from the controller and programs the requests to the lower layers. +* P4RT tables: a new APPL DB table that defines the P4 programming requests. +* P4orch: A new orch that programs the P4RT table from APPL DB to ASIC DB. It also sends response notifications to P4RT and manages the APPL STATE DB. +* APPL STATE DB: A new DB for applications to query the system status. It has the same schema of the APPL DB. + +![alt_text](images/pins_arch.png "image_tooltip") + +The P4RT application listens to a remote SDN controller and creates entries in the APPL and CONFIG databases. Following the SONiC architecture, the P4RT application writes its output to a new table in the APPL database. From there, the new P4RT orchestration agent (orchagent) picks up the changes and writes the entries into the existing ASIC tables, where they get picked up by syncd. This path is highlighted in solid purple in the following figure. There is an alternative path (in dotted pink) that some SAI objects might choose to take, which is going through existing APP database tables, and then following the existing agents in the SWSS container down to the ASIC database. Note that whether the dotted pink or solid purple path is taken is a static decision made by the implementer of the P4RT app. For every kind of object, we statically decide which path is taken, and then only implement that path. The P4 program is not changed due to this change, it is an implementation detail of the switch not exposed to the outside (the controller, or even the vendor layer). + + +## High-Level Design +The high level architecture can be broken down into a set of modules that interact and work together to provide the functionality. + +### P4RT Application +The P4RT application runs in its own container and supports multiple gRPC client sessions. The application is responsible for parsing the requests from its clients, verifying them and writing the intent to the new P4 tables in APPL DB and notifying the clients of the eventual success/failure of the intent. The P4RT application also supports read requests from its clients. The read requests provide clients with current state information of the switch. More detailed information regarding the P4RT application is provided in the supplementary document [P4RT and APPL DB Schema](#bookmark=id.4o11cru31903). + +### P4 Programs & P4 Info +The P4RT Application comes along with a canonical family of P4 programs (also open-source) that outline the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. The SAI P4 programs will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. + +The SAI pipeline is modeled as a P4 program which can be compiled using a P4 compiler ([https://github.com/p4lang/p4c](https://github.com/p4lang/p4c)). The output of the compiler is a P4Info file with a description of the various tables and other objects in the P4 program. This is used by the P4RT Application. Assuming a switch vendor supports the SAI pipeline nothing more is needed. Vendors supporting a P4 backend may use other outputs from the compiler. + +![alt_text](images/sai_p4.png "image_tooltip") + +Fixed SAI components are modeled after the [SAI Pipeline Object Model](https://github.com/opencomputeproject/SAI/blob/master/doc/object-model/pipeline_object_model.pdf). + +Yellow boxes represent the fixed components of the SAI pipeline. These will be the same in every P4 program. Blue boxes represent the configurable components of the SAI pipeline, namely Access Control Lists (ACLs). Every ACL follows the same basic schema, but can be customized for the use-case by changing the match fields and actions (subject to restrictions w.r.t. what SAI allows). + +### P4 APPL DB Tables +This is the interface between the P4RT app and the P4RT orch agent. The set of tables are collectively called the _P4RT Tables_. + +In SONiC, the APPL DB contains high level details of the programming as compared to the ASIC DB tables. Unlike traditional SONiC applications, the SDN controller provides low level details and such a level of detailed programming is not supported by most of the existing APPL DB tables. + +To overcome this limitation, the PINS architecture defines new APPL_DB tables that allow more detailed definitions. The P4RT application writes to these tables. The new tables are written by the P4RT application and consumed by the P4RT Orchagent. + +Readability is an important criteria for SONiC DB tables. The new tables are no different in this respect and use consistent formatting. The new tables are named with the prefix P4RT to easily identify them as P4RT application tables. The naming follows the convention of `P4RT:` where TableType is of FIXED or configurable (only ACL for now) and TableName is the specific table in the SAI pipeline specification like router interface, neighbor, nexthop, IPV4/IPV6 tables etc. + +An example table definition is shown below. + +``` +P4RT:FIXED_NEXTHOP_TABLE:{"match/nexthop_id":"node-1234:eth-1/2/3"} + "action" = "set_nexthop" + "param/router_interface_id" = "intf-eth-1/2/3" + "param/neighbor_id" = "10.0.0.22" + "controller_metadata" = "..." +``` + +Detailed information regarding the schema of the tables and a set of guidelines for consistency are provided in the supplementary documentation on [P4RT and APPL DB Schema](#broken-todo). + +### P4 Orchagent +The P4Orchagent processes the entries added to the new P4 tables in APPL DB by the P4RT application, parses and resolves them and then invokes the necessary SAI APIs to create ASIC DB entries. SAI objects created by the P4RTOrch could refer to SAI objects created by other orchagents. In these cases, the P4Orchagent will interact with the corresponding orchagents to reference those objects and increase reference counters where necessary. Detailed information regarding the operation of the P4 Orchagent is provided in the supplementary documentation on [P4 Orchagent](#broken-todo). + +### Application Level Responses +PINS introduces the concept of application level responses. SONiC currently supports synchronous communication between SWSS and Syncd containers. PINS extends synchronized communication to applications. + +Most SDN controllers require an acknowledgement of success or failure for each programming request. Subsequent programming from the controller depends on the response. SDN controllers are intelligent and can adapt to failures quickly. If one of the switches encounters a failure, the controller can utilize the other switches to achieve its goals. + +The controller requires state information from the switches in order to quickly identify any failures. This is accomplished by the addition of application level responses and state. More information regarding this is provided in the supplementary documentation [Response path and Application DB](#broken-todo). + +### Packet IO +P4RT clients can program ACLs to punt packets received in the ingress pipeline. These packets will be trapped and punted to the P4RT application running in the switch and will be forwarded to the client over grpc. + +SONiC relied on basic packet I/O support that uses netdev ports to send and receive packets. P4Runtime applications require additional packet attributes like the target egress port which are not available via netdev. Similarly directed Tx from application level is not currently supported in the SONiC framework. This is required to support scenarios where the remote SDN controller needs to send a packet via one of the front panel ports of the switch. + +To support the above requirements, a model similar to sFlow is used. The receive solution creates a netlink type host interface. It programs a user defined trap for packets that are interesting to the controller and maps them to the netlink host interface. A generic ASIC independent model is defined for passing parameters such as “target egress port” to the application container. A detailed description of the receive path is present in the supplementary document on [Packet IO](#broken-todo). + +### Repositories +This design adds the following new repositories: +* P4RT Application + +It also has modifications in the following repositories: +* SWSS +* SONiC Build Image + +## SAI API +There are no changes to SAI. + +For programmable hardware targets, PINS introduces an additional SAI header, saip4ext.h, to map user-defined private P4 extensions to vendor SAI implementations. More details on saip4ext.h can be found in the supplemental document [P4 Extensions for SAI](#broken-todo). + +## Configuration and management + +### CLI/YANG model Enhancements +There are no CLI changes. + +### Config DB Enhancements +There are no Config DB changes. + +## Warmboot and Fastboot Design Impact +Similar to other orchagents, the P4Orchagent needs to perform actions for successful warm boot and fast boot operation. These changes are being planned for the next phase ( next SONiC release). In this phase, warmboot and fastboot features will not be supported for objects created through the P4RT application. + +When the P4RT application is not used, warm boot and fastboot will continue to operate as before. There will be no impact on existing warmboot and fastboot design. + +## Restrictions/Limitations +In this introductory phase, limited functionality and features will be supported through the P4RT application. The details of supported features are provided in the requirements section. + + +## Testing Requirements/Design +The entire PINS code, including the P4RT Application, P4 orchagent, etc is well unit tested. The coverage goal is at least 90% which is already achieved. Integration tests will be added in the following release. + +## Open/Action items - if any +None From f619c03541ba94332d28d602a99e6646cfa9bb3c Mon Sep 17 00:00:00 2001 From: Mohanarajan Selvaraj Date: Mon, 2 Aug 2021 05:33:52 -0700 Subject: [PATCH 024/175] update config DB table name and key separator --- doc/bum_storm_control/bum_storm_control_hld.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/bum_storm_control/bum_storm_control_hld.md b/doc/bum_storm_control/bum_storm_control_hld.md index 13ee2d28df7..c320491add2 100644 --- a/doc/bum_storm_control/bum_storm_control_hld.md +++ b/doc/bum_storm_control/bum_storm_control_hld.md @@ -158,8 +158,8 @@ BUM storm control __Figure 1: Storm Control High Level Architecture__ -1) Storm-control configurations are parsed and stored in CFG_PORT_STORM_CONTROL_TABLE in Configuration database by the Management Framework. -2) The Policer Orchestration Agent subscribes to notifications from the CFG_PORT_STORM_CONTROL_TABLE and parses the input parameters (interface, storm-control type, kbps). A policer_name is created internally by encoding the interface_name and storm_control_type. +1) Storm-control configurations are parsed and stored in PORT_STORM_CONTROL in Configuration database by the Management Framework. +2) The Policer Orchestration Agent subscribes to notifications from the PORT_STORM_CONTROL and parses the input parameters (interface, storm-control type, kbps). A policer_name is created internally by encoding the interface_name and storm_control_type. 3) create_policer SAI API is invoked to create a policer with the given input parameters. 4) The identifier of the policer created is associated with the encoded policer_name. 5) The policer identifier is passed to set_port_attribute SAI API to set the appropriate type of storm-control on the port. @@ -170,13 +170,13 @@ This section describes the changes made to different DBs for supporting storm-co ### 3.2.1 CONFIG_DB -A new table CFG_PORT_STORM_CONTROL_TABLE is introduced in the configuration database for the purpose of storing storm-control configuration parameters. This table is filled by the management framework. -#### CFG_PORT_STORM_CONTROL_TABLE +A new table PORT_STORM_CONTROL is introduced in the configuration database for the purpose of storing storm-control configuration parameters. This table is filled by the management framework. +#### PORT_STORM_CONTROL ;Store Storm Control configuration per physical port ;Status: work in progress ;storm control type - broadcast / unknown-unicast / unknown-multicast - key = CFG_PORT_STORM_CONTROL_TABLE:port:storm_control_type ; Ethernet Interface Name and storm control type + key = PORT_STORM_CONTROL:port|storm_control_type ; Ethernet Interface Name and storm control type ;field = value enabled = BIT ; Is the storm control enabled (1) or disabled (0) on the interface kbps = 1*13 DIGIT ; CIR value in kilo bits per second @@ -195,7 +195,7 @@ No changes are introduced in COUNTER_DB. ## 3.3 Switch State Service Design ### 3.3.1 PolicerOrch changes Policer Orchestration agent is responsible for the following activities: - - Subscribes to notifications on CFG_PORT_STORM_CONTROL_TABLE entries in the CONFIG_DB. + - Subscribes to notifications on PORT_STORM_CONTROL entries in the CONFIG_DB. - Creates an internal name for policer by encoding the interface name and storm-control type. - Creates the policer based on the parameters and associates the policer identifier to internal name - Populates the port attribute SAI structures and pushes the entry to ASIC_DB. From 7f22539a7967330e8e14450e43bffe1bbc57b1db Mon Sep 17 00:00:00 2001 From: Mohanarajan Selvaraj Date: Mon, 2 Aug 2021 06:03:53 -0700 Subject: [PATCH 025/175] Update revision number and date, supported configuration modes --- doc/bum_storm_control/bum_storm_control_hld.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/bum_storm_control/bum_storm_control_hld.md b/doc/bum_storm_control/bum_storm_control_hld.md index c320491add2..73b107700d3 100644 --- a/doc/bum_storm_control/bum_storm_control_hld.md +++ b/doc/bum_storm_control/bum_storm_control_hld.md @@ -66,6 +66,7 @@ | Rev | Date | Author | Change Description | |:---:|:-----------:|:------------------:|-----------------------------------| | 0.1 | 06/24/2019 | Mohanarajan Selvaraj| Initial version | +| 1.0 | 08/01/2021 | Mohanarajan Selvaraj| Config DB Table update | # About this Manual @@ -98,7 +99,7 @@ Unknown-multicast traffic consists of all multicast traffic which donot match an 2. Support threshold rate configuration in kilo bits per second (kbps) in the range of 0 kbps to 100,000,000 kbps (100Gbps). ### 1.1.2 Configuration and Management Requirements -This feature supports Click, Klish, REST, gNMI interfaces. +This feature supports ,SONiC yang, SONiC CLI and mgmt framework interfaces(Klish, REST, gNMI). 1. Support a CLI to add or delete broadcast, unknown-unicast and unknown-multicast storm-control on a physical interface as described in "Configuration Commands" section below. 2. Support show commands to display the storm-control configuration as described in "Show Commands" section below. 3. Support debug commands as described in "Debug Commands" section below. @@ -158,7 +159,7 @@ BUM storm control __Figure 1: Storm Control High Level Architecture__ -1) Storm-control configurations are parsed and stored in PORT_STORM_CONTROL in Configuration database by the Management Framework. +1) Storm-control configurations are done using SONiC yang / SONiC CLI / management framework. The configurations are parsed and stored in PORT_STORM_CONTROL Table in Configuration database. 2) The Policer Orchestration Agent subscribes to notifications from the PORT_STORM_CONTROL and parses the input parameters (interface, storm-control type, kbps). A policer_name is created internally by encoding the interface_name and storm_control_type. 3) create_policer SAI API is invoked to create a policer with the given input parameters. 4) The identifier of the policer created is associated with the encoded policer_name. From fb74c29a6e3ce18aaff324032b71146415403d0b Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 5 Aug 2021 13:45:46 +0300 Subject: [PATCH 026/175] [ACL] Flex Counters for ACL rules Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Flex-Counters.md | 240 ++++++++++++++++++ .../img/acl-counters-acl-rule-add-flow.svg | 3 + .../img/acl-counters-acl-rule-remove-flow.svg | 3 + .../img/acl-counters-high-level-diagram.svg | 3 + 4 files changed, 249 insertions(+) create mode 100644 doc/acl/ACL-Flex-Counters.md create mode 100755 doc/acl/img/acl-counters-acl-rule-add-flow.svg create mode 100755 doc/acl/img/acl-counters-acl-rule-remove-flow.svg create mode 100755 doc/acl/img/acl-counters-high-level-diagram.svg diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md new file mode 100644 index 00000000000..3b095b8d6e7 --- /dev/null +++ b/doc/acl/ACL-Flex-Counters.md @@ -0,0 +1,240 @@ + +# ACL Flex Counters Support # + + +## Table of Content +- Revision +- Scope +- Definitions/Abbreviations +- Overview +- Requirements +- Architecture Design +- High-Level Design +- SAI +- Orchagent +- Syncd +- COUNTERS DB +- Flows +- Create ACL rule +- Delete ACL rule +- Mirror flow enhancement +- SAI API +- Configuration and management + - CLI/YANG model Enhancements + - Config DB Enhancements +- Warmboot and Fastboot Design Impact +- Restrictions/Limitations +- Testing Requirements/Design + - Unit Test cases + - System Test cases +- Open/Action items + +### Revision + +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.1 | | Stepan Blyshchak | Initial version | + +### Scope + +The scope of this document covers ACL rule counters support and enhancements in that area. +This document does not cover a reasonable option to create ACL rules without counters as +it may be that ACL rule counters consume additional ASIC resources that might or might not be +required for the end user. This feature is beyond the scope of this document. This design does +not change the existing user experience for ACL functionality. + +### Definitions/Abbreviations + +| Definitions/Abbreviation | Description | +|--------------------------|--------------------------------------------| +| ACL | Access Control List | +| API | Application Programmable Interface | +| Everflow | ERSPAN (Encapsulated Remote Switched Port Analysis) mirroring | +| FC | Flex Counter | +| VID | SAIRedis Virtual object identifier | +| RID | SAI Real object identifier | +| SAI | Switch Abstraction Interface | + +### Overview + +The current design of ACL rule counters implements polling at orchagent side at a constant hardcoded interval of 10 seconds. +While it is a simpler approach comparing to Flex Counters infrastructure it comes at a cost of scalability and performance issues. +Considering that orchagent is single threaded a pretty small amount of ACL rules in comparison to ASIC capabilities may take a while +to poll counters for lot more than 10 seconds and blocking orchagent from performing other tasks. This leads to a problem that orchagent +is always busy collecting counters for ACLs and slow responses to other tasks. + +Flex counters infrastructure on another hand already used for port, PG, queue, watermark counters solves this issue by delegating counter +polling to a separate thread in syncd and allowing to configure polling interval as well. + +### Requirements + +- Free up orchagent queue when lots of ACL rules are configured by delegating counters polling to Flex Counters thread in syncd. +- Support enabling and disabling polling based on user configuration and ```counterpoll``` CLI for it. +- Support changing polling interval in range [1-1000] sec and ```counterpoll``` CLI for it. + +### Architecture Design + +No SONiC architecture changes are required as an existing flex counter infrastructure is being used. + +

+Figure 1. ACL counters +

+ +### High-Level Design + +### SAI + +Unlike port, PG, queue, etc. ACL counters are separate SAI objects of type SAI_OBJECT_TYPE_ACL_COUNTER that are bound to an ACL rule object of type +SAI_OBJECT_TYPE_ACL_ENTRY that orchagent creates with two attributes that are being queried: + +| SAI Attribute | Description +|------------------------------|----------------------| +| SAI_ACL_COUNTER_ATTR_PACKETS | Get/set packet count | +| SAI_ACL_COUNTER_ATTR_BYTES | Get/set byte count | + +These objects as well as ACL rule are dynamic, thus at runtime they might be added or removed so the flex counter manager has to take it into consideration. + +### Orchagent + +A new type of FC is added to flex_counter/flex_counter_manager.h against its SAI object and a new FC group named "ACL" is added: + +Counter Type: +```c++ +CounterType::ACL_COUNTER +``` + +An ACL orchagent holds a new object of type FlexCounterManager and initialized with ```StatsMode::READ``` +and a default polling interval of 10 sec enabled by default: +```c++ +FlexCounterManager m_acl_fc_mgr; +``` + +Although these changes are enough to configure FC in syncd for polling at a certain interval its barely usable for CLI to consume +because of two reasons: +1. ACL counter is separate SAI object and needs to be mapped to ACL table name and ACL rule name. +2. ACL rule may be created and removed in the hardware depending on the rule type and state in the network. + One such example is a mirroring rule. A mirror rule can only exists if a mirror session is created/active. + Orchagent internally removes ACL mirror rule on session deactivation and creates it when the corresponding + session is activated. That means an ACL counter will be recreated as well and the counter will reset, however + it is not intended that ACL rule counter will reset upon session state change. A cache is required to hold an + old counter values and sum them with the newly created one. The solution to this problem is to not remove the + ACL rule counter but detach it from the ACL rule. + +### Syncd + +ACL FC group support in syncd/FlexCounter.cpp. + +### COUNTERS DB + +Counters table in COUNTERS DB: + +- "COUNTERS:oid:" + - key: SAI_ACL_COUNTER_ATTR_PACKETS + - value: Number of packets passed through this rule + - key: SAI_ACL_COUNTER_ATTR_BYTES + - value: Number of bytes passed through this rule + +``` +127.0.0.1:6379[2]> hgetall COUNTERS:oid:0x100000000037a + 1) "SAI_ACL_COUNTER_ATTR_PACKETS" + 2) "100" + 3) "SAI_ACL_COUNTER_ATTR_BYTES" + 4) "102400" +``` + +Mapping hash table in COUNTERS_DB: + +- "COUNTERS_ACL_COUNTER_RULE_MAP" + - key: ACL table name and ACL rule name separated COUNTERS DB separator (e.g: "L3_TABLE:RULE0") + - value: VID of the ACL counter + +E.g: + +``` +127.0.0.1:6379[2]> hgetall COUNTERS_ACL_COUNTER_RULE_MAP + 1) "DATA:RULE0" + 2) "oid:0x100000000037a" +``` + +### Flows + +### Create ACL rule + +

+Figure 2. Create ACL rule flow +

+ +### Delete ACL rule + +

+Figure 3. Delete ACL rule flow +

+ +### Mirror flow enhancement + +ACL counter should not be removed when mirror rule is removed on mirror session deactivation and upon mirror recreation attached back to the rule object. + +### SAI API + +No new SAI API is used. + +### Configuration and management +#### CLI/YANG model Enhancements +#### Config DB Enhancements + +Enable ACL counter polling: +``` +admin@sonic:~$ counterpoll acl enable +``` + +Disable ACL counter polling (NOTE: ACL counter objects are still configured in HW): +``` +admin@sonic:~$ counterpoll acl enable +``` + +Set ACL counter polling interval: +``` +admin@sonic:~$ counterpoll acl interval [INTERVAL IN MS] +``` + +Config DB schema with ACL key in FLEX COUNTER table: + +```json +{ +"FLEX_COUNTER_TABLE": { + "ACL": { + "FLEX_COUNTER_STATUS": "enable" + } + } +} +``` + +YANG model with ACL group: + +```yang + container ACL { + /* ACL_FLEX_COUNTER_GROUP */ + leaf FLEX_COUNTER_STATUS { + type flex_status; + } + } +``` + +### Warmboot and Fastboot Design Impact +N/A + +### Restrictions/Limitations +N/A + +### Testing Requirements/Design + +#### Unit Test cases + +1. Enhance test_flex_counters.py with ACL group +2. Enhance test_acl.py with check for ACL rule mapping and ACL counter OID inserted in FLEX COUNTER DB. + +#### System Test cases + +ACL/Everflow tests suite in sonic-mgmt covers the ACL counter functionality. + +### Open/Action items diff --git a/doc/acl/img/acl-counters-acl-rule-add-flow.svg b/doc/acl/img/acl-counters-acl-rule-add-flow.svg new file mode 100755 index 00000000000..24c3a94b833 --- /dev/null +++ b/doc/acl/img/acl-counters-acl-rule-add-flow.svg @@ -0,0 +1,3 @@ + + +
loop
loop
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
hset COUNTERS:<counter VID> attr value
hset COUNTERS:<counter VID> attr value
return
return
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
hset COUNTERS_ACL_COUNTER_RULE_MAP 
hset COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
hset FLEX_COUNTER:<counter VID> attr IDs 
hset FLEX_COUNTER:<counter VID> attr IDs 
return
return
SAI
SAI
dispatch
dispatch
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
sai_acl_api->get_acl_counter_attribute
sai_acl_api->get_acl_counter_attribute
return
return
Set new rule to map
Set new rule to map
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-counters-acl-rule-remove-flow.svg b/doc/acl/img/acl-counters-acl-rule-remove-flow.svg new file mode 100755 index 00000000000..d71ae837832 --- /dev/null +++ b/doc/acl/img/acl-counters-acl-rule-remove-flow.svg @@ -0,0 +1,3 @@ + + +
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
SAI
SAI
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
Remove VID from rule mapping
Remove VID from rule mappi...
remove counter OID
remove counter OID
del FLEX_COUNTER:<counter VID>
del FLEX_COUNTER:<counter VID>
return
return
return
return
del COUNTERS_ACL_COUNTER_RULE_MAP 
del COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
del COUNTERS:<counter VID>
del COUNTERS:<counter VID>
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-counters-high-level-diagram.svg b/doc/acl/img/acl-counters-high-level-diagram.svg new file mode 100755 index 00000000000..07cf42634af --- /dev/null +++ b/doc/acl/img/acl-counters-high-level-diagram.svg @@ -0,0 +1,3 @@ + + +
SONiC Switch
SONiC Switch
swss
swss
syncd
syncd
orchagent
orchagent
syncd
syncd
COUNTERS DB
COUNTERS DB
CONFIG DB
CONFIG DB
Flex Counters thread
Flex Counters th...
ACL orch
ACL orch
FLEX COUNTER DB
FLEX COUNTER DB
Actor
Actor
Viewer does not support full SVG 1.1
\ No newline at end of file From ec3b5bbd86b128a0f5c2ae0341c0562177de0dd7 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 11 Aug 2021 19:05:07 -0400 Subject: [PATCH 027/175] Update HLD with newest internal version Includes updates to address Microsoft's comments --- .gitignore | 2 + doc/pins/images/pins_arch.png | Bin 162127 -> 0 bytes doc/pins/images/pins_arch.svg | 1 + doc/pins/images/pins_arch_full.svg | 1 + doc/pins/images/sai_p4.png | Bin 76424 -> 0 bytes doc/pins/images/sai_p4.svg | 1 + doc/pins/in_progress.md | 3 + doc/pins/pins_hld.md | 316 +++++++++++++++++++---------- 8 files changed, 219 insertions(+), 105 deletions(-) delete mode 100644 doc/pins/images/pins_arch.png create mode 100644 doc/pins/images/pins_arch.svg create mode 100644 doc/pins/images/pins_arch_full.svg delete mode 100644 doc/pins/images/sai_p4.png create mode 100644 doc/pins/images/sai_p4.svg create mode 100644 doc/pins/in_progress.md diff --git a/.gitignore b/.gitignore index 2543955bc67..66d2a676053 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *~ *.swp *.un~ +.DS_Store +.vscode/ diff --git a/doc/pins/images/pins_arch.png b/doc/pins/images/pins_arch.png deleted file mode 100644 index 4c09410621ebbee3b0d1b8ee9885eb72c30515fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162127 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 diff --git a/doc/pins/images/pins_arch.svg b/doc/pins/images/pins_arch.svg new file mode 100644 index 00000000000..5c89fc4246b --- /dev/null +++ b/doc/pins/images/pins_arch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/pins/images/pins_arch_full.svg b/doc/pins/images/pins_arch_full.svg new file mode 100644 index 00000000000..9fb5e0ba991 --- /dev/null +++ b/doc/pins/images/pins_arch_full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/pins/images/sai_p4.png b/doc/pins/images/sai_p4.png deleted file mode 100644 index 9f024b2f6898d540b8f3dff924e9d711b9d251b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76424 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 diff --git a/doc/pins/images/sai_p4.svg b/doc/pins/images/sai_p4.svg new file mode 100644 index 00000000000..8f46f23e046 --- /dev/null +++ b/doc/pins/images/sai_p4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/pins/in_progress.md b/doc/pins/in_progress.md new file mode 100644 index 00000000000..74f2618ec4f --- /dev/null +++ b/doc/pins/in_progress.md @@ -0,0 +1,3 @@ +# PINS Supplementary HLD + +*This HLD is a WIP and will be uploaded soon.* diff --git a/doc/pins/pins_hld.md b/doc/pins/pins_hld.md index e328d21c23c..e0a8459a650 100644 --- a/doc/pins/pins_hld.md +++ b/doc/pins/pins_hld.md @@ -1,194 +1,300 @@ # PINS HLD -_Rev v0.1_ +_Rev v0.1.1_ ## Table of Contents + +- [Revision](#revision) +- [Scope](#scope) +- [Definitions / Abbreviations](#definitions--abbreviations) +- [Overview](#overview) + - [Open Source](#open-source) + - [Opt-In Path Towards SDN](#opt-in-path-towards-sdn) + - [Familiar Interface](#familiar-interface) + - [Unambiguous Documentation](#unambiguous-documentation) +- [Requirements](#requirements) +- [Architecture](#architecture) +- [High-Level Design](#high-level-design) + - [P4RT Application](#p4rt-application) + - [P4 Programs & P4 Info](#p4-programs--p4-info) + - [P4 Compiler and the P4 Info](#p4-compiler-and-the-p4-info) + - [P4 APPL DB Tables](#p4-appl-db-tables) + - [P4 Orchagent](#p4-orchagent) + - [Application Level Responses](#application-level-responses) + - [Packet IO](#packet-io) + - [Receiving Packets (Packet Ins)](#receiving-packets-packet-ins) + - [Transmitting Packet (Packet Outs)](#transmitting-packet-packet-outs) +- [Repositories](#repositories) +- [SAI API](#sai-api) +- [Configuration and management](#configuration-and-management) + - [CLI / YANG model Enhancements](#cli--yang-model-enhancements) + - [Config DB Enhancements](#config-db-enhancements) +- [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) +- [Restrictions / Limitations](#restrictions--limitations) +- [Testing Requirements / Design](#testing-requirements--design) +- [Open / Action items - if any](#open--action-items---if-any) +- [Supplementary Documents](#supplementary-documents) + -* [Revisions](#revisions) -* [Scope](#scope) -* [Definitions/Abbreviations](#definitions-abbreviations) -* [Overview](#overview) - + [Open Source](#open-source) - + [Opt-In Path Towards SDN](#opt-in-path-towards-sdn) - + [Familiar Interface](#familiar-interface) - + [Unambiguous Documentation](#unambiguous-documentation) -* [Requirements](#requirements) -* [Architecture Design](#architecture-design) -* [High-Level Design](#high-level-design) - + [P4RT Application](#p4rt-application) - + [P4 Programs & P4 Info](#p4-programs---p4-info) - + [P4 APPL DB Tables](#p4-appl-db-tables) - + [P4 Orchagent](#p4-orchagent) - + [Application Level Responses](#application-level-responses) - + [Packet IO](#packet-io) - + [Repositories](#repositories) -* [SAI API](#sai-api) -* [Configuration and management](#configuration-and-management) - + [CLI/YANG model Enhancements](#cli-yang-model-enhancements) - + [Config DB Enhancements](#config-db-enhancements) -* [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) -* [Restrictions/Limitations](#restrictions-limitations) -* [Testing Requirements/Design](#testing-requirements-design) -* [Open/Action items - if any](#open-action-items---if-any) -* [Supplementary Documents](#supplementary-documents) - - - -## Revisions - -| Rev | RevDate | Author(s) | Change Description -|------|------------|--------------------|-------------------- -| v0.1 | 06/24/2021 | Google, ONF, Intel | Initial version + +## Revision + +| Rev | Rev Date | Author(s) | Change Description | +|------|------------|--------------------|--------------------| +| v0.1 | 06/24/2021 | Mythil Raman (Google), Waqar Mohsin (Google), Bhagat Janarthanan (Google), Reshma Sudarshan (Intel), Brian O’Connor (ONF) | Initial version | +| v0.1.1 | 08/11/2021 | Bhagat Janarthanan (Google), Brian O’Connor (ONF) | Update based on feedback from Microsoft SONiC team | ## Scope + This document describes the high level design of PINS - P4 Integrated Network Stack. It provides a detailed explanation of the components that need to be added and modified in the SONiC framework to support a remote controller to program the forwarding tables. -## Definitions/Abbreviations +## Definitions / Abbreviations **P4**: Programming Protocol-independent Packet Processors (P4) is a domain-specific language for network devices, specifying how data plane devices (switches, NICs, routers, filters, etc.) process packets -**P4RT**: P4Runtime (P4RT) is a control plane specification for controlling the data plane elements of a device defined or described by a P4 program. +**P4RT**: P4Runtime (P4RT) is a control plane specification for controlling the data plane elements of a device defined or described by a P4 program. The [latest version of the P4Runtime spec][p4rt-spec-ref] is available on the P4 website. -**PINS**: P4 Integrated Network Stack (PINS) is a project that provides additional components and changes to SONiC and allows the stack to be remotely controlled using P4 and P4Runtime. +**PINS**: P4 Integrated Network Stack (PINS) is a project that provides additional components and changes to SONiC and allows the stack to be remotely controlled using P4 and P4RT. **SAI**: Switch Abstraction Interface (SAI) is a standardized interface which allows programming and managing different switch ASICs in a vendor-independent fashion. **SDN**: Software Defined Networking (SDN) is the practice of disaggregating the data, control, and management planes of networks, and implementing the control and management planes outside the switch. +## Overview -## Overview -This document describes **PINS (P4 Integrated Network Stack)**, a P4Runtime (P4RT) based SDN interface for programming the forwarding tables through SAI APIs. P4Runtime for SAI is open sourceable, is opt-in, has familiar interfaces, enables rapid innovation, provides automated validation, and serves as unambiguous documentation. +This document describes **PINS (P4 Integrated Network Stack)**, a P4RT based SDN interface for SONiC. P4RT for SONiC is opt-in, has familiar interfaces, enables rapid innovation, provides automated validation, and serves as unambiguous documentation. -A canonical family of P4 programs (included in the repository) documents the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. +A canonical family of P4 programs documents the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. ### Open Source -The family of P4 programs, the P4RT server, the orchagent code to translate from P4RT to SAI, the validation framework, and any P4 compiler extensions will all be open sourced. The user and vendor specific aspects of a switch pipeline are cleanly separated into extension and configurable tables. + +The family of P4 programs, the P4RT application server, the orchagent code to translate from P4RT to SAI, the validation framework, and any P4 compiler extensions will all be open sourced. The user and vendor specific aspects of a switch pipeline are cleanly separated into extension and configurable tables. ### Opt-In Path Towards SDN -The P4RT Application is completely opt-in. If the P4RT interface is not used, the remaining parts of SONiC will continue to work the way it does today. This new interface allows interested operators to gradually move towards SDN without needing a full-fledged SDN controller right from the start. It is possible to continue relying on SONiC-provided protocols for some aspects, and to start using P4RT for others. + +The P4RT Application is completely opt-in. If the P4RT interface is not used, the remaining parts of SONiC will continue to work the way they do today. This new interface allows interested operators to gradually move towards SDN without needing a full-fledged SDN controller right from the start. It is possible to continue relying on SONiC-provided protocols for some aspects, and to start using P4RT for others. ### Familiar Interface + The family of P4 programs models the SAI forwarding pipeline, making the P4RT interface familiar to anyone who has worked with SONiC/SAI before. The P4RT interface provides essential networking features (L2 bridging, L3 routing, ACLs, etc.) allowing users to quickly get up to speed on how to use this new API. ### Unambiguous Documentation -The SAI P4 programs will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. The P4 program for L3 routing will be modeled after the SAI pipeline for L3 (the full SAI pipeline is described [here](https://github.com/opencomputeproject/SAI/blob/master/doc/object-model/pipeline_object_model.pdf)). + +The SAI P4 programs will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. The P4 program for L3 routing will be modeled after the SAI pipeline for L3. More details on the full SAI pipeline are available in the [SAI Pipeline Object Model][sai-model-ref]. ## Requirements -The following components are targeted for the SONiC 2021-11 Release -* P4RT application server that runs in its own container. -* P4RT-Orchagent that runs as part of SWSS -* P4 program -The following functionality will be available -* P4RT clients can use P4Runtime to program IP route entries, next hop members and groups, and ACL entries to drop or punt packets to the control plane. -* P4RT clients can program ACLs to punt packets received in the ingress pipeline. These packets will be punted to the P4RT application running in the switch and will be forwarded to the client over grpc. -* Users can introduce custom private extensions to the pipeline by adding other elements to the P4 program. +The following components are targeted for the SONiC 2021-11 Release: + +* P4RT application that runs in its own container, +* P4RT-Orchagent that runs as part of SWSS, and +* SAI P4 program. -Additional functionality will be made available in future releases. +These components will enable the following functionality: -## Architecture Design +* P4RT clients can use P4RT to program IP route entries, next hop members and groups, and ACL entries to drop or punt packets to the control plane. +* P4RT clients can program ACLs to punt packets received in the ingress pipeline. These packets will be punted to the P4RT application running in the switch and will be forwarded to the client over the P4RT gRPC channel. +* Users can introduce custom private extensions to the pipeline by adding other elements to the P4 program. + +Additional functionality will be made available in future releases. Warmboot / fastboot capability will not be supported for the P4RT application in the first MVP release. Support will be added in subsequent releases. Warmboot / fastboot capabilities for other applications will continue to function as normal and will not be impacted by PINS. + +For the first release, the P4RT application will be integrated using SONiC’s traditional, monolithic build, but we will explore moving the new application extension framework in a subsequent release. + +## Architecture SONiC is structured into various containers that communicate through multiple logical databases via a shared Redis instance. To add SDN support, PINS introduces a few new components into the SONiC system: -* P4RT: An application that receives P4 programming requests from the controller and programs the requests to the lower layers. -* P4RT tables: a new APPL DB table that defines the P4 programming requests. -* P4orch: A new orch that programs the P4RT table from APPL DB to ASIC DB. It also sends response notifications to P4RT and manages the APPL STATE DB. -* APPL STATE DB: A new DB for applications to query the system status. It has the same schema of the APPL DB. -![alt_text](images/pins_arch.png "image_tooltip") +* P4RT: An application that receives P4 programming requests from the controller and programs the requests to the APPL DB. +* P4RT tables: a new APPL DB table that defines the P4 programming requests. +* P4Orch: A new orch that programs the P4RT table from APPL DB to ASIC DB. It also sends response notifications to P4RT and manages the APPL STATE DB. +* APPL STATE DB: A new DB for applications to query the system status. It has the same schema of the APPL DB. -The P4RT application listens to a remote SDN controller and creates entries in the APPL and CONFIG databases. Following the SONiC architecture, the P4RT application writes its output to a new table in the APPL database. From there, the new P4RT orchestration agent (orchagent) picks up the changes and writes the entries into the existing ASIC tables, where they get picked up by syncd. This path is highlighted in solid purple in the following figure. There is an alternative path (in dotted pink) that some SAI objects might choose to take, which is going through existing APP database tables, and then following the existing agents in the SWSS container down to the ASIC database. Note that whether the dotted pink or solid purple path is taken is a static decision made by the implementer of the P4RT app. For every kind of object, we statically decide which path is taken, and then only implement that path. The P4 program is not changed due to this change, it is an implementation detail of the switch not exposed to the outside (the controller, or even the vendor layer). +![PINS Architecture Diagram][arch-img] + + +The P4RT application listens to a remote SDN controller and creates entries in the APPL and CONFIG databases. Following the SONiC architecture, the P4RT application writes its output to a new table in the APPL database. From there, the new P4Orch picks up the changes and writes the entries into the existing ASIC tables, where they get picked up by syncd. This path is highlighted in green in the PINS Architecture figure. +The red path is used if a new table, match, or action is being added from the P4RT application into the ASIC DB when this table is not present in the SAI pipeline. More detailed information regarding the red path is provided in the supplementary document: [P4 Extensions for SAI][p4ext-hld]. ## High-Level Design + The high level architecture can be broken down into a set of modules that interact and work together to provide the functionality. +![PINS Architecture Diagram][arch-full-img] + + ### P4RT Application -The P4RT application runs in its own container and supports multiple gRPC client sessions. The application is responsible for parsing the requests from its clients, verifying them and writing the intent to the new P4 tables in APPL DB and notifying the clients of the eventual success/failure of the intent. The P4RT application also supports read requests from its clients. The read requests provide clients with current state information of the switch. More detailed information regarding the P4RT application is provided in the supplementary document [P4RT and APPL DB Schema](#bookmark=id.4o11cru31903). + +The P4RT application runs in its own container and supports multiple gRPC client sessions. The application is responsible for parsing the requests from its clients, verifying them and writing the intent to the new P4 tables in APPL DB and notifying the clients of the eventual success/failure of the intent. The P4RT application also supports read requests from its clients. The read requests provide clients with current state information of the switch. More detailed information regarding the P4RT application is provided in the supplementary document: [P4RT Application][p4rt-hld]. ### P4 Programs & P4 Info -The P4RT Application comes along with a canonical family of P4 programs (also open-source) that outline the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. The SAI P4 programs will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. -The SAI pipeline is modeled as a P4 program which can be compiled using a P4 compiler ([https://github.com/p4lang/p4c](https://github.com/p4lang/p4c)). The output of the compiler is a P4Info file with a description of the various tables and other objects in the P4 program. This is used by the P4RT Application. Assuming a switch vendor supports the SAI pipeline nothing more is needed. Vendors supporting a P4 backend may use other outputs from the compiler. +P4 is used in two ways: to describe the existing SAI pipeline and to extend it. -![alt_text](images/sai_p4.png "image_tooltip") +First, P4 can model the fixed and configurable elements of the existing SAI pipeline. The SAI P4 definition will serve as an unambiguous documentation of the SAI pipeline. This will help to minimize differences between SAI implementation provided by various vendors, and serve as a reference for the community at large. -Fixed SAI components are modeled after the [SAI Pipeline Object Model](https://github.com/opencomputeproject/SAI/blob/master/doc/object-model/pipeline_object_model.pdf). +The P4RT Application comes along with a canonical family of P4 programs (also open-source) that outline the packet forwarding pipeline of SAI. Remote SDN controllers will use these P4 programs to control the switch forwarding behavior over the P4RT API. -Yellow boxes represent the fixed components of the SAI pipeline. These will be the same in every P4 program. Blue boxes represent the configurable components of the SAI pipeline, namely Access Control Lists (ACLs). Every ACL follows the same basic schema, but can be customized for the use-case by changing the match fields and actions (subject to restrictions w.r.t. what SAI allows). +For existing SAI features, the vendor does not need to support P4 in any way. The P4 entities are mapped to existing SAI API objects that are passed to unmodified vendor SAI implementations. For fixed and configurable SAI features, PINS is designed to work on all of SONiC’s existing targets without modification to SAI. -### P4 APPL DB Tables -This is the interface between the P4RT app and the P4RT orch agent. The set of tables are collectively called the _P4RT Tables_. +Second, users can use P4 to define custom extensions to the SAI pipeline. For these extensions, vendors will need to either provide a P4 compiler to map them to their hardware target. Alternatively, the vendor can manually map these extensions to their SDK API in a similar manner to the existing SAI extension mechanism. -In SONiC, the APPL DB contains high level details of the programming as compared to the ASIC DB tables. Unlike traditional SONiC applications, the SDN controller provides low level details and such a level of detailed programming is not supported by most of the existing APPL DB tables. +#### P4 Compiler and the P4 Info -To overcome this limitation, the PINS architecture defines new APPL_DB tables that allow more detailed definitions. The P4RT application writes to these tables. The new tables are written by the P4RT application and consumed by the P4RT Orchagent. +The SAI pipeline is modeled as a P4 program which can be compiled using a [P4 compiler][p4c-repo]. The output of the compiler is a P4Info file with a description of the various tables and other objects in the P4 program; the P4Info comes from the compiler frontend and is not vendor specific. This is used by the P4RT Application, and it is pushed by the P4RT client on the initial connection to the switch. Assuming a switch vendor supports the SAI pipeline, nothing more is needed. Vendors supporting a P4 backend may use other outputs from the compiler. -Readability is an important criteria for SONiC DB tables. The new tables are no different in this respect and use consistent formatting. The new tables are named with the prefix P4RT to easily identify them as P4RT application tables. The naming follows the convention of `P4RT:` where TableType is of FIXED or configurable (only ACL for now) and TableName is the specific table in the SAI pipeline specification like router interface, neighbor, nexthop, IPV4/IPV6 tables etc. +![SAI P4 Pipeline][saip4-img] + -An example table definition is shown below. +Fixed SAI components are modeled after the [SAI Pipeline Object Model][sai-model-ref]. -``` -P4RT:FIXED_NEXTHOP_TABLE:{"match/nexthop_id":"node-1234:eth-1/2/3"} - "action" = "set_nexthop" - "param/router_interface_id" = "intf-eth-1/2/3" - "param/neighbor_id" = "10.0.0.22" - "controller_metadata" = "..." -``` +Yellow boxes represent the fixed components of the SAI pipeline. These will be the same in every P4 program. Blue boxes represent the configurable components of the SAI pipeline, namely Access Control Lists (ACLs). Every ACL follows the same basic schema, but can be customized for the use-case by changing the match fields and actions (subject to restrictions w.r.t. what SAI allows). Red boxes represent SAI extensions, that are provided by the vendor or network operators, and consumed by users through P4RT. Detailed information along with example use cases is provided in the supplementary documentation: [SAI P4 Program][saip4-hld] and [P4 Extensions for SAI][p4ext-hld]. -Detailed information regarding the schema of the tables and a set of guidelines for consistency are provided in the supplementary documentation on [P4RT and APPL DB Schema](#broken-todo). +The green path (i.e. SAI path) shown in the architecture diagram programs the tables corresponding to the yellow and blue boxes. The red path (i.e. SAI extension path) programs the tables corresponding to the red boxes. + +### P4 APPL DB Tables + +This is the interface between the P4RT app and the P4RT orch agent. The set of tables are collectively called the _P4RT Tables_. + +In SONiC, the APPL DB contains high level details of the programming as compared to the ASIC DB tables. Unlike traditional SONiC applications, the SDN controller provides low level details and such a level of detailed programming is not supported by most of the existing APPL DB tables. + +To overcome this limitation, the PINS architecture defines new APPL_DB tables that allow more detailed definitions. The P4RT application writes to these tables. The new tables are written by the P4RT application and consumed by the P4RT Orchagent. + +Readability is an important criteria for SONiC DB tables. The new tables are no different in this respect and use consistent formatting. The new tables are named with the prefix P4RT to easily identify them as P4RT application tables. The naming follows the convention of `P4RT:` where TableType is either FIXED or configurable (only ACL for now) and TableName is the specific table in the SAI pipeline specification like router interface, neighbor, next hop, IPV4/IPV6 tables etc. + +Detailed information regarding the schema of the tables and a set of guidelines for consistency are provided in the supplementary documentation: [P4RT APPL DB Schema][p4rt-db-hld]. ### P4 Orchagent -The P4Orchagent processes the entries added to the new P4 tables in APPL DB by the P4RT application, parses and resolves them and then invokes the necessary SAI APIs to create ASIC DB entries. SAI objects created by the P4RTOrch could refer to SAI objects created by other orchagents. In these cases, the P4Orchagent will interact with the corresponding orchagents to reference those objects and increase reference counters where necessary. Detailed information regarding the operation of the P4 Orchagent is provided in the supplementary documentation on [P4 Orchagent](#broken-todo). + +The P4 Orchagent (P4Orch) processes the entries added to the new P4 tables in APPL DB by the P4RT application, parses and resolves them and then creates the necessary SAI objects and adds them as entries to ASIC DB. SAI objects created by the P4Orch could refer to SAI objects created by other orchagents. In these cases, the P4Orch will interact with the corresponding orchagents to reference those objects and increase reference counters where necessary. Detailed information regarding the operation of the P4Orch is provided in the supplementary document: [P4 Orchagent][p4orch-hld]. ### Application Level Responses -PINS introduces the concept of application level responses. SONiC currently supports synchronous communication between SWSS and Syncd containers. PINS extends synchronized communication to applications. -Most SDN controllers require an acknowledgement of success or failure for each programming request. Subsequent programming from the controller depends on the response. SDN controllers are intelligent and can adapt to failures quickly. If one of the switches encounters a failure, the controller can utilize the other switches to achieve its goals. +PINS introduces the concept of application level responses. SONiC currently supports synchronous communication between the SWSS and Syncd containers. PINS extends synchronized communication to applications. + +Most SDN controllers require an acknowledgement of success or failure for each programming request. Subsequent programming by the controller depends on the response. SDN controllers are intelligent and can adapt to failures quickly. If one of the switches encounters a failure, the controller can utilize the other switches to achieve its goals. -The controller requires state information from the switches in order to quickly identify any failures. This is accomplished by the addition of application level responses and state. More information regarding this is provided in the supplementary documentation [Response path and Application DB](#broken-todo). +The controller requires state information from the switches to quickly identify any failures. This is accomplished by the addition of application level responses and state. More information regarding this is provided in the supplementary document: [APPL STATE DB and Response Path][appl-state-hld]. ### Packet IO -P4RT clients can program ACLs to punt packets received in the ingress pipeline. These packets will be trapped and punted to the P4RT application running in the switch and will be forwarded to the client over grpc. -SONiC relied on basic packet I/O support that uses netdev ports to send and receive packets. P4Runtime applications require additional packet attributes like the target egress port which are not available via netdev. Similarly directed Tx from application level is not currently supported in the SONiC framework. This is required to support scenarios where the remote SDN controller needs to send a packet via one of the front panel ports of the switch. +There are multiple scenarios where the remote controller is interested in listening on the ingress pipeline of the switch for specific packets and getting those packets sent to it. Similarly, the controller is interested in sending specific packets through the egress pipeline and requires the packet to be routed based on the rules already programmed in the switch. These are the receive and transmit rules. + +P4RT clients can program ACLs to punt or copy packets received in the ingress pipeline. These packets will be trapped and sent to the P4RT application running in the switch and will be forwarded to the client over gRPC. + +SONiC relies on basic packet I/O support that uses netdev ports to send and receive packets. PINS follows the example of most SONiC applications and uses devices rather than SAI APIs for packet I/O. -To support the above requirements, a model similar to sFlow is used. The receive solution creates a netlink type host interface. It programs a user defined trap for packets that are interesting to the controller and maps them to the netlink host interface. A generic ASIC independent model is defined for passing parameters such as “target egress port” to the application container. A detailed description of the receive path is present in the supplementary document on [Packet IO](#broken-todo). +#### Receiving Packets (Packet Ins) + +P4RT clients require additional packet attributes, like the target egress port, which are not available via netdev. To support the above requirements, a model similar to the one used to add sFlow to SONiC is used. The packet receive path creates a genetlink type host interface. It programs a user defined trap for packets that are interesting to the controller and maps them to the genetlink host interface. A generic ASIC independent model is defined for passing parameters such as “target egress port” to the application container. + +#### Transmitting Packet (Packet Outs) + +For packets that should be directly transmitted from a specific port, PINS uses the standard SONIC port netdevs. These packets will bypass ingress pipeline processing. + +PINS requires packet transmission based on the programming present in the ASIC. This is required to support scenarios where the remote SDN controller needs to route a packet entirely based on the ASIC hardware tables. To support this feature, PINS introduces a new netdev (“send_to_ingress”) that will send packets through the ingress pipeline before they are transmitted. + +A detailed description of the receive and transmit paths is present in the supplementary document: [Packet IO][packet-hld]. + +## Repositories -### Repositories This design adds the following new repositories: -* P4RT Application -It also has modifications in the following repositories: -* SWSS -* SONiC Build Image +* P4RT Application + +It also has modifications in the following existing SONiC repositories: + +* [SWSS][swss-repo] +* [SWSS-Common][swss-common-repo] +* [SONiC Build Image][buildimage-repo] ## SAI API -There are no changes to SAI. -For programmable hardware targets, PINS introduces an additional SAI header, saip4ext.h, to map user-defined private P4 extensions to vendor SAI implementations. More details on saip4ext.h can be found in the supplemental document [P4 Extensions for SAI](#broken-todo). +PINS uses existing SAI features without any changes, included fixed functions (e.g. routing) and configurable ones (e.g. ACLs). + +For programmable hardware targets, PINS introduces an additional SAI header, saip4ext.h, to map user-defined private P4 extensions to vendor SAI implementations. More details on saip4ext.h can be found in the supplemental document: [P4 Extensions for SAI][p4ext-hld]. ## Configuration and management -### CLI/YANG model Enhancements +### CLI / YANG model Enhancements + There are no CLI changes. ### Config DB Enhancements -There are no Config DB changes. + +There will be configuration entries to enable and disable PINS features. For example, writing the responses to the APPL STATE DB will be controlled by a flag. + +The first version of the P4RT application will use a default set of configuration, including gRPC listening port (tcp/9559) and transport security options. These are hardcoded, but can be changed by editing the P4RT application source code. In future releases, we will aim to model this configuration in Config DB using a similar approach as gNMI (sonic-telemetry). ## Warmboot and Fastboot Design Impact -Similar to other orchagents, the P4Orchagent needs to perform actions for successful warm boot and fast boot operation. These changes are being planned for the next phase ( next SONiC release). In this phase, warmboot and fastboot features will not be supported for objects created through the P4RT application. When the P4RT application is not used, warm boot and fastboot will continue to operate as before. There will be no impact on existing warmboot and fastboot design. -## Restrictions/Limitations -In this introductory phase, limited functionality and features will be supported through the P4RT application. The details of supported features are provided in the requirements section. +When the P4RT application is used, the P4Orch needs to perform specific actions for successful warm boot and fast boot operation. These changes are being planned for the next phase (i.e. the next SONiC release). In the first MVP release, warmboot and fastboot features will not be supported for objects created through the P4RT application. This will not affect warm boot operations for objects created through other orchagents. + +## Restrictions / Limitations + +In the first MVP release, limited functionality and features will be supported through the P4RT application. The details of supported features are provided in the requirements section. + +## Testing Requirements / Design + +The entire PINS code, including the P4RT Application and P4Orch, is well unit tested. The coverage goal is at least 90% which is already achieved. Integration tests will be added in the following release. + +## Open / Action items - if any + +## Supplementary Documents + +Here is the full list of supplementary HLD docs: + +* [P4RT Application][p4rt-hld] +* [SAI P4 Program][saip4-hld] +* [P4 Extensions for SAI][p4ext-hld] +* [P4RT APPL DB Schema][p4rt-db-hld] +* [P4 Orchagent][p4orch-hld] +* [APPL STATE DB & Response Path][appl-state-hld] +* [Packet IO][packet-hld] + + + + + +[p4rt-hld]: p4rt_app_hld.md +[saip4-hld]: in_progress.md +[p4ext-hld]: in_progress.md +[p4rt-db-hld]: in_progress.md +[p4orch-hld]: p4orch_hld.md +[appl-state-hld]: in_progress.md +[packet-hld]: in_progress.md + +[buildimage-repo]: https://github.com/Azure/sonic-buildimage +[p4c-repo]: https://github.com/p4lang/p4c +[swss-repo]: https://github.com/Azure/sonic-swss +[swss-common-repo]: https://github.com/Azure/sonic-swss-common -## Testing Requirements/Design -The entire PINS code, including the P4RT Application, P4 orchagent, etc is well unit tested. The coverage goal is at least 90% which is already achieved. Integration tests will be added in the following release. + +[p4rt-spec-ref]: https://p4lang.github.io/p4runtime/spec/main/P4Runtime-Spec.html +[sai-model-ref]: https://github.com/opencomputeproject/SAI/blob/master/doc/object-model/pipeline_object_model.pdf -## Open/Action items - if any -None + +[arch-img]: images/pins_arch.svg +[arch-full-img]: images/pins_arch_full.svg +[saip4-img]: images/sai_p4.svg From 078b908db3604e17f5b07e3656388a164e209427 Mon Sep 17 00:00:00 2001 From: Bhagatram Janarthanan Date: Wed, 11 Aug 2021 20:49:01 -0700 Subject: [PATCH 028/175] Update pins_hld.md --- doc/pins/pins_hld.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/pins/pins_hld.md b/doc/pins/pins_hld.md index e0a8459a650..43f6d037dfe 100644 --- a/doc/pins/pins_hld.md +++ b/doc/pins/pins_hld.md @@ -196,21 +196,20 @@ The controller requires state information from the switches to quickly identify ### Packet IO -There are multiple scenarios where the remote controller is interested in listening on the ingress pipeline of the switch for specific packets and getting those packets sent to it. Similarly, the controller is interested in sending specific packets through the egress pipeline and requires the packet to be routed based on the rules already programmed in the switch. These are the receive and transmit rules. +There are multiple scenarios where the remote controller is interested in listening on the ingress pipeline of the switch for specific packets and getting those packets along with additional information. In certain other scenarios, the controller is interested in sending specific packets through the egress pipeline and requires the packet to be routed based on the rules already programmed in the switch. -P4RT clients can program ACLs to punt or copy packets received in the ingress pipeline. These packets will be trapped and sent to the P4RT application running in the switch and will be forwarded to the client over gRPC. - -SONiC relies on basic packet I/O support that uses netdev ports to send and receive packets. PINS follows the example of most SONiC applications and uses devices rather than SAI APIs for packet I/O. #### Receiving Packets (Packet Ins) -P4RT clients require additional packet attributes, like the target egress port, which are not available via netdev. To support the above requirements, a model similar to the one used to add sFlow to SONiC is used. The packet receive path creates a genetlink type host interface. It programs a user defined trap for packets that are interesting to the controller and maps them to the genetlink host interface. A generic ASIC independent model is defined for passing parameters such as “target egress port” to the application container. +P4RT clients can program ACLs to punt or copy packets received in the ingress pipeline. These packets will be trapped and sent to the P4RT application running in the switch and will be forwarded to the client over gRPC. + +P4RT clients require additional packet attributes, like the target egress port, which are not available via netdev. To support the above requirements, a model similar to the one used to add sFlow to SONiC is used. The packet receive path creates a genetlink type host interface. The P4RT application programs user defined traps for packets that are interesting to the controller and maps them to the genetlink host interface. A generic ASIC independent model is defined for passing parameters such as “target egress port” to the application container. #### Transmitting Packet (Packet Outs) For packets that should be directly transmitted from a specific port, PINS uses the standard SONIC port netdevs. These packets will bypass ingress pipeline processing. -PINS requires packet transmission based on the programming present in the ASIC. This is required to support scenarios where the remote SDN controller needs to route a packet entirely based on the ASIC hardware tables. To support this feature, PINS introduces a new netdev (“send_to_ingress”) that will send packets through the ingress pipeline before they are transmitted. +PINS also requires packet transmission based on the programming present in the ASIC. To support this feature, PINS introduces a new netdev (“send_to_ingress”) that will send packets through the ingress pipeline before they are transmitted. A detailed description of the receive and transmit paths is present in the supplementary document: [Packet IO][packet-hld]. From 774e54ccd5ed5a7dc4a58f92db44dfdfa725d59e Mon Sep 17 00:00:00 2001 From: Alexandru Banu Date: Mon, 16 Aug 2021 15:44:21 +0300 Subject: [PATCH 029/175] Added MPLS EXP to TC map HLD --- doc/qos/mpls_exp_to_tc_map.md | 131 ++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 doc/qos/mpls_exp_to_tc_map.md diff --git a/doc/qos/mpls_exp_to_tc_map.md b/doc/qos/mpls_exp_to_tc_map.md new file mode 100644 index 00000000000..cec4b1d5853 --- /dev/null +++ b/doc/qos/mpls_exp_to_tc_map.md @@ -0,0 +1,131 @@ +# MPLS EXP to TC map + +## 1. Table of Content + +- [MPLS EXP to TC map](#mpls-exp-to-tc-map) + - [1. Table of Content](#1-table-of-content) + - [2. Revision](#2-revision) + - [3. Scope](#3-scope) + - [4. Definitions/Abbreviations](#4-definitionsabbreviations) + - [5. Overview](#5-overview) + - [6. Requirements](#6-requirements) + - [7. Architecture Design](#7-architecture-design) + - [8. High-Level Design](#8-high-level-design) + - [8.1. DB](#81-db) + - [8.2. sonic-swss-common](#82-sonic-swss-common) + - [8.3. sonic-swss](#83-sonic-swss) + - [8.4. sonic-utilities](#84-sonic-utilities) + - [8.5. Other implications](#85-other-implications) + - [9. SAI API](#9-sai-api) + - [10. Configuration and management](#10-configuration-and-management) + - [10.1. CLI/YANG model Enhancements](#101-cliyang-model-enhancements) + - [10.2. Config DB Enhancements](#102-config-db-enhancements) + - [11. Warmboot and Fastboot Design Impact](#11-warmboot-and-fastboot-design-impact) + - [12. Restrictions/Limitations](#12-restrictionslimitations) + - [13. Testing Requirements/Design](#13-testing-requirementsdesign) + - [13.1. Unit Test cases](#131-unit-test-cases) + - [13.2. System Test cases](#132-system-test-cases) + - [14. Open/Action items - if any](#14-openaction-items---if-any) + +## 2. Revision + +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:-----------------------:|--------------------------------------------| +| 0.1 | 16/08/2021 | Alexandru Banu | Initial version | + +## 3. Scope + +This HLD extends SONiC to support MPLS EXP to TC mappings. + +## 4. Definitions/Abbreviations + +TC = Traffic Class +QoS = Quality of Service + +## 5. Overview + +This new enhancement adds support to SONiC for MPLS EXP to TC map which allows QoS to work on MPLS packets. + +## 6. Requirements + +User can configure MPLS EXP to TC map at start-of-day via configuration file. CLI support will exist to offer the same amount of support as for DSCP to TC map. + +## 7. Architecture Design + +The overall SONiC architecture will not be changed and no new sub-modules will be introduced. + +## 8. High-Level Design + +### 8.1. DB + +The CONFIG DB will be updated to include a new "MPLS_EXP_TO_TC_MAP_TABLE" similar to the existing "DSCP_TO_TC_MAP_TABLE". This will have the following format: +``` +### MPLS_EXP_TO_TC_MAP_TABLE + ; MPLS EXP to TC map + ;SAI mapping - qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_MPLS_EXP_TO_TC + key = "MPLS_EXP_TO_TC_MAP_TABLE:"name + ;field value + mpls_exp_value = 1*DIGIT + tc_value = 1*DIGIT + + Example: + 127.0.0.1:6379> hgetall "MPLS_EXP_TO_TC_MAP_TABLE:AZURE" + 1) "3" ;mpls exp + 2) "3" ;tc + 3) "6" + 4) "5" + 5) "7" + 6) "5" +``` + +### 8.2. sonic-swss-common + +sonic-swss-common's schema will be updated to include a CFG_MPLS_EXP_TO_TC_MAP_TABLE_NAME define for the new table name. + +### 8.3. sonic-swss + +sonic-swss's QoS orch will be updated to include a new handler for MPLS EXP to TC map, similar to the existing DSCP to TC map but with extra input validations, checking that the values are in the correct numeric range and that no MPLS EXP value is mapped to more than one TC value. Among debugging logs, appropriate error logs will be introduced to let the user know if they miss-configured a map. + +### 8.4. sonic-utilities + +sonic-utilities will be updated to offer the same amount of support for CLI commands that DSCP to TC map already provide. + +### 8.5. Other implications + +There are no other implications. SAI and sairedis already support for MPLS EXP to TC map. In terms of warm restart / fastboot / scalability / performance and so on, this should not represent an impact. + +## 9. SAI API + +MPLS EXP to TC map are already supported in SAI. + +## 10. Configuration and management + +### 10.1. CLI/YANG model Enhancements + +CLI config commands will be updated to include the same level of support for MPLS EXP to TC maps as for DSCP to TC maps. Namely, `config reload` and `config clear` will be updated to include the new mapping table as well. + +### 10.2. Config DB Enhancements + +The relevant changes have been described in HLD's DB sub-section. + +## 11. Warmboot and Fastboot Design Impact + +Not impacted by the changes. + +## 12. Restrictions/Limitations + +User can't configure MPLS EXP to TC map via CLI (only via reload command). + +## 13. Testing Requirements/Design + +### 13.1. Unit Test cases + +The QoS UTs present in sonic-swss will be extended to accommodate the new MPLS EXP to TC map. These will largely follow the DSCP to TC map example but will add input validation checks as well. The new code will have full code coverage as far as the UT framework allows it. + +### 13.2. System Test cases + +No system test cases will be added. + +## 14. Open/Action items - if any + +N/A From 70ba0f2c661aa34df8ba001f97229f2add2425ca Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak <38952541+stepanblyschak@users.noreply.github.com> Date: Tue, 17 Aug 2021 16:28:25 +0300 Subject: [PATCH 030/175] Update ACL-Flex-Counters.md --- doc/acl/ACL-Flex-Counters.md | 50 +++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 3b095b8d6e7..27c5133a653 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -152,10 +152,33 @@ E.g: ``` 127.0.0.1:6379[2]> hgetall COUNTERS_ACL_COUNTER_RULE_MAP - 1) "DATA:RULE0" + 1) "L3_TABLE:RULE0" 2) "oid:0x100000000037a" ``` +### CLI + +*aclshow* utility is modified to read counters from COUNTERS DB using ACL_RULE table in CONFIG DB and COUNTERS_ACL_COUNTER_RULE_MAP in COUNTERS DB. +Utility reads all ACLs from ACL_RULE table, uses COUNTERS_ACL_COUNTER_RULE_MAP to get the VID of the ACL counter object and gets the counter values +from COUNTERS DB. If COUNTERS_ACL_COUNTER_RULE_MAP is missing an entry for the rule it either means that ACL rule was created without counter (which +is not supported right now, but might be possible in the future) or we hit a condition when orchagent hasn't yet created the rule or the entry in the +map. In both cases we will display N/A. + +``` +admin@sonic:~$ aclshow -a +RULE NAME TABLE NAME PRIO PACKETS COUNT BYTES COUNT +------------ ------------ ------ --------------- ------------- +RULE_1 DATAACL 9999 101 100 +RULE_2 DATAACL 9998 201 200 +RULE_3 DATAACL 9997 301 300 +RULE_4 DATAACL 9996 401 400 +RULE_7 DATAACL 9993 701 700 +RULE_9 DATAACL 9991 901 900 +RULE_10 DATAACL 9989 1001 1000 +DEFAULT_RULE DATAACL 1 2 1 +RULE_6 EVERFLOW 9994 601 600 +``` + ### Flows ### Create ACL rule @@ -164,12 +187,16 @@ E.g: Figure 2. Create ACL rule flow

+In case an *error* happened, we roll back, deleting objects with best effort and removing the ACL rule taks from m_toSync map. An error is printed in the syslog. + ### Delete ACL rule

Figure 3. Delete ACL rule flow

+In case an *error* happened, we proceed deleting objects with best effort and removing the ACL rule taks from m_toSync map. An error is printed in the syslog. + ### Mirror flow enhancement ACL counter should not be removed when mirror rule is removed on mirror session deactivation and upon mirror recreation attached back to the rule object. @@ -189,7 +216,7 @@ admin@sonic:~$ counterpoll acl enable Disable ACL counter polling (NOTE: ACL counter objects are still configured in HW): ``` -admin@sonic:~$ counterpoll acl enable +admin@sonic:~$ counterpoll acl disable ``` Set ACL counter polling interval: @@ -201,10 +228,11 @@ Config DB schema with ACL key in FLEX COUNTER table: ```json { -"FLEX_COUNTER_TABLE": { - "ACL": { - "FLEX_COUNTER_STATUS": "enable" - } + "FLEX_COUNTER_TABLE": { + "ACL": { + "FLEX_COUNTER_STATUS": "enable", + "POLL_INTERVAL": "10000" + } } } ``` @@ -219,6 +247,8 @@ YANG model with ACL group: } } ``` + +NOTE: YANG is currently not having POLL_INTERVAL field defined. ### Warmboot and Fastboot Design Impact N/A @@ -232,9 +262,17 @@ N/A 1. Enhance test_flex_counters.py with ACL group 2. Enhance test_acl.py with check for ACL rule mapping and ACL counter OID inserted in FLEX COUNTER DB. +3. Modify aclshow_test.py in sonic-utilities to work with new data source. #### System Test cases ACL/Everflow tests suite in sonic-mgmt covers the ACL counter functionality. ### Open/Action items + +- In case mirror session goes down, ACL rule is deleted but counters is not to save the counters values. This counter could be deleted from FLEX COUNTER DB to avoid polling it but it will trigger removal of the VID in the COUNTERS DB which we would like to keep. + - In the current desing it will work just like for PORT, QUEUE, PG counters for port in down state - meaning polling is happenning although there is no real point for it. + - It is more like an optimization for a bad scenario rather then a real optimization. A rule is created to be active and counter to be polled in the first place and there must be enough resources and free CPU time to do that. + - In case the ACL rule has more action, like mirror ingress on session s0 and mirror egress on session s1 (currently not supported but possible scenario) and if one sesssion goes down, say s0, the counter can't be removed anyway as there is still egress mirroring happening on s1. + - Considering previous items it does not make sense to remove the whole rule and a counter but just disable actions if the state in the network(session IP is reachable) requires. + - It is not clear how to remove mirror action from the rule in SAI as the SAI_ACL_ACTION_TYPE_MIRROR_INGRESS/SAI_ACL_ACTION_TYPE_MIRROR_EGRESS are not @allowempty. From 76028d17c75a3a4e908e40d64d270cc5035842cb Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak <38952541+stepanblyschak@users.noreply.github.com> Date: Tue, 17 Aug 2021 16:30:10 +0300 Subject: [PATCH 031/175] Update ACL-Flex-Counters.md --- doc/acl/ACL-Flex-Counters.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 27c5133a653..6c011d599da 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -159,10 +159,10 @@ E.g: ### CLI *aclshow* utility is modified to read counters from COUNTERS DB using ACL_RULE table in CONFIG DB and COUNTERS_ACL_COUNTER_RULE_MAP in COUNTERS DB. -Utility reads all ACLs from ACL_RULE table, uses COUNTERS_ACL_COUNTER_RULE_MAP to get the VID of the ACL counter object and gets the counter values -from COUNTERS DB. If COUNTERS_ACL_COUNTER_RULE_MAP is missing an entry for the rule it either means that ACL rule was created without counter (which +Utility reads all ACLs from ACL_RULE table, uses the map to get the VID of the ACL counter object and gets the counter values +from COUNTERS DB. If the map is missing an entry for the rule it either means that ACL rule was created without counter (which is not supported right now, but might be possible in the future) or we hit a condition when orchagent hasn't yet created the rule or the entry in the -map. In both cases we will display N/A. +map. In both cases utility displays N/A. In case the COUNTERS DB is missing a VID that exists in the rule the utilitity displays N/A. That means that either polling is disabled for ACL group or syncd haven't yet put any value in COUNTERS DB. ``` admin@sonic:~$ aclshow -a From c7a195c595ba09cfa34a8e112869e9280ab967bf Mon Sep 17 00:00:00 2001 From: stepanblyschak Date: Wed, 18 Aug 2021 20:24:38 +0300 Subject: [PATCH 032/175] [ACL] user defined ACL table types Signed-off-by: stepanblyschak --- doc/acl/ACL-Table-Type-HLD.md | 225 ++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 doc/acl/ACL-Table-Type-HLD.md diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md new file mode 100644 index 00000000000..c2db212036f --- /dev/null +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -0,0 +1,225 @@ + +# ACL User Defined Table Type Support # + + +## Table of Content + +### Revision + +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.1 | | Stepan Blyshchak | Initial version | + +### Scope + +The scope of this document covers ACL feature enhancements. + +### Definitions/Abbreviations + +| Definitions/Abbreviation | Description | +|--------------------------|--------------------------------------------| +| ACL | Access Control List | +| API | Application Programmable Interface | +| Everflow | ERSPAN (Encapsulated Remote Switched Port Analysis) mirroring | +| FC | Flex Counter | +| VID | SAIRedis Virtual object identifier | +| RID | SAI Real object identifier | +| SAI | Switch Abstraction Interface | + +### Overview + +The current design of ACL list a predefined set of table types - L3, L3V6, MIRROR, PFC_WD etc. +On every new feature added or on every new use case it is required to update ACL orchagent component with +new table type or modify existing table type. The predefined set of ACL match fields allocated for a particular +table type might also consume more HW resources then a use case requires. + +This document addresses this limitation by introducing a new concept of user defined ACL table types in SONiC. + +### Requirements + +- Support user configurable ACL table types. +- Support programming custom ACL tables by using AclOrch public interface without defining a new ACL table type. + +### Architecture Design + +No SONiC architecture changes are required. + +### High-Level Design + +### SAI + +N/A + +### Orchagent + +The AclOrch is subscribed to a table ```ACL_TABLE_TYPE``` in CFG DB. This table holds a definition for a table with the matches, actions and bind points. + +*AclTableType* Data structure: + +```c++ +struct AclTableType +{ + std::string m_name; + std::set m_bpoint_types; + std::set m_matches; + std::set m_acl_actions; +} +``` + +*AclTable*: + +```c++ +class AclTable +{ +public: + // ... + bool validateAddType(const AclTableType& type); +private: + // ... + AclTableType m_type; +} +``` + +Orchagent's ACL orch AclRule::make_shared makes decision which AclRule child instance to create based on table type. +Since orchagent does not know. + +#### Mirror table type: combined/separated table + +Orchagent has a special treatment for tables of type MIRROR and MIRRORV6 +based on the ASIC platform it is running on. There is either a "combined" or +"seperated" mode for MIRROR tables. + +``` ++-------------------+------------------------------+ +| | CONFIG DB | ASIC DB | ++-------------------+--------------+---------------+ +| combined | MIRROR | Single mirror | +| +--------------+ table in HW | +| | MIRRORV6 | V4 + V6 keys | ++-------------------+--------------+---------------+ +| seperated | MIRROR | Mirror V4 | +| +--------------+---------------+ +| | MIRRORV6 | Mirror V6 | ++-------------------+--------------+---------------+ +``` + +This does not play well with the new concept of user defined table types. +To solve this we have few options: + +1. Non backward compatible change: let the CONFIG DB table maps 1:1 in ASIC DB table. +User is able to configure either two tables types, one for IPv4, one for IPv6 or single +with IPv4 and IPv6 keys. + +2. Maintaing the current behaviour. Orchagent should have the knowledge to act in either +*combined* or *separeted* mode if the table type is named "MIRROR" or "MIRRORV6". + +3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well +as default table types. + +In this design option 2 is chosen since it maintains current behaviour and does not expose different treatment of mirror tables +based on ASIC vendor to the user. + +### Syncd + +N/A + +### CONFIG DB + +```abnf +key: ACL_TABLE_TYPE:name ; key of the ACL table type entry. The name is arbitary name user chooses. +; field = value +matches = match-list ; list of matches for this table +actions = action-list ; list of actions for this table +bind_points = bind-points-list ; list of bind point types for this table + +; values annotation +match = 1*64VCHAR +match-list = [1-max-matches]*match +action = 1*64VCHAR +action-list = [1-max-actions]*action +bind-point = port/lag +bind-points-list = [1-max-bind-points]*bind-point +``` + +Example: +```json +{ + "ACL_TABLE_TYPE": { + "L3": { + "MATCHES": [ + "IN_PORTS", + "OUT_PORTS", + "SRC_IP" + ], + "ACTIONS": [ + "PACKET_ACTION", + "MIRROR_INGRESS_ACTION" + ], + "BIND_POINTS": [ + "PORT", + "LAG" + ] + } + }, + "ACL_TABLE": { + "DATAACL": { + "STAGE": "INGRESS", + "TYPE": "L3", + "PORTS": [ + "Ethernet0", + "PortChannel1" + ] + } + }, + "ACL_RULE": { + "DATAACL|RULE0": { + "PRIORITY": "999", + "PACKET_ACTION": "DROP", + "SRC_IP": "1.1.1.1/32", + } + } +} +``` + +Yang container for ACL_TABLE_TYPE table: + +```yang +container ACL_TABLE_TYPE { + list ACL_TABLE_TYPE_LIST { + key "ACL_TABLE_TYPE_NAME"; + + leaf-list MATCHES { + type stypes:match; + } + + leaf-list ACTIONS { + type stypes:actions; + } + + leaf-list BIND_POINTS { + type stypes:acl_bind_points; + } + } +} +``` + + +### Initial CONFIG DB + +The following existing table types defined in init_cfg.json: + +- L3 +- L3V6 +- MIRROR +- MIRRORV6 +- MIRROR_DSCP +- DTEL_FLOW_WATCHLIST +- DTEL_DROP_WATCHLIST +- MCLAG + +On platforms where certain features are not supported (like in band telemetry) the error is thrown on ACL table creation +of the unsupported type. + +### Flows + +### Open questions \ No newline at end of file From c71cf1bc696e582675c56e1c1996de3778dae99e Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 19 Aug 2021 11:41:48 +0300 Subject: [PATCH 033/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index c2db212036f..597cd3b7556 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -3,6 +3,22 @@ ## Table of Content +- Revision +- Scope +- Definitions/Abbreviations +- Overview +- Requirements +- Architecture Design +- High-Level Design +- SAI +- Orchagent + - Mirror table type: combined/separated table +- Syncd +- CONFIG DB + - Control plane tables +- Initial CONFIG DB +- Flows +- Open questions ### Revision @@ -116,7 +132,7 @@ with IPv4 and IPv6 keys. 3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well as default table types. -In this design option 2 is chosen since it maintains current behaviour and does not expose different treatment of mirror tables +In this design option 2 is chosen since it maintains current behavior and does not expose different treatment of mirror tables based on ASIC vendor to the user. ### Syncd @@ -203,6 +219,21 @@ container ACL_TABLE_TYPE { } ``` +#### Control plane tables + +Control plane table are moved to its own table in CONFIG DB to not overlap with HW ACL tables. + +```json +"CTRL_PLANE_ACL_TABLE": { + "SSH_ONLY": { + "policy_desc": "SSH only", + "services": [ + "SSH" + ], + "stage": "ingress" + } +} +``` ### Initial CONFIG DB From ade9a61f3dae96c53bf89f9259c27786b89a2181 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 19 Aug 2021 15:05:44 +0300 Subject: [PATCH 034/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 57 ++++++++++++++++++++-- doc/acl/img/acl-rule-flow.svg | 3 ++ doc/acl/img/acl-rule-object-model.svg | 3 ++ doc/acl/img/acl-table-type-create-flow.svg | 3 ++ doc/acl/img/acl-table-type-remove-flow.svg | 3 ++ 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100755 doc/acl/img/acl-rule-flow.svg create mode 100755 doc/acl/img/acl-rule-object-model.svg create mode 100755 doc/acl/img/acl-table-type-create-flow.svg create mode 100755 doc/acl/img/acl-table-type-remove-flow.svg diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index 597cd3b7556..c78b76b09a5 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -13,11 +13,16 @@ - SAI - Orchagent - Mirror table type: combined/separated table + - ACL rule object model - Syncd - CONFIG DB - Control plane tables - Initial CONFIG DB - Flows + - ACL table type create flow + - ACL table type update flow + - ACL table type remove flow + - ACL rule update flow - Open questions ### Revision @@ -96,8 +101,9 @@ private: } ``` -Orchagent's ACL orch AclRule::make_shared makes decision which AclRule child instance to create based on table type. -Since orchagent does not know. +Orchagent's AclRule::make_shared makes decision which AclRule child instance to create based on table type. +Since orchagent does not know all the table types there should be single AclRule handling all the matches +and actions and perform validation against the table type configuration. #### Mirror table type: combined/separated table @@ -135,6 +141,16 @@ as default table types. In this design option 2 is chosen since it maintains current behavior and does not expose different treatment of mirror tables based on ASIC vendor to the user. +#### ACL rule object model + +Since the ACL rule is now not bound to a table type (e.g could be table type which supports mirror action, packet action and redirect action at the same time) +a single AclRule implementation should account for all. The AclRuleBase holds common implementation to validate, create and remove the rule allowing +other orchs to override the behavior. + +

+Figure 1. ACL rule model +

+ ### Syncd N/A @@ -253,4 +269,39 @@ of the unsupported type. ### Flows -### Open questions \ No newline at end of file +#### ACL table type create flow + +

+Figure 2. ACL table type create flow +

+ +#### ACL table type update flow + +ACL table type update would mean recreation of ACL table and ACL rules in that table. +Currently orchagent does not support changing ACL table type nor changing a set of matches, actions +and bind points. + +#### ACL table type remove flow + +ACL table type removal can happen if non of the ACL tables reference it. This validation could be done by YANG +infrastructure. On the orchagent level, orchagent does not remove it from internal cache unless there are no more +tables referencing it. + +

+Figure 3. ACL table type remove flow +

+ +#### ACL rule update flow + +Single AclRule implementation handles updates for mirror, in-band telemetry session state changes. + +

+Figure 4. ACL rule update flow +

+ +### Open questions + +- SAI does not allow to disable mirror action as it is not @allowempty +- ACL counters issue: since a rule may have several actions (counter is one of them) + the counter counts matched packets and not the packets that are mirrored + and this is behavior change. \ No newline at end of file diff --git a/doc/acl/img/acl-rule-flow.svg b/doc/acl/img/acl-rule-flow.svg new file mode 100755 index 00000000000..7a075539890 --- /dev/null +++ b/doc/acl/img/acl-rule-flow.svg @@ -0,0 +1,3 @@ + + +
MirrorOrch
MirrorOrch
AclOrch
AclOrch
SAI
SAI
INT session state change
INT session state change
AclRule::update()
AclRule::update()
if has DTEL action
disable/enable action
sai_acl_api->set_acl_entry_attr
if has DTEL action...
DtelOrch
DtelOrch
AclRule
AclRule
session state change
session state change
AclRule::update()
AclRule::update()
if has mirror action
disable/enable action
sai_acl_api->set_acl_entry_attr
if has mirror action...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-rule-object-model.svg b/doc/acl/img/acl-rule-object-model.svg new file mode 100755 index 00000000000..e29552b620d --- /dev/null +++ b/doc/acl/img/acl-rule-object-model.svg @@ -0,0 +1,3 @@ + + +
pbhorch
pbhorch
pbhorch
pbhorch
aclorch
aclorch
AclBaseRule+ m_matches:+ m_actions+ m_priority+ virtual create(): bool+ virtual remove(): bool+ virtual update(): boolAclRuleAclRulePfcwdAclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-table-type-create-flow.svg b/doc/acl/img/acl-table-type-create-flow.svg new file mode 100755 index 00000000000..62bcd25a86f --- /dev/null +++ b/doc/acl/img/acl-table-type-create-flow.svg @@ -0,0 +1,3 @@ + + +
CONFIG DB
CONFIG DB
ACL_TABLE_TYPE|type
ACL_TABLE_TYPE|...
ACLOrch
ACLOrch
SAI
SAI
save to
internal cache
save to...
ACL_TABLE|table
ACL_TABLE|table
if table type
is not known -
retry on next iteration
if table type...
else: sai_acl_api->create_acl_table
else: sai_acl_a...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-table-type-remove-flow.svg b/doc/acl/img/acl-table-type-remove-flow.svg new file mode 100755 index 00000000000..5d9f27c42c6 --- /dev/null +++ b/doc/acl/img/acl-table-type-remove-flow.svg @@ -0,0 +1,3 @@ + + +
CONFIG DB
CONFIG DB
del ACL_TABLE_TYPE|type
del ACL_TABLE_T...
ACLOrch
ACLOrch
SAI
SAI
else: remove from
internal cache
else: remove from...
if there are ACL tables
referencing "type" - 
retry on next iteration
if there are ACL tables...
Viewer does not support full SVG 1.1
\ No newline at end of file From e3ef0455a4387f5a7e931d14db1b3b1aeb9b362e Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Fri, 20 Aug 2021 15:27:21 +0800 Subject: [PATCH 035/175] Update dynamic buffer calculation HLD change to calculate peer_response at different operating speeds, according to the definition in IEEE 802.3 31B.3.7, instead of taking a fixed number. --- doc/qos/dynamically-headroom-calculation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/qos/dynamically-headroom-calculation.md b/doc/qos/dynamically-headroom-calculation.md index 3bd4c33f330..3c484a6dcd1 100644 --- a/doc/qos/dynamically-headroom-calculation.md +++ b/doc/qos/dynamically-headroom-calculation.md @@ -746,7 +746,7 @@ Let's imagine what will happen after a XOFF frame has been sent for a priority. 1. MAC/PHY delay, which is the bytes held in the SWITCH CHIP's egress pipeline and PHY when XOFF has been generated. 2. Gearbox delay, which is the latency caused by the Gearbox, if there is one. 3. KB on cable, which is the bytes held in the cable, which is equals the time required for packet to travel from one end of the cable to the other multiplies the port's speed. Obviously, the time is equal to cable length divided by speed of the light in the media. -4. Peer response time, which is the bytes that are held in the peer switch's pipeline and will be send out when the XOFF packet is received. +4. Peer response time, which is the bytes that are held in the peer switch's pipeline and will be send out when the XOFF packet is received. IEEE 802.3 31B.3.7 defines how many pause_quanta shall wait when a switch receives a pause frame at different operating speed. For example, at 40 Gb/s it shall wait for 118 pause_quanta while 394 pause_quanta shall be taken at 100 Gb/s. A pause_quanta equal to 512 bit times(see IEEE 802.3 31B.2). Let's consider the flow of XOFF packet generating and handling: @@ -773,6 +773,7 @@ Therefore, headroom is calculated as the following: - `cell occupancy` = (100 - `small packet percentage` + `small packet percentage` * `worst case factor`) / 100 - `kb on cable` = `cable length` / `speed of light in media` * `port speed` - `kb on gearbox` = `port speed` * `gearbox delay` / 8 / 1024 +- `peer response` = (`number of pause_quanta` * 512) / 8 / 1024 - `propagation delay` = `port mtu` + 2 * (`kb on cable` + `kb on gearbox`) + `mac/phy delay` + `peer response` - `Xon` = `pipeline latency` - `Xoff` = `lossless mtu` + `propagation delay` * `cell occupancy` @@ -787,7 +788,6 @@ The values used in the above procedure are fetched from the following table: - `port mtu`: PORT|\|mtu, default value is `9100` - `gearbox delay`: PERIPHERIAL_TABLE|\|gearbox_delay - `mac/phy delay`: ASIC_TABLE|\|mac_phy_delay -- `peer response`: ASIC_TABLE|\|peer_response_time - `cell`: ASIC_TABLE|\|cell_size - `small packet percentage`: LOSSLESS_TRAFFIC_PATTERN|\|small_packet_percentage - `lossless mtu`: LOSSLESS_TRAFFIC_PATTERN|\|mtu From 8858b7a6a281043d376a202b4c877895db0f4934 Mon Sep 17 00:00:00 2001 From: stepanblyschak Date: Wed, 25 Aug 2021 23:31:15 +0300 Subject: [PATCH 036/175] update ACL table type HLD Signed-off-by: stepanblyschak --- doc/acl/ACL-Table-Type-HLD.md | 271 ++++++++++++++++++++-------------- 1 file changed, 160 insertions(+), 111 deletions(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index c78b76b09a5..d3ef5425391 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -31,10 +31,6 @@ |:---:|:-----------:|:------------------:|-----------------------------------| | 0.1 | | Stepan Blyshchak | Initial version | -### Scope - -The scope of this document covers ACL feature enhancements. - ### Definitions/Abbreviations | Definitions/Abbreviation | Description | @@ -58,8 +54,18 @@ This document addresses this limitation by introducing a new concept of user def ### Requirements -- Support user configurable ACL table types. -- Support programming custom ACL tables by using AclOrch public interface without defining a new ACL table type. +- Introduce a concept of ACL table types to the ACL orch + - ACLOrch partially implements but current support is limited for predefined ACL table types only + - ACLOrch's public API to leverage custom table types and use in different orchs (pfcwdorch, pbhorch, macsecorch, etc.) + - CONFIG DB user interface for defining custom ACL table types + +### Scope + +The scope of this document covers ACL feature enhancements, in particular the way user creates customized ACL tables +with user defined set of matches, actions if required and bind point types. The way developers use aclorch public API +is also improved to be more flexible for different use cases, such as PFC watchdog, PBH, MACSec, etc. The ACL rule +classes defined in aclorch is also a subject to be changed due to the new concept of custom ACL table types. +CLI nor other user interface is not covered by this document. ### Architecture Design @@ -67,108 +73,23 @@ No SONiC architecture changes are required. ### High-Level Design -### SAI - -N/A - -### Orchagent - -The AclOrch is subscribed to a table ```ACL_TABLE_TYPE``` in CFG DB. This table holds a definition for a table with the matches, actions and bind points. - -*AclTableType* Data structure: - -```c++ -struct AclTableType -{ - std::string m_name; - std::set m_bpoint_types; - std::set m_matches; - std::set m_acl_actions; -} -``` - -*AclTable*: - -```c++ -class AclTable -{ -public: - // ... - bool validateAddType(const AclTableType& type); -private: - // ... - AclTableType m_type; -} -``` - -Orchagent's AclRule::make_shared makes decision which AclRule child instance to create based on table type. -Since orchagent does not know all the table types there should be single AclRule handling all the matches -and actions and perform validation against the table type configuration. - -#### Mirror table type: combined/separated table - -Orchagent has a special treatment for tables of type MIRROR and MIRRORV6 -based on the ASIC platform it is running on. There is either a "combined" or -"seperated" mode for MIRROR tables. - -``` -+-------------------+------------------------------+ -| | CONFIG DB | ASIC DB | -+-------------------+--------------+---------------+ -| combined | MIRROR | Single mirror | -| +--------------+ table in HW | -| | MIRRORV6 | V4 + V6 keys | -+-------------------+--------------+---------------+ -| seperated | MIRROR | Mirror V4 | -| +--------------+---------------+ -| | MIRRORV6 | Mirror V6 | -+-------------------+--------------+---------------+ -``` - -This does not play well with the new concept of user defined table types. -To solve this we have few options: - -1. Non backward compatible change: let the CONFIG DB table maps 1:1 in ASIC DB table. -User is able to configure either two tables types, one for IPv4, one for IPv6 or single -with IPv4 and IPv6 keys. - -2. Maintaing the current behaviour. Orchagent should have the knowledge to act in either -*combined* or *separeted* mode if the table type is named "MIRROR" or "MIRRORV6". - -3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well -as default table types. - -In this design option 2 is chosen since it maintains current behavior and does not expose different treatment of mirror tables -based on ASIC vendor to the user. - -#### ACL rule object model - -Since the ACL rule is now not bound to a table type (e.g could be table type which supports mirror action, packet action and redirect action at the same time) -a single AclRule implementation should account for all. The AclRuleBase holds common implementation to validate, create and remove the rule allowing -other orchs to override the behavior. - -

-Figure 1. ACL rule model -

- -### Syncd - -N/A - ### CONFIG DB +ACL table create-only SAI attributes include a list of match fields, bind point types and action list in case it is mandatory +to pass on table creation, which is defined by SAI_SWITCH_ATTR_ACL_STAGE_INGRESS, SAI_SWITCH_ATTR_ACL_STAGE_EGRESS in sai_acl_capability_t structure, field is_action_list_mandatory. + ```abnf key: ACL_TABLE_TYPE:name ; key of the ACL table type entry. The name is arbitary name user chooses. ; field = value -matches = match-list ; list of matches for this table -actions = action-list ; list of actions for this table -bind_points = bind-points-list ; list of bind point types for this table +matches = match-list ; list of matches for this table, matches are same as in ACL_RULE table. +actions = action-list ; list of actions for this table, actions are same as in ACL_RULE table. +bind_points = bind-points-list ; list of bind point types for this table. ; values annotation match = 1*64VCHAR -match-list = [1-max-matches]*match +match-list = [1-max-matches]*match action = 1*64VCHAR -action-list = [1-max-actions]*action +action-list = [1-max-actions]*action bind-point = port/lag bind-points-list = [1-max-bind-points]*bind-point ``` @@ -221,15 +142,18 @@ container ACL_TABLE_TYPE { key "ACL_TABLE_TYPE_NAME"; leaf-list MATCHES { - type stypes:match; + type string; } leaf-list ACTIONS { - type stypes:actions; + type string; } leaf-list BIND_POINTS { - type stypes:acl_bind_points; + type enumeration { + enum PORT; + enum LAG; + } } } } @@ -240,13 +164,15 @@ container ACL_TABLE_TYPE { Control plane table are moved to its own table in CONFIG DB to not overlap with HW ACL tables. ```json -"CTRL_PLANE_ACL_TABLE": { - "SSH_ONLY": { - "policy_desc": "SSH only", - "services": [ - "SSH" - ], - "stage": "ingress" +{ + "CTRL_PLANE_ACL_TABLE": { + "SSH_ONLY": { + "policy_desc": "SSH only", + "services": [ + "SSH" + ], + "stage": "ingress" + } } } ``` @@ -259,13 +185,136 @@ The following existing table types defined in init_cfg.json: - L3V6 - MIRROR - MIRRORV6 +- MIRRORV4V6 - MIRROR_DSCP - DTEL_FLOW_WATCHLIST - DTEL_DROP_WATCHLIST - MCLAG -On platforms where certain features are not supported (like in band telemetry) the error is thrown on ACL table creation -of the unsupported type. +The init_cfg.json.j2 creates some table types only for platforms that support a particular feature (like in band telemetry). + +### STATE DB + +ACL stage capabilities are queried by reading SAI_SWITCH_ATTR_ACL_STAGE_INGRESS and SAI_SWITCH_ATTR_ACL_STAGE_EGRESS +which are published in STATE DB at orchagent initialization. + +```abnf +key: ACL_STAGE_CAPABILITY|stage ; key of the ACL switch capability. +; field = value +is_action_list_mandatory = true/false ; Boolean +action_list = action-list ; list of actions for this table, actions are same as in ACL_RULE table. + +; values annotation +stage = ingress/egress +action = 1*64VCHAR +action-list = [1-max-actions]*action +``` + +Example: + +```json +127.0.0.1:6379[6]> hgetall ACL_STAGE_CAPABILITY|INGRESS +1) is_action_list_mandatory +2) false +3) action_list +4) PACKET_ACTION,MIRROR_INGRESS_ACTION,REDIRECT_ACTION +``` + +### Orchagent + +The AclOrch is subscribed to a table ```ACL_TABLE_TYPE``` in CFG DB. This table holds a definition for a table with the matches, actions and bind points. + +*AclTableType* Data structure: + +```c++ +struct AclTableType +{ + std::string m_name; + std::set m_bpoint_types; + std::set m_matches; + std::set m_acl_actions; +} +``` + +*AclTable*: + +```c++ +class AclTable +{ +public: + // ... + bool validateAddType(const AclTableType& type); +private: + // ... + AclTableType m_type; +} +``` + +Orchagent's AclRule::make_shared makes decision which AclRule child instance to create based on table type. +Since orchagent does not know all the table types there should be single AclRule handling all the matches +and actions and perform validation against the table type configuration. + +#### Mirror table type: combined/separated table + +Orchagent has a special treatment for tables of type MIRROR and MIRRORV6 +based on the ASIC platform it is running on. There is either a "combined" or +"seperated" mode for MIRROR tables. + +``` ++-------------------+------------------------------+ +| | CONFIG DB | ASIC DB | ++-------------------+--------------+---------------+ +| combined | MIRROR | Single mirror | +| +--------------+ table in HW | +| | MIRRORV6 | V4 + V6 keys | ++-------------------+--------------+---------------+ +| seperated | MIRROR | Mirror V4 | +| +--------------+---------------+ +| | MIRRORV6 | Mirror V6 | ++-------------------+--------------+---------------+ +``` + +This does not play well with the new concept of user defined table types. +To solve this we have few options: + +1. Non backward compatible change: let the CONFIG DB table maps 1:1 in ASIC DB table. +User is able to configure either two tables types, one for IPv4, one for IPv6 or single +with IPv4 and IPv6 keys. + +2. Maintaing the current behaviour. Orchagent should have the knowledge to act in either +*combined* or *separeted* mode if the table type is named "MIRROR" or "MIRRORV6". + +3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well +as default table types. + +In this design option 1 is chosen due to transparency and simplicity. The mode is exposed by orchagent in STATE DB by orchagent. + +``` + +127.0.0.1:6379[6]> hgetall SWITCH_CAPABILITY|switch +1) mirror_mode +2) combined +``` + +The user or controller needs to read this value and decide whether to create two ACL tables for IPv4 and IPv6 (separated) or single ACL table for both IPv4 and IPv6 (combined). + +#### ACL rule object model + +Since the ACL rule is now not bound to a table type (e.g could be table type which supports mirror action, packet action and redirect action at the same time) +a single AclRule implementation should account for all. The AclRuleBase holds common implementation to validate, create and remove the rule allowing +other orchs to override the behavior. + +

+Figure 1. ACL rule model +

+ +### Syncd + +N/A + +### SAI + +N/A ### Flows From fe1bf2e0f043e6f3febbd56044f135ba552efdc9 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 26 Aug 2021 04:02:23 +0300 Subject: [PATCH 037/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 67 ++++++++++++++++++--------- doc/acl/img/acl-rule-flow.svg | 3 -- doc/acl/img/acl-rule-object-model.svg | 2 +- 3 files changed, 47 insertions(+), 25 deletions(-) delete mode 100755 doc/acl/img/acl-rule-flow.svg diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index d3ef5425391..4d067304132 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -4,25 +4,26 @@ ## Table of Content - Revision -- Scope - Definitions/Abbreviations - Overview - Requirements +- Scope - Architecture Design - High-Level Design -- SAI +- CONFIG DB + - Control plane tables +- Initial CONFIG DB +- STATE DB - Orchagent - Mirror table type: combined/separated table - ACL rule object model + - ACLOrch public API - Syncd -- CONFIG DB - - Control plane tables -- Initial CONFIG DB +- SAI - Flows - ACL table type create flow - ACL table type update flow - ACL table type remove flow - - ACL rule update flow - Open questions ### Revision @@ -62,9 +63,9 @@ This document addresses this limitation by introducing a new concept of user def ### Scope The scope of this document covers ACL feature enhancements, in particular the way user creates customized ACL tables -with user defined set of matches, actions if required and bind point types. The way developers use aclorch public API +with user defined set of matches, actions if required and bind point types. The way developers use ACLOrch public API is also improved to be more flexible for different use cases, such as PFC watchdog, PBH, MACSec, etc. The ACL rule -classes defined in aclorch is also a subject to be changed due to the new concept of custom ACL table types. +classes defined in ACLOrch is also a subject to be changed due to the new concept of custom ACL table types. CLI nor other user interface is not covered by this document. ### Architecture Design @@ -192,6 +193,7 @@ The following existing table types defined in init_cfg.json: - MCLAG The init_cfg.json.j2 creates some table types only for platforms that support a particular feature (like in band telemetry). +The list of matches, bind point types and actions is copied from orchagent code. ### STATE DB @@ -242,11 +244,16 @@ struct AclTableType class AclTable { public: + AclTable(AclOrch *pAclOrch, string id, const AclTableType& type); + // ... bool validateAddType(const AclTableType& type); + // ... + private: // ... AclTableType m_type; + // ... } ``` @@ -300,7 +307,7 @@ The user or controller needs to read this value and decide whether to create two #### ACL rule object model -Since the ACL rule is now not bound to a table type (e.g could be table type which supports mirror action, packet action and redirect action at the same time) +Since the ACL rule is not bound to a table type anymore (e.g could be table type which supports mirror action, packet action and redirect action at the same time) a single AclRule implementation should account for all. The AclRuleBase holds common implementation to validate, create and remove the rule allowing other orchs to override the behavior. @@ -308,6 +315,30 @@ other orchs to override the behavior. Figure 1. ACL rule model

+#### ACLOrch public API + +ACL Table methods declarations: + +```c++ +bool addAclTable(AclTable &aclTable); +bool removeAclTable(string aclTableName); +bool updateAclTable(AclTable &aclTable); +``` + +ACL Rule methods declaration: +```c++ +bool addAclRule(AclRule& aclRule, string aclTableName); +bool removeAclRule(string aclTableName, string aclRuleName); +bool updateAclRule(AclRule& aclRule, string aclTableName); +``` + +While add and remove are known and already implemented today in orchagent, update for ACLRule iterates over the diff between old and new +member fields m_matches, m_actions and sets the corresponding attribute of an ACL Rule. + +Updating ACL table allows only for updating ports bound to it. + +NOTE: ACL rules coming from CONFIG DB are updated by removal and re-creation, an updateAclRule is mostly used for other orch's use cases. + ### Syncd N/A @@ -340,17 +371,11 @@ tables referencing it. Figure 3. ACL table type remove flow

-#### ACL rule update flow - -Single AclRule implementation handles updates for mirror, in-band telemetry session state changes. - -

-Figure 4. ACL rule update flow -

- ### Open questions -- SAI does not allow to disable mirror action as it is not @allowempty -- ACL counters issue: since a rule may have several actions (counter is one of them) - the counter counts matched packets and not the packets that are mirrored - and this is behavior change. \ No newline at end of file +- What kind of level of YANG validation is required? + - Have matches and actions as enumeration (needs to be updated every time new match/action is introduced in SONiC) or could it be just of a type of string? + - Does YANG infrastructure in SONiC supports validation against STATE DB information (e.g. is_action_list_mandatory)? +- Does this feature needs a similar capability table for match fields? What is the SAI API to query it? + - Currently SAI object API allows to query for an ACL table attributes CREATE, SET, GET operations implementation availability (sai_query_attribute_capability, sai_attr_capability_t), + but does not tell wether it is supported or not. Can we assume if it is not implemented it is not supported? diff --git a/doc/acl/img/acl-rule-flow.svg b/doc/acl/img/acl-rule-flow.svg deleted file mode 100755 index 7a075539890..00000000000 --- a/doc/acl/img/acl-rule-flow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
MirrorOrch
MirrorOrch
AclOrch
AclOrch
SAI
SAI
INT session state change
INT session state change
AclRule::update()
AclRule::update()
if has DTEL action
disable/enable action
sai_acl_api->set_acl_entry_attr
if has DTEL action...
DtelOrch
DtelOrch
AclRule
AclRule
session state change
session state change
AclRule::update()
AclRule::update()
if has mirror action
disable/enable action
sai_acl_api->set_acl_entry_attr
if has mirror action...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-rule-object-model.svg b/doc/acl/img/acl-rule-object-model.svg index e29552b620d..e231adceae7 100755 --- a/doc/acl/img/acl-rule-object-model.svg +++ b/doc/acl/img/acl-rule-object-model.svg @@ -1,3 +1,3 @@ -
pbhorch
pbhorch
pbhorch
pbhorch
aclorch
aclorch
AclBaseRule+ m_matches:+ m_actions+ m_priority+ virtual create(): bool+ virtual remove(): bool+ virtual update(): boolAclRuleAclRulePfcwdAclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Viewer does not support full SVG 1.1
\ No newline at end of file +
pfcwdorch
pfcwdorch
pbhorch
pbhorch
aclorch
aclorch
AclBaseRule+ m_matches+ m_actions+ m_priority+ virtual create(): bool+ virtual remove(): bool+ virtual update(): bool+ virtual validate(AclCapabilities): bool
Extends
Extends
AclRule
Extends
Extends
AclRulePfcwd
Extends
Extends
AclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Observervoid onUpdate(Subject, void*)AclOrchAclTable+ m_type: AclTableType:+ m_stage+ m_ports+ virtual create(): bool+ virtual remove(): bool+ virtual update(): bool+ virtual validate(AclCapability): boolOrchvoid doTask(Consumer&)AclTableTypeAclCapabilities
Use
Use
Viewer does not support full SVG 1.1
\ No newline at end of file From 63c28cfbf08262234b514906118099f4df6560fc Mon Sep 17 00:00:00 2001 From: Alexandru Banu Date: Thu, 26 Aug 2021 13:55:12 +0300 Subject: [PATCH 038/175] Updates for new SAI model --- doc/cbf/cbf_hld.md | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/doc/cbf/cbf_hld.md b/doc/cbf/cbf_hld.md index 10b16925440..eed24e0a355 100644 --- a/doc/cbf/cbf_hld.md +++ b/doc/cbf/cbf_hld.md @@ -31,6 +31,7 @@ | Rev | Date | Author | Change Description | |:---:|:-----------:|:-----------------------:|--------------------------------------------| | 0.1 | 03/06/2021 | Alexandru Banu | Initial version | +| 0.2 | 26/08/2021 | Alexandru Banu | Updates for new SAI model | # About this Manual @@ -39,6 +40,7 @@ This document provides general information about Class Based Forwarding which al Along this document the following abbreviations might be used: FC - Forwarding Class +TC - Traffic Class CBF - Class Based Forwarding NHG - Next Hop Group @@ -53,7 +55,7 @@ DSCP/EXP value of W for --> in the DSCP/EXP to FC --> assigned to the --> lookup ``` This feature enables opeartors, among other things, to send the important (foreground) traffic through the shortest path, while sending the background traffic through longer paths to still give it some bandwidth instead of using QoS queues which may block background traffic from getting bandwitdh. -These new class based next hop groups are allowed thanks to the changes in https://github.com/opencomputeproject/SAI/pull/1193, which allow a next hop group object to also have other next hop group objects as members of the group along with the next hop objects. The way such a next hop group works is that a packet which has a Forwarding Class value of X will be matched against an appropriate member of this group, selected based on the Forwarding Class value thanks to the "class_map" property of the group. As an example, given the CBF group with members Nhg1, Nhg2 and Nhg3 and a class map of FC 0 -> Nhg1, FC 1 -> Nhg2 and FC 3 -> Nhg3, a packet which has an FC value of 0 will be forwarded using Nhg1. Note that multiple FC values can point to the same member, but a single FC value can't be mapped to more than one member. +These new class based next hop groups are allowed thanks to the changes in https://github.com/opencomputeproject/SAI/pull/1193, which allow a next hop group object to also have other next hop group objects as members of the group along with the next hop objects. The way such a next hop group works is that a packet which has a Forwarding Class value of X will be matched against an appropriate member of this group, selected based on the Forwarding Class value thanks to the "selection_map" property of the group. As an example, given the CBF group with members Nhg1, Nhg2 and Nhg3 and a selection map of FC 0 -> Nhg1, FC 1 -> Nhg2 and FC 3 -> Nhg3, a packet which has an FC value of 0 will be forwarded using Nhg1. Note that multiple FC values can point to the same member, but a single FC value can't be mapped to more than one member. In order to support this mapping, 2 new mapping tables will be added to the CONFIG_DB for the DSCP/EXP to FC mapping and a new CLASS_BASED_NEXT_HOP_GROUP table will be added to APPL_DB to support the new FC-aware next hop groups. @@ -86,21 +88,38 @@ This design directly changes CONFIG_DB, APPL_DB, orchagent and sairedis. ## 3.2 DB Changes ### 3.2.1 APPL DB Based on the next hop group split (https://github.com/Azure/SONiC/pull/712) on which this HLD is based on, a new CLASS_BASED_NEXT_HOP_GROUP table will be added to the APPL_DB with the following format: + +A new table is added to store the NHG maps. +``` +### FC_TO_NHG_INDEX_MAP_TABLE + ; FC to Next hop group index map + key = "FC_TO_NHG_INDEX_MAP_TABLE:"name + fc_num = 1*DIGIT ;value + nh_index = 1*DIGIT; index of NH inside NH group +``` + + Example: + 127.0.0.1:6379> hgetall "FC_TO_NHG_INDEX_MAP_TABLE:AZURE" + 1) "0" ;fc_num + 2) "0" ;nhg_index + 3) "1" + 4) "0" + ``` ### CLASS_BASED_NEXT_HOP_GROUP_TABLE ;Stores a list of FC-aware next hop groups. ;Status: Mandatory key = CLASS_BASED_NEXT_HOP_GROUP_TABLE:string ; arbitrary string identifying the class based next hop group, as determined by the programming application. members = NEXT_HOP_GROUP_TABLE.key, ; one or more indexes within NEXT_HOP_GROUP_TABLE, separated by “,” - class_map = number:number, ; one or more mapping from Forwarding Class to index in "members" field to use as NHG, separated by "," + selection_map = FC_TO_NHG_INDEX_MAP_TABLE.key ; the NHG map to use for this CBF NHG ``` Example: 127.0.0.1:6379[1]> hgetall "CLASS_BASED_NEXT_HOP_GROUP:CbfNhg1" 1) "members" 2) "Nhg1,Nhg2,Nhg3,Nhg4" - 3) "class_map" - 4) "0:0,1:0,2:1,3:1,4:2,5:2,6:3,7:3" + 3) "selection_map" + 4) "NhgMap1" The ROUTE_TABLE is updated to allow the "nexthop_group" to allow both keys from NEXT_HOP_GROUP_TABLE and from the new CLASS_BASED_NEXT_HOP_GROUP_TABLE. ``` @@ -178,13 +197,15 @@ Example: A new orchestration agent will be written to handle the requests to both NEXT_HOP_GROUP_TABLE and CLASS_BASED_NEXT_HOP_GROUP_TABLE while also providing a common API for the route orchestration agent to use when working with next hop groups stored in these tables. -For a new entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will validate the data and create a new next hop group object in ASIC_DB of type SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED to which it will add the provided members as long as they have alreaedy been created in ASIC_DB. If an error occurs during this process and it's coming from the validation process, the task will be efectively removed from the process queue as an update to the entry would be needed in order to fix it; otherwise the task will be kept in the process queue for the event of the missing member(s) being created which would allow the class based next hop group to be created. +At the same time, another new orchestration agent will be added to handle the new FC_TO_NHG_INDEX_MAP_TABLE entries. This agent will validate the data and create a SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP entry in ASIC_DB. If the data validation fails, the task will be removed from the process queue as an update to the entry is mandatory in order to fix these errors. This agent is also responsible of handling the switch's capabilities regarding the maximum number of FCs and NHG maps supported. If at a given point there is no more room in the dataplane for new NHG maps, these tasks will remain in the process queue waiting for space to be freed. The NHG maps can't be removed as long as they are being referenced by other objects (in our case, by CBF NHGs). + +For a new entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will validate the data and create a new next hop group object in ASIC_DB of type SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED to which it will add the provided members as long as they have alreaedy been created in ASIC_DB. If an error occurs during the creation of the object, the task will be kept in the process queue for the event of the missing member(s) and/or selection map being created, which would allow the class based next hop group to be created. If the dataplane doesn't have any more room for a new next hop group object, the task will remain in the process queue for the event of space being freed. There is a special scenario for creating the class based next hop groups, and that is when it references temporary next hop groups (as described in https://github.com/Azure/SONiC/pull/712), as these may be updated at some point which in turn will change their SAI ID. For this scenario, the class based next hop groups will keep a list of their temporary members and periodically check if it's SAI ID has been updated. If so, the SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID attribute of the class based next hop group member will be updated to the match the new value and if the next hop group was updated to a proper (;-temporary) next hop group object, it will be erased from the specified list. When all the temporary next hop groups have been updated to proper next hop groups, the class based one will stop checking periodically for the updates. -For an updated entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will remove the group's previous members and add the updated ones. We do this due to the limitation of the SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX attribute which is CREATE_ONLY and so can't be updated. Instead of accounting for all the possibilities for the index of a member to be updated (by moving it to a different position in the list, removing a member that comes before it or adding a new one before it) which would be exhaustive to handle, we prefer this simpler and more robust solution. The class map will also be updated in ASIC_DB if necessary. +For an updated entry in CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will remove the group's previous members and add the updated ones. We do this due to the limitation of the SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX attribute which is CREATE_ONLY and so can't be updated. Instead of accounting for all the possibilities for the index of a member to be updated (by moving it to a different position in the list, removing a member that comes before it or adding a new one before it) which would be exhaustive to handle, we prefer this simpler and more robust solution. The selection map will also be updated in ASIC_DB if necessary. For a removed entry from CLASS_BASED_NEXT_HOP_GROUP_TABLE, the orchestration agent will remove the group from ASIC_DB only if it is not referenced anymore by other objects (such as routes). @@ -193,7 +214,9 @@ Thanks to the common API provided by the new next hop group orhcestration agent, The QoS orchestration agent is extended in order to process the DSCP_TO_FC_MAP_TABLE and EXP_TO_FC_MAP_TABLE entries. It's similar in functionality with the QoS task handling with the exception of the SAI_QOS_MAP_TYPE used for the entries created into ASIC_DB, being one of the SAI_QOS_MAP_TYPE_DSCP_TO_FORWARDING_CLASS or SAI_QOS_MAP_TYPE_MPLS_EXP_TO_FORWARDING_CLASS. ## 3.4 sairedis -Sairedis support has been added for objects of type "sai_map_t" for validation, serialization and deserialization in order for the "class_map" property of the class based next hop groups to work properly and also "fc" has been added to "sai_qos_map_params_t" object to support the DSCP/EXP to FC mappings. +Sairedis support has been added for objects of type "sai_map_t" for validation, serialization and deserialization in order for the NHG map objects to work properly and also "fc" has been added to "sai_qos_map_params_t" object to support the DSCP/EXP to FC mappings. + +libsairedis and libsaivs are enhanced to support the API for NHG maps and the VS interface is enhanced to default the NHG maps object availability to 512. ## 3.5 SAI The SAI changes are handled in https://github.com/opencomputeproject/SAI/pull/1193. @@ -208,8 +231,5 @@ Unchanged. Unchanged. # 5 Unit Test -Unit tests have been added to orchagent to test the mainline scenarios (create/delete) for the DSCP/EXP_TO_FC_MAP entries (update doesn't seem to be supported by CONFIG_DB tables) and mainline scenarios (create/update/delete) for the CLASS_BASED_NEXT_HOP_GROUP entries. Along with these mainline scenarios, different corner case scenarios have been tested as well, among which next hop group objects exhaustion has been tested to confirm the expected behaviour of class based next hop groups with limited resources available. - -A unit test has also been added to sairedis to test the serialization and deserialization of the "sai_map_t" objects. - -There are plans to complete the code coverage for the new orchagent code in the following month, as well as adding sonic-mgmt unit tests in the near future. +The entire code is fully tested, having 100% code coverage. +Adding sonic-mgmt unit tests in the near future. From 5560588416b08251170c636f3ff335f3364b7f77 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 26 Aug 2021 16:00:10 +0300 Subject: [PATCH 039/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index 4d067304132..cd9c3cb9ed8 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -16,6 +16,7 @@ - STATE DB - Orchagent - Mirror table type: combined/separated table + - DB migration - ACL rule object model - ACLOrch public API - Syncd @@ -305,6 +306,11 @@ In this design option 1 is chosen due to transparency and simplicity. The mode i The user or controller needs to read this value and decide whether to create two ACL tables for IPv4 and IPv6 (separated) or single ACL table for both IPv4 and IPv6 (combined). +#### DB migration + +The DB migrator script updated with a logic to move ACL rules for particular platforms supporting combined mirror mode to a table MIRRORV4V6 and for +platforms where separated mode is used ACL rules are moved into corresponding MIRROR or MIRRORV6. + #### ACL rule object model Since the ACL rule is not bound to a table type anymore (e.g could be table type which supports mirror action, packet action and redirect action at the same time) From c0f071aecb20bc8454269a361498c1000f951828 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Mon, 30 Aug 2021 16:25:49 +0300 Subject: [PATCH 040/175] Update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index cd9c3cb9ed8..38a17d0ce37 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -323,6 +323,33 @@ other orchs to override the behavior. #### ACLOrch public API +ACL rule base class declaration: + +```c++ +class AclRule +{ +protected: + virtual bool create(); + virtual bool remove(); + virtual bool update(const AclRule& updatedRule); + virtual bool validate(const AclCapabilities& capabilities); +protected: + uint32_t m_priority; + AclEntryAttrMap m_matches; + AclEntryAttrMap m_actions; +private: + std::string m_name; + sai_object_id_t m_oid {SAI_NULL_OBJECT_ID}; + const AclTable& m_table; + + friend class AclOrch; +}; +``` + +The create/update/remove methods are protected allowing the child classes to be overwritten for custom behavior (like, AclRuleMirror), +but the AclOrch's public API is the only way to create the actual rule, so that the AclOrch will manage AclRule CRM, FC, etc. + + ACL Table methods declarations: ```c++ @@ -335,7 +362,7 @@ ACL Rule methods declaration: ```c++ bool addAclRule(AclRule& aclRule, string aclTableName); bool removeAclRule(string aclTableName, string aclRuleName); -bool updateAclRule(AclRule& aclRule, string aclTableName); +bool updateAclRule(AclRule& updatedAclRule, string aclTableName); ``` While add and remove are known and already implemented today in orchagent, update for ACLRule iterates over the diff between old and new From ca0031f4b5c71addfc2c85e05888d6c53bdd9481 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Mon, 30 Aug 2021 18:43:57 +0300 Subject: [PATCH 041/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index 38a17d0ce37..0be53f89078 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -326,7 +326,7 @@ other orchs to override the behavior. ACL rule base class declaration: ```c++ -class AclRule +class AclBaseRule { protected: virtual bool create(); From e113735cd9d6381cb88a5291822e0eca983a5084 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Tue, 31 Aug 2021 10:41:58 +0300 Subject: [PATCH 042/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index 0be53f89078..b5dd63fcd0c 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -328,7 +328,7 @@ ACL rule base class declaration: ```c++ class AclBaseRule { -protected: +public: virtual bool create(); virtual bool remove(); virtual bool update(const AclRule& updatedRule); @@ -341,8 +341,6 @@ private: std::string m_name; sai_object_id_t m_oid {SAI_NULL_OBJECT_ID}; const AclTable& m_table; - - friend class AclOrch; }; ``` From 085ff2367c65c5afc63ccb820bf1d138e88179d8 Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Tue, 31 Aug 2021 16:29:50 +0800 Subject: [PATCH 043/175] rephrase the description --- doc/qos/dynamically-headroom-calculation.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/qos/dynamically-headroom-calculation.md b/doc/qos/dynamically-headroom-calculation.md index 3c484a6dcd1..abf8ade364c 100644 --- a/doc/qos/dynamically-headroom-calculation.md +++ b/doc/qos/dynamically-headroom-calculation.md @@ -746,7 +746,19 @@ Let's imagine what will happen after a XOFF frame has been sent for a priority. 1. MAC/PHY delay, which is the bytes held in the SWITCH CHIP's egress pipeline and PHY when XOFF has been generated. 2. Gearbox delay, which is the latency caused by the Gearbox, if there is one. 3. KB on cable, which is the bytes held in the cable, which is equals the time required for packet to travel from one end of the cable to the other multiplies the port's speed. Obviously, the time is equal to cable length divided by speed of the light in the media. -4. Peer response time, which is the bytes that are held in the peer switch's pipeline and will be send out when the XOFF packet is received. IEEE 802.3 31B.3.7 defines how many pause_quanta shall wait when a switch receives a pause frame at different operating speed. For example, at 40 Gb/s it shall wait for 118 pause_quanta while 394 pause_quanta shall be taken at 100 Gb/s. A pause_quanta equal to 512 bit times(see IEEE 802.3 31B.2). +4. Peer response time, when a switch receives a pause frame, it will not stop the packet transmission immediately, because it need to drain the frames which already submitted to MAC layer. So extra buffer shall be considered to handle the peer delay response. IEEE 802.3 31B.3.7 defines how many pause_quanta shall wait upon an XOFF. A pause_quanta equal to the time required to transmit 512 bits of a frame at the data rate of the MAC. At different operating speed the number of pause_quanta shall be taken are also different. Following table shows the number of pause_quanta shall be taken for each speed. + + | Operating speed | Number of pause_quanta | + |:--------:|:-----------------------------:| + | 100 Mb/s | 1 | + | 1 Gb/s | 2 | + | 10 Gb/s | 67 | + | 25 Gb/s | 80 | + | 40 Gb/s | 118 | + | 50 Gb/s | 147 | + | 100 Gb/s | 394 | + | 200 Gb/s | 453 | + | 400 Gb/s | 905 | Let's consider the flow of XOFF packet generating and handling: From 959f26668b7d9c8956118b1f47f10b33417f023b Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Tue, 31 Aug 2021 12:02:58 +0300 Subject: [PATCH 044/175] update ACL flex counters HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Flex-Counters.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 6c011d599da..910a70ae256 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -14,6 +14,7 @@ - Orchagent - Syncd - COUNTERS DB +- CLI - Flows - Create ACL rule - Delete ACL rule @@ -179,6 +180,14 @@ DEFAULT_RULE DATAACL 1 2 1 RULE_6 EVERFLOW 9994 601 600 ``` +*sonic-clear* utility is extended with the ACL group to clear ACL counters. Counters are dumped into a file under /home/admin and the next time *aclshow* is invoked +it shows the difference between dumped counters and actual from database. This approach makes each user have it's own view on the counters and aligned to other +counter groups. + +``` +admin@sonic:~$ sonic-clear acl +``` + ### Flows ### Create ACL rule From 08da3709f6a49db00b3ec1f9a8be81e9555afe98 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Tue, 31 Aug 2021 18:34:53 +0300 Subject: [PATCH 045/175] update ACL flex counters HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Flex-Counters.md | 28 +++++++++++++++---- .../img/acl-counters-acl-rule-add-flow.svg | 2 +- .../img/acl-counters-acl-rule-remove-flow.svg | 2 +- doc/acl/img/acl-fc-th-add.svg | 3 ++ doc/acl/img/acl-fc-th-removal.svg | 3 ++ 5 files changed, 30 insertions(+), 8 deletions(-) create mode 100755 doc/acl/img/acl-fc-th-add.svg create mode 100755 doc/acl/img/acl-fc-th-removal.svg diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 910a70ae256..5b1529a628a 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -18,6 +18,8 @@ - Flows - Create ACL rule - Delete ACL rule +- ACL counter registration in FC +- ACL counter de-registration in FC - Mirror flow enhancement - SAI API - Configuration and management @@ -196,7 +198,7 @@ admin@sonic:~$ sonic-clear acl Figure 2. Create ACL rule flow

-In case an *error* happened, we roll back, deleting objects with best effort and removing the ACL rule taks from m_toSync map. An error is printed in the syslog. +In case an *error* happened, we roll back, deleting objects with best effort and removing the ACL rule tasks from m_toSync map. An error is printed in the syslog. ### Delete ACL rule @@ -204,7 +206,19 @@ In case an *error* happened, we roll back, deleting objects with best effort and Figure 3. Delete ACL rule flow

-In case an *error* happened, we proceed deleting objects with best effort and removing the ACL rule taks from m_toSync map. An error is printed in the syslog. +In case an *error* happened, we roll back, deleting objects with best effort. An error is printed in the syslog. + +### ACL counter registration in FC + +

+Figure 3. ACL counter registration in FC +

+ +### ACL counter de-registration in FC + +

+Figure 4. ACL counter de-registration in FC +

### Mirror flow enhancement @@ -240,9 +254,9 @@ Config DB schema with ACL key in FLEX COUNTER table: "FLEX_COUNTER_TABLE": { "ACL": { "FLEX_COUNTER_STATUS": "enable", - "POLL_INTERVAL": "10000" + "POLL_INTERVAL": "10000" } - } + } } ``` @@ -271,11 +285,13 @@ N/A 1. Enhance test_flex_counters.py with ACL group 2. Enhance test_acl.py with check for ACL rule mapping and ACL counter OID inserted in FLEX COUNTER DB. -3. Modify aclshow_test.py in sonic-utilities to work with new data source. +3. Enhance test_mirror.py with the check for ACL rule mapping and ACL counter OID inserted in FLEX COUNTER DB. Cover the flow of deactivation/activating mirror session. +4. Modify aclshow_test.py in sonic-utilities to work with new data source. #### System Test cases -ACL/Everflow tests suite in sonic-mgmt covers the ACL counter functionality. +- ACL/Everflow tests suite in sonic-mgmt covers the ACL counter functionality. +- Warm/Fast reboot tests to check the changes do not break these features. ### Open/Action items diff --git a/doc/acl/img/acl-counters-acl-rule-add-flow.svg b/doc/acl/img/acl-counters-acl-rule-add-flow.svg index 24c3a94b833..77b8b637282 100755 --- a/doc/acl/img/acl-counters-acl-rule-add-flow.svg +++ b/doc/acl/img/acl-counters-acl-rule-add-flow.svg @@ -1,3 +1,3 @@ -
loop
loop
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
hset COUNTERS:<counter VID> attr value
hset COUNTERS:<counter VID> attr value
return
return
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
hset COUNTERS_ACL_COUNTER_RULE_MAP 
hset COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
hset FLEX_COUNTER:<counter VID> attr IDs 
hset FLEX_COUNTER:<counter VID> attr IDs 
return
return
SAI
SAI
dispatch
dispatch
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
sai_acl_api->get_acl_counter_attribute
sai_acl_api->get_acl_counter_attribute
return
return
Set new rule to map
Set new rule to map
Viewer does not support full SVG 1.1
\ No newline at end of file +
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
FLEX COUNTER DB
FLEX COUNTER DB
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
hset COUNTERS_ACL_COUNTER_RULE_MAP 
hset COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
hset FLEX_COUNTER:<counter VID> attr IDs 
hset FLEX_COUNTER:<counter VID> attr IDs 
return
return
SAI
SAI
sai_acl_api->create_acl_counter
sai_acl_api->create_acl_counter
return
return
sai_acl_api->create_acl_entry
sai_acl_api->create_acl_entry
return
return
Set new rule to map
Set new rule to map
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-counters-acl-rule-remove-flow.svg b/doc/acl/img/acl-counters-acl-rule-remove-flow.svg index d71ae837832..760888ed2cc 100755 --- a/doc/acl/img/acl-counters-acl-rule-remove-flow.svg +++ b/doc/acl/img/acl-counters-acl-rule-remove-flow.svg @@ -1,3 +1,3 @@ -
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
SAI
SAI
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
Remove VID from rule mapping
Remove VID from rule mappi...
remove counter OID
remove counter OID
del FLEX_COUNTER:<counter VID>
del FLEX_COUNTER:<counter VID>
return
return
return
return
del COUNTERS_ACL_COUNTER_RULE_MAP 
del COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
del COUNTERS:<counter VID>
del COUNTERS:<counter VID>
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file +
aclorch
aclorch
DATA|RULE0
DATA|RULE0
syncd
syncd
COUNTERS DB
COUNTERS DB
FLEX COUNTER DB
FLEX COUNTER DB
SAI
SAI
Remove VID from rule mapping
Remove VID from rule mappi...
del FLEX_COUNTER:<counter VID>
del FLEX_COUNTER:<counter VID>
return
return
del COUNTERS_ACL_COUNTER_RULE_MAP 
del COUNTERS_ACL_COUNTER_RULE_MAP 
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
sai_acl_api->remove_acl_entry
sai_acl_api->remove_acl_entry
return
return
sai_acl_api->remove_acl_counter
sai_acl_api->remove_acl_counter
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-fc-th-add.svg b/doc/acl/img/acl-fc-th-add.svg new file mode 100755 index 00000000000..94c564a68a1 --- /dev/null +++ b/doc/acl/img/acl-fc-th-add.svg @@ -0,0 +1,3 @@ + + +
loop
loop
aclorch
aclorch
DATA|RULE0
DATA|RULE0
COUNTERS DB
COUNTERS DB
hset COUNTERS:<counter VID> attr value
hset COUNTERS:<counter VID> attr value
return
return
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
hset FLEX_COUNTER:<counter VID> attr IDs 
hset FLEX_COUNTER:<counter VID> attr IDs 
return
return
SAI
SAI
dispatch
dispatch
sai_acl_api->get_acl_counter_attribute
sai_acl_api->get_acl_counter_attribute
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/acl/img/acl-fc-th-removal.svg b/doc/acl/img/acl-fc-th-removal.svg new file mode 100755 index 00000000000..d1d1489d236 --- /dev/null +++ b/doc/acl/img/acl-fc-th-removal.svg @@ -0,0 +1,3 @@ + + +
aclorch
aclorch
COUNTERS DB
COUNTERS DB
FLEX COUNTER DB
FLEX COUNTER DB
FC thread
FC thread
remove counter OID
remove counter OID
del FLEX_COUNTER:<counter VID>
del FLEX_COUNTER:<counter VID>
return
return
return
return
del COUNTERS:<counter VID>
del COUNTERS:<counter VID>
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file From 04abc04eee6b3f703bbda58c0df0fb01d0e157a0 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Mon, 6 Sep 2021 12:49:50 +0300 Subject: [PATCH 046/175] update ACL flex counter HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Flex-Counters.md | 13 ++++++++----- doc/acl/img/acl-mirror-rule-flow.svg | 3 +++ 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100755 doc/acl/img/acl-mirror-rule-flow.svg diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 5b1529a628a..7ef1d5d8fc5 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -224,6 +224,10 @@ In case an *error* happened, we roll back, deleting objects with best effort. An ACL counter should not be removed when mirror rule is removed on mirror session deactivation and upon mirror recreation attached back to the rule object. +

+Figure 5. ACL mirror flow enhancement +

+ ### SAI API No new SAI API is used. @@ -274,7 +278,8 @@ YANG model with ACL group: NOTE: YANG is currently not having POLL_INTERVAL field defined. ### Warmboot and Fastboot Design Impact -N/A + +Counter polling is delayed at system startup. ### Restrictions/Limitations N/A @@ -296,8 +301,6 @@ N/A ### Open/Action items - In case mirror session goes down, ACL rule is deleted but counters is not to save the counters values. This counter could be deleted from FLEX COUNTER DB to avoid polling it but it will trigger removal of the VID in the COUNTERS DB which we would like to keep. - - In the current desing it will work just like for PORT, QUEUE, PG counters for port in down state - meaning polling is happenning although there is no real point for it. + - In the current desing it will work just like for PORT, QUEUE, PG counters for port in down state - meaning polling is happening although there is no real point for it. - It is more like an optimization for a bad scenario rather then a real optimization. A rule is created to be active and counter to be polled in the first place and there must be enough resources and free CPU time to do that. - - In case the ACL rule has more action, like mirror ingress on session s0 and mirror egress on session s1 (currently not supported but possible scenario) and if one sesssion goes down, say s0, the counter can't be removed anyway as there is still egress mirroring happening on s1. - - Considering previous items it does not make sense to remove the whole rule and a counter but just disable actions if the state in the network(session IP is reachable) requires. - - It is not clear how to remove mirror action from the rule in SAI as the SAI_ACL_ACTION_TYPE_MIRROR_INGRESS/SAI_ACL_ACTION_TYPE_MIRROR_EGRESS are not @allowempty. + - Current FC infrastructure does not allow to enable/disable polling on per-counter OID basis. diff --git a/doc/acl/img/acl-mirror-rule-flow.svg b/doc/acl/img/acl-mirror-rule-flow.svg new file mode 100755 index 00000000000..0527852718d --- /dev/null +++ b/doc/acl/img/acl-mirror-rule-flow.svg @@ -0,0 +1,3 @@ + + +
MirrorOrch
MirrorOrch
AclOrch
AclOrch
SAI
SAI
FLEX COUNTER DB
FLEX COUNTER DB
AclRule
AclRule
session state change
session state change
AclRule::update()
AclRule::update()
sai_acl_api->remove_acl_entry()/
sai_acl_api->create_acl_entry()
sai_acl_ap...
Based on session state
remove or re-create ACL entry
Based on session state...
ACL counter is not removed from the HW.
FC thread still polls the counter.
ACL counter is not removed from the HW....
Viewer does not support full SVG 1.1
\ No newline at end of file From 7add0f7e2a01593804df4b657b11085a0fa9325b Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Mon, 6 Sep 2021 13:11:37 +0300 Subject: [PATCH 047/175] update ACL flex counter HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Flex-Counters.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/acl/ACL-Flex-Counters.md b/doc/acl/ACL-Flex-Counters.md index 7ef1d5d8fc5..76d16072571 100644 --- a/doc/acl/ACL-Flex-Counters.md +++ b/doc/acl/ACL-Flex-Counters.md @@ -300,7 +300,8 @@ N/A ### Open/Action items +- Can a default FC ACL counter state be disabled in init_cfg.json? Only enabled when generating configuration from minigraph.xml or when performing S2S upgrade in DB migrator? - In case mirror session goes down, ACL rule is deleted but counters is not to save the counters values. This counter could be deleted from FLEX COUNTER DB to avoid polling it but it will trigger removal of the VID in the COUNTERS DB which we would like to keep. - In the current desing it will work just like for PORT, QUEUE, PG counters for port in down state - meaning polling is happening although there is no real point for it. - It is more like an optimization for a bad scenario rather then a real optimization. A rule is created to be active and counter to be polled in the first place and there must be enough resources and free CPU time to do that. - - Current FC infrastructure does not allow to enable/disable polling on per-counter OID basis. + - Current FC infrastructure does not allow to enable/disable polling on per-counter OID basis but keeping the counter value in COUNTERS DB. From 0c136e7da50a98e166594fa5bb0c52d708f03e6e Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Tue, 31 Aug 2021 18:10:54 +0300 Subject: [PATCH 048/175] update ACL table type HLD Signed-off-by: Stepan Blyschak --- doc/acl/ACL-Table-Type-HLD.md | 28 ++++++++++++++++++++++----- doc/acl/img/acl-rule-object-model.svg | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index b5dd63fcd0c..83f31c181d1 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -25,6 +25,9 @@ - ACL table type create flow - ACL table type update flow - ACL table type remove flow +- Testing +- VS tests +- System tests - Open questions ### Revision @@ -196,6 +199,8 @@ The following existing table types defined in init_cfg.json: The init_cfg.json.j2 creates some table types only for platforms that support a particular feature (like in band telemetry). The list of matches, bind point types and actions is copied from orchagent code. +DTEL table is created in the init_cfg.json on a platform supporting it. + ### STATE DB ACL stage capabilities are queried by reading SAI_SWITCH_ATTR_ACL_STAGE_INGRESS and SAI_SWITCH_ATTR_ACL_STAGE_EGRESS @@ -223,6 +228,8 @@ Example: 4) PACKET_ACTION,MIRROR_INGRESS_ACTION,REDIRECT_ACTION ``` +On table creation, a check is performed by the orchagent to check against the action list and action_list capability as well as is_action_list_mandatory flag. + ### Orchagent The AclOrch is subscribed to a table ```ACL_TABLE_TYPE``` in CFG DB. This table holds a definition for a table with the matches, actions and bind points. @@ -326,7 +333,7 @@ other orchs to override the behavior. ACL rule base class declaration: ```c++ -class AclBaseRule +class AclRule { public: virtual bool create(); @@ -351,16 +358,16 @@ but the AclOrch's public API is the only way to create the actual rule, so that ACL Table methods declarations: ```c++ -bool addAclTable(AclTable &aclTable); +bool addAclTable(shared_ptr aclTable); bool removeAclTable(string aclTableName); -bool updateAclTable(AclTable &aclTable); +bool updateAclTable(shared_ptr aclTable); ``` ACL Rule methods declaration: ```c++ -bool addAclRule(AclRule& aclRule, string aclTableName); +bool addAclRule(shared_ptr aclRule, string aclTableName); bool removeAclRule(string aclTableName, string aclRuleName); -bool updateAclRule(AclRule& updatedAclRule, string aclTableName); +bool updateAclRule(shared_ptr updatedAclRule); ``` While add and remove are known and already implemented today in orchagent, update for ACLRule iterates over the diff between old and new @@ -402,6 +409,17 @@ tables referencing it. Figure 3. ACL table type remove flow

+### Testing + +### VS tests + +- Enhance test_acl.py with a test configuration including table types needed for the rest of the tests (L3, L3V6, etc.). + +### System tests + +- Existing ACL/Everflow tests cover default table types coming from init_cfg.json, which means it is covering the flow of creating table types. +- Warm/Fast reboot tests to verify the functionality with new changes. + ### Open questions - What kind of level of YANG validation is required? diff --git a/doc/acl/img/acl-rule-object-model.svg b/doc/acl/img/acl-rule-object-model.svg index e231adceae7..305cb7c708d 100755 --- a/doc/acl/img/acl-rule-object-model.svg +++ b/doc/acl/img/acl-rule-object-model.svg @@ -1,3 +1,3 @@ -
pfcwdorch
pfcwdorch
pbhorch
pbhorch
aclorch
aclorch
AclBaseRule+ m_matches+ m_actions+ m_priority+ virtual create(): bool+ virtual remove(): bool+ virtual update(): bool+ virtual validate(AclCapabilities): bool
Extends
Extends
AclRule
Extends
Extends
AclRulePfcwd
Extends
Extends
AclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Observervoid onUpdate(Subject, void*)AclOrchAclTable+ m_type: AclTableType:+ m_stage+ m_ports+ virtual create(): bool+ virtual remove(): bool+ virtual update(): bool+ virtual validate(AclCapability): boolOrchvoid doTask(Consumer&)AclTableTypeAclCapabilities
Use
Use
Viewer does not support full SVG 1.1
\ No newline at end of file +
pfcwdorch
pfcwdorch
pbhorch
pbhorch
aclorch
aclorch
AclRule+ m_matches+ m_actions+ m_priority
Extends
Extends
AclRulePfcwd
Extends
Extends
AclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Observervoid onUpdate(Subject, void*)AclOrchAclTable+ m_type: AclTableType:+ m_stage+ m_portsOrchvoid doTask(Consumer&)AclTableTypeAclCapabilities
Use
Use
Manages ACLs objects,
observes on mirror, port changes and updated ACL objects.
Manages ACLs objects,...
Viewer does not support full SVG 1.1
\ No newline at end of file From 4e94ae41579217e74e39963b28e92881c383de5e Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Thu, 9 Sep 2021 09:51:11 +0300 Subject: [PATCH 049/175] update HLD Signed-off-by: Stepan Blyschak --- doc/acl/img/acl-rule-object-model.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/acl/img/acl-rule-object-model.svg b/doc/acl/img/acl-rule-object-model.svg index 305cb7c708d..85daccefc0b 100755 --- a/doc/acl/img/acl-rule-object-model.svg +++ b/doc/acl/img/acl-rule-object-model.svg @@ -1,3 +1,3 @@ -
pfcwdorch
pfcwdorch
pbhorch
pbhorch
aclorch
aclorch
AclRule+ m_matches+ m_actions+ m_priority
Extends
Extends
AclRulePfcwd
Extends
Extends
AclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Handles all cases
supported in ACL_RULE table
Handles all cases...
Observervoid onUpdate(Subject, void*)AclOrchAclTable+ m_type: AclTableType:+ m_stage+ m_portsOrchvoid doTask(Consumer&)AclTableTypeAclCapabilities
Use
Use
Manages ACLs objects,
observes on mirror, port changes and updated ACL objects.
Manages ACLs objects,...
Viewer does not support full SVG 1.1
\ No newline at end of file +
pfcwdorch
pfcwdorch
pbhorch
pbhorch
aclorch
aclorch
AclRule+ m_matches+ m_actions+ m_priority
Extends
Extends
AclRulePfcwd
Extends
Extends
AclRulePbh
Base classes need to fill
m_matches, m_actions, m_priority.
Base classes need to fill...
Observervoid onUpdate(Subject, void*)AclOrchAclTable+ m_type: AclTableType:+ m_stage+ m_portsOrchvoid doTask(Consumer&)AclTableTypeAclCapabilities
Use
Use
Manages ACLs objects,
observes on mirror, port changes and updated ACL objects.
Manages ACLs objects,...
AclPacketRuleAclMirrorRule
Extends
Extends
Extends
Extends
Viewer does not support full SVG 1.1
\ No newline at end of file From 2bb22a2e98937574d850790fcdf981bba2c34483 Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Mon, 13 Sep 2021 14:38:56 +0800 Subject: [PATCH 050/175] Update doc/qos/dynamically-headroom-calculation.md Co-authored-by: Stephen Sun <5379172+stephenxs@users.noreply.github.com> --- doc/qos/dynamically-headroom-calculation.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/qos/dynamically-headroom-calculation.md b/doc/qos/dynamically-headroom-calculation.md index abf8ade364c..5c188529624 100644 --- a/doc/qos/dynamically-headroom-calculation.md +++ b/doc/qos/dynamically-headroom-calculation.md @@ -746,7 +746,8 @@ Let's imagine what will happen after a XOFF frame has been sent for a priority. 1. MAC/PHY delay, which is the bytes held in the SWITCH CHIP's egress pipeline and PHY when XOFF has been generated. 2. Gearbox delay, which is the latency caused by the Gearbox, if there is one. 3. KB on cable, which is the bytes held in the cable, which is equals the time required for packet to travel from one end of the cable to the other multiplies the port's speed. Obviously, the time is equal to cable length divided by speed of the light in the media. -4. Peer response time, when a switch receives a pause frame, it will not stop the packet transmission immediately, because it need to drain the frames which already submitted to MAC layer. So extra buffer shall be considered to handle the peer delay response. IEEE 802.3 31B.3.7 defines how many pause_quanta shall wait upon an XOFF. A pause_quanta equal to the time required to transmit 512 bits of a frame at the data rate of the MAC. At different operating speed the number of pause_quanta shall be taken are also different. Following table shows the number of pause_quanta shall be taken for each speed. +4. Peer response time. When a switch receives a pause frame, it will not stop the packet transmission immediately, because it needs to drain the frames which already been submitted to the MAC layer. So extra buffer shall be considered to handle the peer delay response. IEEE 802.3 31B.3.7 defines how many pause_quanta shall wait upon an XOFF. A pause_quanta is equal to the time required to transmit 512 bits of a frame at the data rate of the MAC. At different operating speeds, the number of pause_quanta shall be taken are also different. Following table shows the number of pause_quanta that shall be taken for each speed. + | Operating speed | Number of pause_quanta | |:--------:|:-----------------------------:| From 11fed3d32226efae5923c627df1131164d96ec9b Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Mon, 13 Sep 2021 14:40:55 +0800 Subject: [PATCH 051/175] Update dynamically-headroom-calculation.md --- doc/qos/dynamically-headroom-calculation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qos/dynamically-headroom-calculation.md b/doc/qos/dynamically-headroom-calculation.md index 5c188529624..1376e02ab96 100644 --- a/doc/qos/dynamically-headroom-calculation.md +++ b/doc/qos/dynamically-headroom-calculation.md @@ -786,7 +786,7 @@ Therefore, headroom is calculated as the following: - `cell occupancy` = (100 - `small packet percentage` + `small packet percentage` * `worst case factor`) / 100 - `kb on cable` = `cable length` / `speed of light in media` * `port speed` - `kb on gearbox` = `port speed` * `gearbox delay` / 8 / 1024 -- `peer response` = (`number of pause_quanta` * 512) / 8 / 1024 +- `peer response` = (`number of pause_quanta` * 512) / 8 - `propagation delay` = `port mtu` + 2 * (`kb on cable` + `kb on gearbox`) + `mac/phy delay` + `peer response` - `Xon` = `pipeline latency` - `Xoff` = `lossless mtu` + `propagation delay` * `cell occupancy` From 14d99d988631203df58642bf0d7c812c365d57d7 Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak Date: Wed, 15 Sep 2021 12:45:25 +0300 Subject: [PATCH 052/175] Update ACL table type HLD Signed-off-by: Stepan Blyshchak --- doc/acl/ACL-Table-Type-HLD.md | 70 ++++++++++++++++++++-- doc/acl/img/acl-table-type-remove-flow.svg | 2 +- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index 83f31c181d1..d2e70b7efa1 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -70,7 +70,8 @@ The scope of this document covers ACL feature enhancements, in particular the wa with user defined set of matches, actions if required and bind point types. The way developers use ACLOrch public API is also improved to be more flexible for different use cases, such as PFC watchdog, PBH, MACSec, etc. The ACL rule classes defined in ACLOrch is also a subject to be changed due to the new concept of custom ACL table types. -CLI nor other user interface is not covered by this document. + +No new CLI nor other user interface for creating custom ACL table types is covered by this document. ### Architecture Design @@ -146,15 +147,22 @@ container ACL_TABLE_TYPE { list ACL_TABLE_TYPE_LIST { key "ACL_TABLE_TYPE_NAME"; + leaf ACK_TABLE_TYPE_NAME { + type string; + } + leaf-list MATCHES { + mandatory true; type string; } leaf-list ACTIONS { type string; + default ""; } leaf-list BIND_POINTS { + mandatory true; type enumeration { enum PORT; enum LAG; @@ -164,6 +172,27 @@ container ACL_TABLE_TYPE { } ``` +ACL_TABLE container change: + +```yang +container ACL_TABLE { + list ACL_TABLE_LIST { + key "ACL_TABLE_NAME"; + + leaf ACL_TABLE_NAME { + type string; + } + + leaf type { + type leafref { + path "/acl:sonic-acl/acl:ACL_TABLE_TYPE/acl:ACL_TABLE_TYPE_LIST/acl:ACL_TABLE_TYPE_NAME"; + } + } + } +} + +``` + #### Control plane tables Control plane table are moved to its own table in CONFIG DB to not overlap with HW ACL tables. @@ -292,7 +321,7 @@ based on the ASIC platform it is running on. There is either a "combined" or This does not play well with the new concept of user defined table types. To solve this we have few options: -1. Non backward compatible change: let the CONFIG DB table maps 1:1 in ASIC DB table. +1. Reflecting exact CONFIG DB configuration: Let the CONFIG DB table maps 1:1 in ASIC DB table. User is able to configure either two tables types, one for IPv4, one for IPv6 or single with IPv4 and IPv6 keys. @@ -302,6 +331,21 @@ with IPv4 and IPv6 keys. 3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well as default table types. +e.g: + +```json +{ + "DEVICE_METADATA": { + "localhost": { + "combined_v4_v6_mode": [ + "MIRROR", + "MIRRORV6" + ] + } + } +} +``` + In this design option 1 is chosen due to transparency and simplicity. The mode is exposed by orchagent in STATE DB by orchagent. ``` @@ -315,8 +359,7 @@ The user or controller needs to read this value and decide whether to create two #### DB migration -The DB migrator script updated with a logic to move ACL rules for particular platforms supporting combined mirror mode to a table MIRRORV4V6 and for -platforms where separated mode is used ACL rules are moved into corresponding MIRROR or MIRRORV6. +The DB migrator script updated with a logic to move ACL rules for particular platforms supporting combined mirror mode to a table MIRRORV4V6 and for platforms where separated mode is used ACL rules are moved into corresponding MIRROR or MIRRORV6. #### ACL rule object model @@ -377,6 +420,15 @@ Updating ACL table allows only for updating ports bound to it. NOTE: ACL rules coming from CONFIG DB are updated by removal and re-creation, an updateAclRule is mostly used for other orch's use cases. +### CLI + +ACL CLI implementation is updated to perform validation of a table type. In this validation, a table type name passed to CLI +is validated against ACL_TABLE_TYPE CONFIG DB table. In addition, a list of actions is validated against STATE DB information. + +``` +admin@sonic:~$ sudo config acl add table DATAACL L3 --ports Ethernet0,Ethernet4 --stage ingress +``` + ### Syncd N/A @@ -414,10 +466,20 @@ tables referencing it. ### VS tests - Enhance test_acl.py with a test configuration including table types needed for the rest of the tests (L3, L3V6, etc.). +- Add a new test case to check creating custom table types: + - Create a ACL table referencing not yet created table type "TEST" + - Verify no ACL table is created in ASIC DB + - Create a custom ACL table type "TEST" with the predefined list of matches, actions, bind points + - Verify ACL table is created in ASIC DB with correct attributes + - Delete ACL table type "TEST" from CONFIG DB + - Verify ACL table still exists in ASIC DB + - Delete ACL table from CONFIG DB + - Verify no ACL table exists in ASIC DB ### System tests - Existing ACL/Everflow tests cover default table types coming from init_cfg.json, which means it is covering the flow of creating table types. +- Extend existing ACL/Everflow tests with a fixture to create custom table types that will be a copy of a default onces and run the same test cases. - Warm/Fast reboot tests to verify the functionality with new changes. ### Open questions diff --git a/doc/acl/img/acl-table-type-remove-flow.svg b/doc/acl/img/acl-table-type-remove-flow.svg index 5d9f27c42c6..7b1182b9c58 100755 --- a/doc/acl/img/acl-table-type-remove-flow.svg +++ b/doc/acl/img/acl-table-type-remove-flow.svg @@ -1,3 +1,3 @@ -
CONFIG DB
CONFIG DB
del ACL_TABLE_TYPE|type
del ACL_TABLE_T...
ACLOrch
ACLOrch
SAI
SAI
else: remove from
internal cache
else: remove from...
if there are ACL tables
referencing "type" - 
retry on next iteration
if there are ACL tables...
Viewer does not support full SVG 1.1
\ No newline at end of file +
CONFIG DB
CONFIG DB
del ACL_TABLE_TYPE|type
del ACL_TABLE_T...
ACLOrch
ACLOrch
SAI
SAI
else: remove from
internal cache
else: remove from...
if there are ACL tables
referencing "type" - 
retry on next iteration
if there are ACL tables...
del ACL_TABLE|DATAACL
del ACL_TABLE|D...
sai_acl_api->remove_acl_table
sai_acl_api->re...
Viewer does not support full SVG 1.1
\ No newline at end of file From 32c85f4452952152928ba14d862adc5b2e120ba9 Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak Date: Wed, 15 Sep 2021 12:47:32 +0300 Subject: [PATCH 053/175] Update ACL table type HLD Signed-off-by: Stepan Blyshchak --- doc/acl/ACL-Table-Type-HLD.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index d2e70b7efa1..da8dc14711b 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -318,6 +318,10 @@ based on the ASIC platform it is running on. There is either a "combined" or +-------------------+--------------+---------------+ ``` +This special handling has also the following limitations: + - Only 1 ACL table of type MIRROR and 1 ACL table of type MIRRORV6 can exist and must be of the same stage + - Modifying ACL table configuration for V4 mirror table, e.g: bind ports results in silent modification of a V6 table. + This does not play well with the new concept of user defined table types. To solve this we have few options: From 96a65f0a4d67dc3b0949d5798be51ab10da99c07 Mon Sep 17 00:00:00 2001 From: Alexandru Banu Date: Tue, 21 Sep 2021 11:52:52 +0300 Subject: [PATCH 054/175] Renamed MPLS EXP to MPLS TC --- ..._exp_to_tc_map.md => mpls_tc_to_tc_map.md} | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) rename doc/qos/{mpls_exp_to_tc_map.md => mpls_tc_to_tc_map.md} (61%) diff --git a/doc/qos/mpls_exp_to_tc_map.md b/doc/qos/mpls_tc_to_tc_map.md similarity index 61% rename from doc/qos/mpls_exp_to_tc_map.md rename to doc/qos/mpls_tc_to_tc_map.md index cec4b1d5853..c3147e77185 100644 --- a/doc/qos/mpls_exp_to_tc_map.md +++ b/doc/qos/mpls_tc_to_tc_map.md @@ -1,8 +1,8 @@ -# MPLS EXP to TC map +# MPLS TC to TC map ## 1. Table of Content -- [MPLS EXP to TC map](#mpls-exp-to-tc-map) +- [MPLS TC to TC map](#mpls-tc-to-tc-map) - [1. Table of Content](#1-table-of-content) - [2. Revision](#2-revision) - [3. Scope](#3-scope) @@ -32,10 +32,11 @@ | Rev | Date | Author | Change Description | |:---:|:-----------:|:-----------------------:|--------------------------------------------| | 0.1 | 16/08/2021 | Alexandru Banu | Initial version | +| 0.2 | 21/09/2021 | Alexandru Banu | Renamed MPLS EXP to MPLS TC per RFC 5462 | ## 3. Scope -This HLD extends SONiC to support MPLS EXP to TC mappings. +This HLD extends SONiC to support MPLS TC to TC mappings. ## 4. Definitions/Abbreviations @@ -44,11 +45,11 @@ QoS = Quality of Service ## 5. Overview -This new enhancement adds support to SONiC for MPLS EXP to TC map which allows QoS to work on MPLS packets. +This new enhancement adds support to SONiC for MPLS TC to TC map which allows QoS to work on MPLS packets. ## 6. Requirements -User can configure MPLS EXP to TC map at start-of-day via configuration file. CLI support will exist to offer the same amount of support as for DSCP to TC map. +User can configure MPLS TC to TC map at start-of-day via configuration file. CLI support will exist to offer the same amount of support as for DSCP to TC map. ## 7. Architecture Design @@ -58,19 +59,19 @@ The overall SONiC architecture will not be changed and no new sub-modules will b ### 8.1. DB -The CONFIG DB will be updated to include a new "MPLS_EXP_TO_TC_MAP_TABLE" similar to the existing "DSCP_TO_TC_MAP_TABLE". This will have the following format: +The CONFIG DB will be updated to include a new "MPLS_TC_TO_TC_MAP_TABLE" similar to the existing "DSCP_TO_TC_MAP_TABLE". This will have the following format: ``` -### MPLS_EXP_TO_TC_MAP_TABLE - ; MPLS EXP to TC map +### MPLS_TC_TO_TC_MAP_TABLE + ; MPLS TC to TC map ;SAI mapping - qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_MPLS_EXP_TO_TC - key = "MPLS_EXP_TO_TC_MAP_TABLE:"name + key = "MPLS_TC_TO_TC_MAP_TABLE:"name ;field value - mpls_exp_value = 1*DIGIT - tc_value = 1*DIGIT + mpls_tc_value = 1*DIGIT + tc_value = 1*DIGIT Example: - 127.0.0.1:6379> hgetall "MPLS_EXP_TO_TC_MAP_TABLE:AZURE" - 1) "3" ;mpls exp + 127.0.0.1:6379> hgetall "MPLS_TC_TO_TC_MAP_TABLE:AZURE" + 1) "3" ;mpls tc 2) "3" ;tc 3) "6" 4) "5" @@ -80,11 +81,11 @@ The CONFIG DB will be updated to include a new "MPLS_EXP_TO_TC_MAP_TABLE" simila ### 8.2. sonic-swss-common -sonic-swss-common's schema will be updated to include a CFG_MPLS_EXP_TO_TC_MAP_TABLE_NAME define for the new table name. +sonic-swss-common's schema will be updated to include a CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME define for the new table name. ### 8.3. sonic-swss -sonic-swss's QoS orch will be updated to include a new handler for MPLS EXP to TC map, similar to the existing DSCP to TC map but with extra input validations, checking that the values are in the correct numeric range and that no MPLS EXP value is mapped to more than one TC value. Among debugging logs, appropriate error logs will be introduced to let the user know if they miss-configured a map. +sonic-swss's QoS orch will be updated to include a new handler for MPLS TC to TC map, similar to the existing DSCP to TC map but with extra input validations, checking that the values are in the correct numeric range and that no MPLS TC value is mapped to more than one TC value. Among debugging logs, appropriate error logs will be introduced to let the user know if they miss-configured a map. ### 8.4. sonic-utilities @@ -92,17 +93,17 @@ sonic-utilities will be updated to offer the same amount of support for CLI comm ### 8.5. Other implications -There are no other implications. SAI and sairedis already support for MPLS EXP to TC map. In terms of warm restart / fastboot / scalability / performance and so on, this should not represent an impact. +There are no other implications. SAI and sairedis already support for MPLS TC to TC map. In terms of warm restart / fastboot / scalability / performance and so on, this should not represent an impact. ## 9. SAI API -MPLS EXP to TC map are already supported in SAI. +MPLS TC to TC map are already supported in SAI. ## 10. Configuration and management ### 10.1. CLI/YANG model Enhancements -CLI config commands will be updated to include the same level of support for MPLS EXP to TC maps as for DSCP to TC maps. Namely, `config reload` and `config clear` will be updated to include the new mapping table as well. +CLI config commands will be updated to include the same level of support for MPLS TC to TC maps as for DSCP to TC maps. Namely, `config reload` and `config clear` will be updated to include the new mapping table as well. ### 10.2. Config DB Enhancements @@ -114,13 +115,13 @@ Not impacted by the changes. ## 12. Restrictions/Limitations -User can't configure MPLS EXP to TC map via CLI (only via reload command). +User can't configure MPLS TC to TC map via CLI (only via reload command). ## 13. Testing Requirements/Design ### 13.1. Unit Test cases -The QoS UTs present in sonic-swss will be extended to accommodate the new MPLS EXP to TC map. These will largely follow the DSCP to TC map example but will add input validation checks as well. The new code will have full code coverage as far as the UT framework allows it. +The QoS UTs present in sonic-swss will be extended to accommodate the new MPLS TC to TC map. These will largely follow the DSCP to TC map example but will add input validation checks as well. The new code will have full code coverage as far as the UT framework allows it. ### 13.2. System Test cases From 62b8d998a7d665fee43b711650674599eb133016 Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak Date: Tue, 21 Sep 2021 18:40:30 +0300 Subject: [PATCH 055/175] update ACL table type HLD Signed-off-by: Stepan Blyshchak --- doc/acl/ACL-Table-Type-HLD.md | 105 +++++----------------------------- 1 file changed, 13 insertions(+), 92 deletions(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index da8dc14711b..b05eb223ae5 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -73,6 +73,9 @@ classes defined in ACLOrch is also a subject to be changed due to the new concep No new CLI nor other user interface for creating custom ACL table types is covered by this document. +Currently supported table types (L3, L3V6, MIRROR, etc.) are still built-in in orchagent as they require special handling, +specifically tables of type MIRROR/MIRRORV6. + ### Architecture Design No SONiC architecture changes are required. @@ -104,7 +107,7 @@ Example: ```json { "ACL_TABLE_TYPE": { - "L3": { + "CUSTOM_L3": { "MATCHES": [ "IN_PORTS", "OUT_PORTS", @@ -123,7 +126,7 @@ Example: "ACL_TABLE": { "DATAACL": { "STAGE": "INGRESS", - "TYPE": "L3", + "TYPE": "CUSTOM_L3", "PORTS": [ "Ethernet0", "PortChannel1" @@ -147,7 +150,7 @@ container ACL_TABLE_TYPE { list ACL_TABLE_TYPE_LIST { key "ACL_TABLE_TYPE_NAME"; - leaf ACK_TABLE_TYPE_NAME { + leaf ACL_TABLE_TYPE_NAME { type string; } @@ -184,8 +187,12 @@ container ACL_TABLE { } leaf type { - type leafref { - path "/acl:sonic-acl/acl:ACL_TABLE_TYPE/acl:ACL_TABLE_TYPE_LIST/acl:ACL_TABLE_TYPE_NAME"; + mandatory true; + type union { + type leafref { + path "/acl:sonic-acl/acl:ACL_TABLE_TYPE/acl:ACL_TABLE_TYPE_LIST/acl:ACL_TABLE_TYPE_NAME"; + } + type stypes:acl_table_type; } } } @@ -211,25 +218,6 @@ Control plane table are moved to its own table in CONFIG DB to not overlap with } ``` -### Initial CONFIG DB - -The following existing table types defined in init_cfg.json: - -- L3 -- L3V6 -- MIRROR -- MIRRORV6 -- MIRRORV4V6 -- MIRROR_DSCP -- DTEL_FLOW_WATCHLIST -- DTEL_DROP_WATCHLIST -- MCLAG - -The init_cfg.json.j2 creates some table types only for platforms that support a particular feature (like in band telemetry). -The list of matches, bind point types and actions is copied from orchagent code. - -DTEL table is created in the init_cfg.json on a platform supporting it. - ### STATE DB ACL stage capabilities are queried by reading SAI_SWITCH_ATTR_ACL_STAGE_INGRESS and SAI_SWITCH_ATTR_ACL_STAGE_EGRESS @@ -298,73 +286,6 @@ Orchagent's AclRule::make_shared makes decision which AclRule child instance to Since orchagent does not know all the table types there should be single AclRule handling all the matches and actions and perform validation against the table type configuration. -#### Mirror table type: combined/separated table - -Orchagent has a special treatment for tables of type MIRROR and MIRRORV6 -based on the ASIC platform it is running on. There is either a "combined" or -"seperated" mode for MIRROR tables. - -``` -+-------------------+------------------------------+ -| | CONFIG DB | ASIC DB | -+-------------------+--------------+---------------+ -| combined | MIRROR | Single mirror | -| +--------------+ table in HW | -| | MIRRORV6 | V4 + V6 keys | -+-------------------+--------------+---------------+ -| seperated | MIRROR | Mirror V4 | -| +--------------+---------------+ -| | MIRRORV6 | Mirror V6 | -+-------------------+--------------+---------------+ -``` - -This special handling has also the following limitations: - - Only 1 ACL table of type MIRROR and 1 ACL table of type MIRRORV6 can exist and must be of the same stage - - Modifying ACL table configuration for V4 mirror table, e.g: bind ports results in silent modification of a V6 table. - -This does not play well with the new concept of user defined table types. -To solve this we have few options: - -1. Reflecting exact CONFIG DB configuration: Let the CONFIG DB table maps 1:1 in ASIC DB table. -User is able to configure either two tables types, one for IPv4, one for IPv6 or single -with IPv4 and IPv6 keys. - -2. Maintaing the current behaviour. Orchagent should have the knowledge to act in either -*combined* or *separeted* mode if the table type is named "MIRROR" or "MIRRORV6". - -3. Put this as a configuration in CONFIG DB. E.g, for certain two table types define "combined_v4_v6_mode". This configuration can come from init_cfg.json at start as well -as default table types. - -e.g: - -```json -{ - "DEVICE_METADATA": { - "localhost": { - "combined_v4_v6_mode": [ - "MIRROR", - "MIRRORV6" - ] - } - } -} -``` - -In this design option 1 is chosen due to transparency and simplicity. The mode is exposed by orchagent in STATE DB by orchagent. - -``` - -127.0.0.1:6379[6]> hgetall SWITCH_CAPABILITY|switch -1) mirror_mode -2) combined -``` - -The user or controller needs to read this value and decide whether to create two ACL tables for IPv4 and IPv6 (separated) or single ACL table for both IPv4 and IPv6 (combined). - -#### DB migration - -The DB migrator script updated with a logic to move ACL rules for particular platforms supporting combined mirror mode to a table MIRRORV4V6 and for platforms where separated mode is used ACL rules are moved into corresponding MIRROR or MIRRORV6. - #### ACL rule object model Since the ACL rule is not bound to a table type anymore (e.g could be table type which supports mirror action, packet action and redirect action at the same time) @@ -489,7 +410,7 @@ tables referencing it. ### Open questions - What kind of level of YANG validation is required? - - Have matches and actions as enumeration (needs to be updated every time new match/action is introduced in SONiC) or could it be just of a type of string? + - Have matches and actions need to be of enumeration type (needs to be updated every time new match/action is introduced in SONiC) or could it be just of a type of string? - Does YANG infrastructure in SONiC supports validation against STATE DB information (e.g. is_action_list_mandatory)? - Does this feature needs a similar capability table for match fields? What is the SAI API to query it? - Currently SAI object API allows to query for an ACL table attributes CREATE, SET, GET operations implementation availability (sai_query_attribute_capability, sai_attr_capability_t), From a13f7d2514ccddadb55653e7b00373b925aefa7c Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak Date: Wed, 22 Sep 2021 11:19:56 +0300 Subject: [PATCH 056/175] Update Acl Table Type HLD Signed-off-by: Stepan Blyshchak --- doc/acl/ACL-Table-Type-HLD.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/acl/ACL-Table-Type-HLD.md b/doc/acl/ACL-Table-Type-HLD.md index b05eb223ae5..09f74509504 100644 --- a/doc/acl/ACL-Table-Type-HLD.md +++ b/doc/acl/ACL-Table-Type-HLD.md @@ -218,6 +218,10 @@ Control plane table are moved to its own table in CONFIG DB to not overlap with } ``` +### Initial CONFIG + +Table types that need to be available by default can be defined in the init_cfg.json. Later on some of the pre-defined tables types (L3, L3V6, etc.) in CONFIG DB can be put in init_cfg.json. + ### STATE DB ACL stage capabilities are queried by reading SAI_SWITCH_ATTR_ACL_STAGE_INGRESS and SAI_SWITCH_ATTR_ACL_STAGE_EGRESS @@ -296,6 +300,11 @@ other orchs to override the behavior. Figure 1. ACL rule model

+The polymorphism of existing AclRule derivatives AclRuleL3, AclRuleL3V6, etc is in the validation methods. +E.g. AclRuleL3's validateAddMatch() method checks wether the match is one of the L3 table type matches. +This can be consolidated into single generic validate() method that validations ACL Rule configuration +by checking AclRule SAI matches and SAI actions against AclTable SAI attributes. + #### ACLOrch public API ACL rule base class declaration: @@ -331,6 +340,8 @@ bool removeAclTable(string aclTableName); bool updateAclTable(shared_ptr aclTable); ``` +NOTE: Updating ACL table allows only for updating ports bound to it. + ACL Rule methods declaration: ```c++ bool addAclRule(shared_ptr aclRule, string aclTableName); @@ -338,10 +349,15 @@ bool removeAclRule(string aclTableName, string aclRuleName); bool updateAclRule(shared_ptr updatedAclRule); ``` +##### ACL rule update + While add and remove are known and already implemented today in orchagent, update for ACLRule iterates over the diff between old and new member fields m_matches, m_actions and sets the corresponding attribute of an ACL Rule. -Updating ACL table allows only for updating ports bound to it. +Besides attributes of ACL rule itself, ACL rule owns an ACL counter object and ACL range objects. +By comparing the m_createCounter boolean flag and ranges defined for old and new ACL rule these objects +are removed/created based on the difference calculation. + NOTE: ACL rules coming from CONFIG DB are updated by removal and re-creation, an updateAclRule is mostly used for other orch's use cases. From bb476c589a6ac5a7e3ea66a0a84caab6264dc7a9 Mon Sep 17 00:00:00 2001 From: Alexandru Banu Date: Wed, 22 Sep 2021 15:49:50 +0300 Subject: [PATCH 057/175] Add per-port binding configuration details --- doc/qos/mpls_tc_to_tc_map.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/qos/mpls_tc_to_tc_map.md b/doc/qos/mpls_tc_to_tc_map.md index c3147e77185..0bd36ee2f3a 100644 --- a/doc/qos/mpls_tc_to_tc_map.md +++ b/doc/qos/mpls_tc_to_tc_map.md @@ -33,6 +33,7 @@ |:---:|:-----------:|:-----------------------:|--------------------------------------------| | 0.1 | 16/08/2021 | Alexandru Banu | Initial version | | 0.2 | 21/09/2021 | Alexandru Banu | Renamed MPLS EXP to MPLS TC per RFC 5462 | +| 0.3 | 22/09/2021 | Alexandru Banu | Added per-port binding configuration | ## 3. Scope @@ -59,18 +60,18 @@ The overall SONiC architecture will not be changed and no new sub-modules will b ### 8.1. DB -The CONFIG DB will be updated to include a new "MPLS_TC_TO_TC_MAP_TABLE" similar to the existing "DSCP_TO_TC_MAP_TABLE". This will have the following format: +The CONFIG DB will be updated to include a new "MPLS_TC_TO_TC_MAP" similar to the existing "DSCP_TO_TC_MAP". This will have the following format: ``` -### MPLS_TC_TO_TC_MAP_TABLE +### MPLS_TC_TO_TC_MAP ; MPLS TC to TC map ;SAI mapping - qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_MPLS_EXP_TO_TC - key = "MPLS_TC_TO_TC_MAP_TABLE:"name + key = "MPLS_TC_TO_TC_MAP|"name ;field value mpls_tc_value = 1*DIGIT tc_value = 1*DIGIT Example: - 127.0.0.1:6379> hgetall "MPLS_TC_TO_TC_MAP_TABLE:AZURE" + 127.0.0.1:6379> hgetall "MPLS_TC_TO_TC_MAP|Mpls_tc_to_tc_map1" 1) "3" ;mpls tc 2) "3" ;tc 3) "6" @@ -79,6 +80,8 @@ The CONFIG DB will be updated to include a new "MPLS_TC_TO_TC_MAP_TABLE" similar 6) "5" ``` +In order to allow a user to bind such a map to a port, the existing `PORT_QOS_MAP` table will be enhanced to allow a new field-value pair, where the field is going to be named `mpls_tc_to_tc_map` and the value will be the `MPLS_TC_TO_TC_MAP.key` of the map to use. + ### 8.2. sonic-swss-common sonic-swss-common's schema will be updated to include a CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME define for the new table name. @@ -87,6 +90,8 @@ sonic-swss-common's schema will be updated to include a CFG_MPLS_TC_TO_TC_MAP_TA sonic-swss's QoS orch will be updated to include a new handler for MPLS TC to TC map, similar to the existing DSCP to TC map but with extra input validations, checking that the values are in the correct numeric range and that no MPLS TC value is mapped to more than one TC value. Among debugging logs, appropriate error logs will be introduced to let the user know if they miss-configured a map. +Also, the QoS orch will be enhanced to configure the new field-value pair in `PORT_QOS_MAP` mentioned at section 8.1. + ### 8.4. sonic-utilities sonic-utilities will be updated to offer the same amount of support for CLI commands that DSCP to TC map already provide. @@ -115,7 +120,8 @@ Not impacted by the changes. ## 12. Restrictions/Limitations -User can't configure MPLS TC to TC map via CLI (only via reload command). +- User can't configure MPLS TC to TC map via CLI (only via reload command). +- User can't configure per-switch or per-inseg MPLS TC to TC maps. ## 13. Testing Requirements/Design From 3f9d00538c566f5f36c32a67b74cdbac565eb2b6 Mon Sep 17 00:00:00 2001 From: Senthil Kumar Guruswamy Date: Fri, 1 Oct 2021 07:42:27 -0700 Subject: [PATCH 058/175] SYSTEM READY --- doc/system-ready/system-ready-HLD.md | 546 +++++++++++++++++++++++++++ 1 file changed, 546 insertions(+) create mode 100644 doc/system-ready/system-ready-HLD.md diff --git a/doc/system-ready/system-ready-HLD.md b/doc/system-ready/system-ready-HLD.md new file mode 100644 index 00000000000..1c49039fe59 --- /dev/null +++ b/doc/system-ready/system-ready-HLD.md @@ -0,0 +1,546 @@ + + +# System Ready HLD + +#### Rev 0.2 + +# Table of Contents + +- [List of Tables](#list-of-tables) +- [Revision](#revision) +- [Definition/Abbreviation](#definitionabbreviation) +- [About This Manual](#about-this-manual) +- [1 Introduction and Scope](#1-introduction-and-scope) + - [1.1 Limitation of Existing tools](#11-existingtools-limitation) + - [1.2 Benefits of this feature](#12-benefits-of-this-feature) +- [2 Feature Requirements](#2-feature-requirements) + - [2.1 Functional Requirements](#21-functional-requirements) + - [2.2 Configuration and Management Requirements](#22-configuration-and-management-requirements) + - [2.3 Scalability Requirements](#23-scalability-requirements) + - [2.4 Warm Boot Requirements](#24-warm-boot-requirements) +- [3 Feature Description](#3-feature-description) +- [4 Feature Design](#4-feature-design) + - [4.1 Overview](#41-design-overview) + - [4.2 Sysmonitor](#42-db-changes) + - [4.2.1 Subtasks in Sysmonitor](#421-subtasks-in-sysmonitor) + - [4.3 Service Identification and Categorization](#43-service-categorization) + - [4.4 System ready Framework business logic](#44-systemready-fremework-logic) + - [4.5 Provision for apps to mark closest UP status](#45-provision-for-apps-to-mark-UP) + - [4.5.1 CONFIG_DB Changes](#451-config-db-changes) + - [4.5.2 STATE_DB Changes](#452-state-db-changes) + - [4.5.3 Feature yang Changes](#453-feature-yang-changes) + - [4.6 Syslogs](#46-syslogs) +- [5 CLI](#5-cli) + - [5.1 Output Format](#51-cli-output-format) + - [5.2 show system status core](#52-system-status-core) + - [5.3 show system status all](#53-system-status-all) + - [5.4 show system status all --brief](#54-system-status-all-brief) + - [5.5 show system status all --detail](#55-system-status-all-detail) +- [6 Serviceability and Debug](#6-serviceability-and-debug) +- [7 Warm reboot Support](#7-warm-reboot-support) +- [8 Unit Test Cases ](#8-unit-test-cases) +- [9 References ](#9-references) + +# List of Tables + +[Table 1: Abbreviations](#table-1-abbreviations) + +# Revision +| Rev | Date | Author | Change Description | +|:--:|:--------:|:-----------------:|:------------------------------------------------------------:| +| 0.1 | | Senthil Kumar Guruswamy | Initial version | +| 0.2 | | Senthil Kumar Guruswamy | Update as per review comments | + + +# Definition/Abbreviation + +### Table 1: Abbreviations + +| **Term** | **Meaning** | +| -------- | ----------------------------------------- | +| FEATURE | Docker/Service | +| App | Docker/Service | + + +# About this Manual + +This document provides general information about the System Ready feature implementation in SONiC. + + +# 1 Introduction and Scope + +This document describes the Functionality and High level design of the System Ready feature. + +At present, there is no mechanism to know that the system is up with all the essential sonic services and also, all the docker apps are ready along with port ready status to start the network traffic. +With the asynchronous architecture of SONiC, we will not be able to verify if the config has been applied all the way down to the hardware. +However, if we could get the closest up status of each docker app considering their config receive ready and port ready, the system readiness could be arrived. + +A new python based System monitor framework is introduced to monitor all the essential system host services including docker wrapper services on an event based model and declare the system is ready. +This framework gives provision for docker and host apps to notify its closest up status. +CLIs are provided to fetch the current system status and also service running status and its app ready status along with failure reason if any. + + +## 1.1 Limitation of Existing tools: + - Monit tool is a poll based approach which monitors the configured services for every 1 minute. + - Monit tools feature of critical process monitoring was deprecated as supervisor does the job. Hence system-health tool which depends on monit does not work. + - Container_checker in monit checks only for running status of expected containers. + - Monits custom script execution can only run a logic to take some action but it is yet again a poll based approach. + + +## 1.2 Benefits of this feature: + - Event based model - which does not hog cpu unlike poll based approach. + - Know the overall system status through syslog and as well through CLIs + - CLIs just connect to the backend daemon to fetch the details. No redundant codes. + - Combatibility with application extension framework. + SONiC package installation process will register new feature in CONFIG DB. + Third party dockers(signature verified) gets integrated into sonic os and runs similar to the existing dockers accessing db etc. + Now, once the feature is enabled, it becomes part of either sonic.target or multi-user.target and when it starts, it automatically comes under the system monitor framework watchlist. + However, app ready status for those dockers cant be tracked unless they comply with the framework logic. + Hence any third party docker needs to follow the framework logic by including "check_up_status" field while registering itself in CONFIG_DB and also make use of the provision given to docker apps to mark its closest up status in STATE_DB. + + + + +# 2 Feature Requirements + +## 2.1 Functional Requirements + +Following requirements are addressed by the design presented in this document: + +1. Identify the list of sonic services to be monitored and categorize them into core and all services. +2. A new service for the sysmon framework to check system status of all the service units and receive service state change notifications to declare the system ready status. +3. Provision for apps to notify its closest up status in STATE DB. This should internally cover Port ready status. +4. Appropriate system ready syslogs to be raised. +5. New CLIs to be introduced to know the current system status of core and all services. + - "show system status core" covers the core services. + - "show system status all" covers the overall system status. +6. During the techsupport data collection, the new CLIs to be included for debugging. + + +## 2.2 Configuration and Management Requirements + +This feature will support CLI and no configuration command is provided for any congiruations. + + +## 2.3 Scalability Requirements + +NA + +## 2.4 Warm Boot Requirements + +warmboot-finalizer sonic service to be monitored as part of all services. + + +# 3 Feature Description + +This feature provides framework to determine the current system status to declare the system is (almost) ready for network traffic. + +System ready is arrived at considering the following factors. +1. All sonic docker services and its UP status(including Portready status) +2. All sonic host services + + +# 4 Feature Design +## 4.1 Design Overview + +- A new service sysmonitor tracks the sonic host service list, all the docker wrapper services for their running status and also, their app ready status including portready and declare the system is ready. +- When sysmonitor daemon boots up, it polls for the service list status once and maintains a global dictionary in ram and publishes the system ready status in form of syslog and as well as in STATE_DB. +- Subsequently, when any service state changes, sysmonitor gets the event notification for that service to be checked for its status and update the dictionary promptly. +- Hence the system status is always up-to-date to be notifed to user in the form of syslog, STATE_DB update and as well as could be fetched by appropriate CLIs. +- The memory for the dictionary is just ~1Kb. + + +## 4.2 Sysmonitor + +Sysmonitor is the main service daemon which does the job of checking the service status and updating the system readiness. + +### 4.2.1 Subtasks in Sysmonitor + +1. subscribe to system dbus + - With the dbus subscription, any systemd events gets notified to this task and it puts the event in the multiprocessing queue. + +2. subscribe to the new FEATURE table in STATE_DB of Redis database + - With the STATE_DB feature table subscription, any input to the FEATURE table gets notified to this task and it puts the event in the queue. + +3. Main task + - Runs through the polling of all service status check once and listen for events in queue populated by dbus task and statedb task to take appropriate action of checking the specific event unit status + and updating system status in the dictionary. + +4. Listener task + - A listener task runs in sysmonitor listening in socket /var/run/sysready.socket. + - Show command communicates with sysmonitor through this socket to get the current system status information from the dictionary maintained. + + + +## 4.3 Service Identification and Categorization + +Services are categorized into core services and all services. +1. core services: + - swss, bgp, teamd, pmon, syncd, database, mgmt-framework are identified as core services and a list of these services are maintained predefined. + +2. all services: + - It covers the enabled services from FEATURE table of CONFIG_DB.I + - It also covers the HOST_FEATURE table services of CONFIG_DB. + - Also, since the idea is to cover only the sonic services but not the general system services, sysmonitor tracks services under "multi-user.target" and "sonic.target" + - This covers all the sonic docker services and most of the sonic host services. + + +## 4.4 System ready Framework business logic + +The system ready framework design should just not only display the current status of the services in the system +but align the services within framework to flag the status as "not ok" if the service is not running when it was intended to be running. + +- A 'core' service must be active and running and up_status marked by docker app should be true to be considered OK, otherwise flag it as Failed +- For 'all' services: + - Loaded, enabled/enabled-runtime/static, active & running, active & exited state services are considered 'OK'. + - For active and running services, up_status marked by docker app should be True to be considered 'OK'. + - Failed state services are considered 'Not OK'. + - Activating state services are considered as 'Starting'. + - Deactivating state services are considered as 'Stopping'. + - Inactive state services category: + - oneshot services are considered as 'OK'. + - Special services with condition pathexists check failure are considered as 'OK'. + - Other services in inactive state are considered to be 'Not OK'. + - Any service type other than oneshot if by default goes to inactive state, RemainAfterExit=yes entry needs to be added to their service unit file to be inline with the framework. + + +## 4.5 Provision for apps to mark closest UP status + +The feature provides framework for services to mark its closest UP status. +In simple, each app is responsible in marking its closest up status in STATE_DB. Sysmonitor tool just reads from it. + +### 4.5.1 CONFIG_DB Changes (init_cfg.json) + +Docker apps marking their UP status in STATE_DB will input an entry in FEATURE table of CONFIG_DB with check_up_status flag set to true through /etc/sonic/init_cfg.json file change. +Host apps marking their UP status in STATE_DB will input an entry in HOST_FEATURE table of CONFIG_DB with check_up_status flag set to true through /etc/sonic/init_cfg.json file change. +Sysmonitor checks for the check_up_status flag in CONFIG_DB before reading the app ready status from STATE_DB. +If the flag does not exist or if set to False, then sysmonitor will not read the app ready status but just checks the running status of the service. + + +``` +- Schema in /etc/sonic/init_cfg.json + This json file will be fed to FEATURE & HOST_FEATURE table of CONFIG_DB during bootup. + This json file will be factory default and no config command will be provided for "check_up_status" entry to be updated in CONFIG_DB later. + { + "FEATURE": { + "": { + ... + "state": "enabled", + "check_up_status": "true" + } + }, + "HOST_FEATURE": { + "": { + "check_up_status": "true" + } + } + } +``` + +### 4.5.2 STATE_DB Changes +- Docker apps which rely on config, can mark 'up_status' to true in STATE_DB when they are ready to receive configs from CONFIG_DB and/or some extra dependencies are met. +- Respective apps should mark its up_status considering Port ready status. Hence there is no separate logic check needed by system monitoring tool +- Any docker app which has multiple independent daemons can maintain a separate intermediate key-value in the redis-db for each of the daemons and the startup script that invokes each of these daemons can determine the status from the redis entries by each daemon and finally update the STATE_DB up_status. +- Along with up_status, docker apps should update the fail_reason field with appropriate reason in case of failure or empty string in case of success. +- Also, update_time field to be fed in as well in the format of epoch time. +- Host apps update the same FEATURE table in STATE_DB as sysmonitor subtask subscribes to the table. + To reduce redundancy in db table subscription, we update the same table in STATE_DB for host apps as well. + + +For instances, +- swss docker app can wait for port init done and wait for Vrfmgr, Intfmgr and Vxlanmgr to be ready before marking its up status. +- Other apps like udld,stp etc once after waiting for PortInitDone status and interface db creation, they could mark their UP status. +- Database app which is the first/base app to be up, may set the UP_STATUS to True once all the required number of redis-server instances are in running state. + However, as the supervisor monitors all the redis db instances as part of critical process list, there is no need of a separate app ready status in database docker. + + +STATE_DB: +``` +- sonic-db-cli STATE_DB HSET "FEATURE|" up_status true +- sonic-db-cli STATE_DB HSET "FEATURE|" fail_reason "" / "" +- sonic-db-cli STATE_DB HSET "FEATURE|" update_time "" + +- Schema in STATE_DB + sonic-db-dump -n STATE_DB output + "FEATURE|": { + "type": "hash", + "value": { + "up_status": "true", + "fail_reason": "", + "update_time": "" + + } + }, + +- Example: + "FEATURE|bgp": { + "type": "hash", + "value": { + "fail_reason": "", + "update_time": "1634119649.7268105", + "up_status": "true" + } + }, + +``` + + +In addition to this, sysmonitor posts the 'core' and 'all' system status to SYSTEM_READY table in STATE_DB as below. + +``` + "SYSTEM_READY|SYSTEM_STATE_CORE": { + "type": "hash", + "value": { + "status": "up" + } + } + "SYSTEM_READY|SYSTEM_STATE_ALL": { + "type": "hash", + "value": { + "status": "up" + } + } +``` + +### 4.5.3 Feature yang Changes + +Following field is added to the sonic-feature.yang file and also new table HOST_FEATURE and its field is introduced. + +``` +container sonic-feature { + + container FEATURE { + + ... + + leaf check_up_status { + description "This configuration controls the system ready tool to check + the app ready/up status"; + type boolean; + default false; + } + } + container HOST_FEATURE { + + description "host feature table in config_db.json"; + + list HOST_FEATURE_LIST { + + key "name"; + + leaf name { + description "host feature name in host Feature table"; + type string { + length 1..32; + } + } + + leaf check_up_status { + description "This configuration controls the system ready tool to check + the app ready/up status"; + type boolean; + default false; + } + } + } +} +``` + +## 4.6 Syslogs: + +- Syslog to be generated for any Sonic systemd services that changes event(active/inactive) +- A dedicated task in sysmonitor runs to listen for any service state change events. + Upon receiving any state change events, the task check for its status and identify the particular event service that caused the change and raise a syslog for that service. +- syslog is generated for "System is ready with core services" and "System is not ready - core services are not ok" for core service category. +- Also, for all services, syslog is generated for "System is ready with all the services" and "System is not ready - One or more services are not ok" scenario, only when there is a change between the two states. + +``` +Example 1: + Jul 02 11:53:51.020133 2021 sonic INFO system#monitor: System is not ready - core services are not ok + Jul 02 11:53:51.020133 2021 sonic INFO system#monitor: System is not ready - one or more services are not ok + Jul 02 11:53:51.020133 2021 sonic INFO system#monitor: System is ready with core services + Jul 02 11:53:51.020133 2021 sonic INFO system#monitor: System is ready with all the services + +Example 2: + Jul 02 17:01:00.454978 2021 sonic INFO system#monitor: hostcfgd.service service state changed to [inactive/dead] + Jul 02 17:01:28.725101 2021 sonic INFO system#monitor: hostcfgd.service service state changed to [active/running] +``` + +## 5 CLI: + +Only Click commands are supported and not KLISH commands as KLISH will not work if Mgmt-framework service is down. +- show system status core + +- show system status all + Options: --brief/--detail + - show system status all --brief + - show system status all --detail + +### 5.1 Output Format: + 1. Short message indicating system is ready or not + 2. Header - Service-Name, Service-Status, App-Ready-Status, Fail-Reason + 3. List of servies and it status values + 4. Output Strings for Service-Status and App-Ready-Status: + "OK" - when a service is up + "Not OK" - to emphasise a service is not running when it was intended to be running. + "Starting" - Initializing + "Stopping" - Deactivating + 5. Fail-Reason will be extracted from "Result" property of systemctl command and then displayed appropriately. + Different reasons can be: + start-limit-hit + exit-code + Inactive + custom strings from apps + +``` + <"System is ready with all the services"/"System is not ready - one or more services are not up"> + <"System is ready with core services"/"System is not ready - core services are not up"> + Service-Name Service-Status App-Ready-Status Fail-Reason + OK OK - + Not OK Not OK start-limit-hit + OK Not OK Inactive +``` + + +### 5.2 show system status core + +``` + [#]show system status core + System is ready with core services + + Service-Name Service-Status App-Ready-Status Fail-Reason + swss OK OK - + bgp OK OK - + teamd OK OK - + pmon OK OK - + syncd OK OK - + database OK OK - + mgmt-framework OK OK - + [#] + + + [#]show system status core + System is not ready - core services are not ok + + Service-Name Service-Status App-Ready-Status Fail-Reason + swss OK OK - + bgp Not OK Not OK Inactive + teamd OK OK - + pmon OK OK - + syncd OK OK - + database OK OK - + mgmt-framework OK OK - + [#] +``` + + +### 5.3 show system status all + +``` + root@sonic:/# show system status all + System is ready with all the services + + Service-Name Service-Status App-Ready-Status Fail-Reason + as7712-pddf-platform-monitor OK OK - + bgp OK OK - + caclmgrd OK OK - + config-setup OK OK - + containerd OK OK - + + root@sonic:/# show system status all + System is not ready - one or more services are not ok + + Service-Name Service-Status App-Ready-Status Fail-Reason + aaastatsd Not OK Not OK start-limit-hit + as7712-pddf-platform-monitor OK OK - + bgp OK Starting - + caclmgrd OK OK - + config-setup OK OK - + ntp-config Starting Starting - + pmon OK Not OK Transceiver daemon is not up +``` + +### 5.4 show system status all --brief +- The output of this command will just display the brief status of the entire sonic services. +- Output format of the CLI : + +``` + <"System is ready with all the services"/"System is not ready - one or more services are not ok"> + + Example 1: + root@sonic:/# show system status all --brief + System is not ready - one or more services are not ok + + root@sonic:/# +``` + +### 5.5 show system status all --detail +- This command would display systemctl status output of failed services along with "all" option output. + +- Output format of the CLI : + +``` + <"System is ready with all the services"/"System is not ready - one or more services are not ok"> + Service-Name Service-Status App-Ready-Status Fail-Reason + OK OK - + Not OK Not OK start-limit-hit + OK OK - + + ● system-health1.service - SONiC system health monitor + Loaded: loaded (/lib/systemd/system/system-health.service; enabled-runtime; + Active: failed (Result: start-limit-hit) since Thu 2019-02-14 11:21:09 UTC; + Main PID: 4764 (code=exited, status=0/SUCCESS) + + + + Example: + root@sonic:/# show system status all --detail + System is not ready - one or more services are not OK + + Service-Name Service-Status App-Ready-Status Fail-Reason + as7712-pddf-platform-monitor OK OK - + bgp OK OK - + caclmgrd OK OK - + ... + telemetry OK OK - + tpcm OK OK - + udld Not OK Not OK exit-code + updategraph OK OK - + vrrp OK OK - + + ● udld.service - UDLD container + Loaded: loaded (/usr/lib/systemd/system/udld.service; enabled; vendor preset: enabled) + Active: failed (Result: exit-code) since Fri 2021-07-02 11:53:09 UTC; 2h 8min ago + Process: 1827 ExecStartPre=/usr/bin/udld.sh start (code=exited, status=255) + CPU: 161ms +``` + +## 6 Serviceability and Debug + +- The system logging mechanisms explained in section 4.6 shall be used. +- The show commands can be used as debug aids. +- Techsupport: + In generate dump tool, show system status all --detail CLI is included to be saved to the dump in the name of systemstatus.all.detail + + + +## 7 Warm Reboot Support + +Sysmonitor monitors the running status of warmboot-finalizer.service +This can be enhanced to hook to the actual completion of warboot-finalizer service later. + + +## 8 Unit Test Cases + +1. Check show system status all +2. Check show system status all --brief +3. Check show system status all --detail +4. Check show system status core +5. Make any of the docker apps down and check failed apps details are shown +6. Make any of the host apps down and check failed apps details are shown +7. Check top command for sysmonitor CPU and memory usage +8. Check syslogs for any service state change. +9. Check syslog for overall system status change. + +## 9 References +NA From 1a484778655f1138c87ba0d352a9162c43cbce39 Mon Sep 17 00:00:00 2001 From: Bhagatram Janarthanan Date: Tue, 19 Oct 2021 12:56:29 -0700 Subject: [PATCH 059/175] Update pins_hld.md --- doc/pins/pins_hld.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pins/pins_hld.md b/doc/pins/pins_hld.md index 43f6d037dfe..a7588f8f7e8 100644 --- a/doc/pins/pins_hld.md +++ b/doc/pins/pins_hld.md @@ -124,7 +124,7 @@ SONiC is structured into various containers that communicate through multiple lo https://docs.google.com/drawings/d/1Maxgf2-DyJHi_MpGbYLhgUWnfebJfFHYJPcB8NO_WVE/edit --> -The P4RT application listens to a remote SDN controller and creates entries in the APPL and CONFIG databases. Following the SONiC architecture, the P4RT application writes its output to a new table in the APPL database. From there, the new P4Orch picks up the changes and writes the entries into the existing ASIC tables, where they get picked up by syncd. This path is highlighted in green in the PINS Architecture figure. +The P4RT application listens to a remote SDN controller and creates entries in the APPL and CONFIG databases. Following the SONiC architecture, the P4RT application writes its output to a new table in the APPL database. From there, the new P4Orch picks up the changes and writes the entries into the existing ASIC tables, where they get picked up by syncd. This path is highlighted in green in the PINS Architecture figure. The green path builds a parallel path in the orchagent as the current SWSS does not support (1) Response path - which is required by the P4RT application, (2) Ownership tags - which are required when there are more than one writer to the same table. Over the long term, once such features are supported by the SWSS, the green path can be merged with the existing tables. The red path is used if a new table, match, or action is being added from the P4RT application into the ASIC DB when this table is not present in the SAI pipeline. More detailed information regarding the red path is provided in the supplementary document: [P4 Extensions for SAI][p4ext-hld]. From 255d61ae5921f7c798af1019128c02d56a1fce28 Mon Sep 17 00:00:00 2001 From: Renuka Manavalan <47282725+renukamanavalan@users.noreply.github.com> Date: Mon, 25 Oct 2021 17:00:32 -0700 Subject: [PATCH 060/175] Update Json_Change_Application_Design.md --- .../Json_Change_Application_Design.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/config-generic-update-rollback/Json_Change_Application_Design.md b/doc/config-generic-update-rollback/Json_Change_Application_Design.md index d28267120ce..43b614ed88b 100644 --- a/doc/config-generic-update-rollback/Json_Change_Application_Design.md +++ b/doc/config-generic-update-rollback/Json_Change_Application_Design.md @@ -398,3 +398,4 @@ N/A | 8 | Remove a key from an existing table. | | 9 | Replace a mandatory item e.g. type under ACL_TABLE. | | 10 | Remove an item that has a default value e.g. stage under ACL_TABLE. | +| 11 | Change applier - with sample data & validators that touch all code paths | From 60e3b6d2baccf0145e3586f283a46ac1d97d4ae2 Mon Sep 17 00:00:00 2001 From: kannankvs Date: Wed, 27 Oct 2021 18:47:43 +0530 Subject: [PATCH 061/175] Updated the images for fetching the latest build Updated the images for fetching the latest build from pipelines page and also changed the name from Image to Latest successful build --- Supported-Devices-and-Platforms.html | 496 ++++++++++++++++----------- 1 file changed, 288 insertions(+), 208 deletions(-) diff --git a/Supported-Devices-and-Platforms.html b/Supported-Devices-and-Platforms.html index 442917cacfb..ff5ae18657e 100644 --- a/Supported-Devices-and-Platforms.html +++ b/Supported-Devices-and-Platforms.html @@ -1,4 +1,8 @@ + + + + @@ -40,314 +44,495 @@ - Page-4 - + Page-5 + Actor lifeline.1378 ConfigDB - - Sheet.1175 - + + Sheet.1001 + - - Sheet.1176 - + + Sheet.1002 + - - Sheet.1177 + + Sheet.1003 - - Sheet.1178 - + + Sheet.1004 + - - - ConfigDB + + + ConfigDB - + Object lifeline.1383 PbhOrch - - Sheet.1180 - + + Sheet.1006 + - - Sheet.1181 - + + Sheet.1007 + - - Sheet.1182 + + Sheet.1008 - - Sheet.1183 - + + Sheet.1009 + - - - PbhOrch + + + PbhOrch - + Object lifeline.1388 AclOrch - - Sheet.1185 - + + Sheet.1011 + - - Sheet.1186 - + + Sheet.1012 + - - Sheet.1187 + + Sheet.1013 - - Sheet.1188 - + + Sheet.1014 + - - - AclOrch + + + AclOrch - + Object lifeline.1393 SAI - - Sheet.1190 - + + Sheet.1016 + - - Sheet.1191 - + + Sheet.1017 + - - Sheet.1192 + + Sheet.1018 - - Sheet.1193 - + + Sheet.1019 + - - - SAI + + + SAI - + Activation.1398 - + - + Activation.1399 - + - + Asynchronous Message.1400 PBH_HASH_FIELD|name - - - PBH_HASH_FIELD|name - + + + PBH_HASH_FIELD|name + Self Message.1401 process data - - - process data - + + + process data + Asynchronous Message.1402 PBH_TABLE|name - - - PBH_TABLE|name - + + + PBH_TABLE|name + Message.1412 updateAclTable - - - updateAclTable - + + + updateAclTable + Activation.1413 - + - + Return Message.1414 return <result> - - - return <result> - + + + return <result> + Message.1418 set_acl_table_attribute - - - set_acl_table_attribute - + + + set_acl_table_attribute + Return Message.1419 return <status> - - - return <status> - + + + return <status> + Activation.1430 - + - + Self Message.1431 process data - - - process data - + + + process data + Activation.1452 - + - + Self Message.1453 updatePbhHashField - - - updatePbhHashField - + + + updatePbhHashField + Activation.1451 - + - + Message.1455 set_fine_grained_hash_field_attribute - - - set_fine_grained_hash_field_attribute - + + + set_fine_grained_hash_field_attribute + Activation.1456 - + - + Return Message.1457 return <status> - - - return <status> - + + + return <status> + Asynchronous Message.1458 PBH_HASH|name - - - PBH_HASH|name - + + + PBH_HASH|name + Activation.1459 - + - + Self Message.1460 updatePbhHash - - - updatePbhHash - + + + updatePbhHash + Activation.1461 - + - + Message.1462 set_hash_attribute - - - set_hash_attribute - + + + set_hash_attribute + Activation.1463 - + - + Return Message.1464 return <status> - - - return <status> - + + + return <status> + Asynchronous Message.1466 PBH_RULE|name - - - PBH_RULE|name - + + + PBH_RULE|name + Message.1469 updateAclRule - - - updateAclRule - + + + updateAclRule + Activation.1470 - + - + Return Message.1471 return <result> - - - return <result> - + + + return <result> + Message.1472 set_acl_entry_attribute - - - set_acl_entry_attribute - + + + set_acl_entry_attribute + Return Message.1473 return <status> - - - return <status> - + + + return <status> + Activation.1565 - + - + Self Message.1566 process data - - - process data - + + + process data + Activation.1567 - + - + Self Message.1568 updatePbhTable - - - updatePbhTable - + + + updatePbhTable + Activation.1569 - + - + Activation.1673 - + - + Activation.1573 - + - + Self Message.1675 process data - - - process data - + + + process data + Activation.1575 - + - + Self Message.1576 updatePbhRule - - - updatePbhRule - + + + updatePbhRule + Activation.1577 - + - + Activation.1579 - + + + Loop fragment.877 + + + + + Sheet.1064 + transaction + + transaction + + Sheet.1065 + HSET/HDEL + HSET/HDEL + + + Actor lifeline.1087 + CLI + + Sheet.1067 + + + + Sheet.1068 + + + + Sheet.1069 + + + Sheet.1070 + + + + + CLI + + + Asynchronous Message.1092 + PBH_HASH_FIELD|key|field + + + PBH_HASH_FIELD|key|field + + Activation.1093 + + + + Asynchronous Message.1073 + PBH_HASH_FIELD|key|field + + + PBH_HASH_FIELD|key|field + + Asynchronous Message.1076 + PBH_HASH_FIELD|key|field + + + PBH_HASH_FIELD|key|field + + Sheet.1075 + . . . + + . . . + + Loop fragment.1097 + + + + + Sheet.1077 + transaction + + transaction + + Sheet.1078 + HSET/HDEL + HSET/HDEL + + + Asynchronous Message.1100 + PBH_HASH|key|field + + + PBH_HASH|key|field + + Asynchronous Message.1101 + PBH_HASH|key|field + + + PBH_HASH|key|field + + Asynchronous Message.1102 + PBH_HASH|key|field + + + PBH_HASH|key|field + + Sheet.1082 + . . . + + . . . + + Loop fragment.1104 + + + + + Sheet.1084 + transaction + + transaction + + Sheet.1085 + HSET/HDEL + HSET/HDEL + + + Asynchronous Message.1107 + PBH_TABLE|key|field + + + PBH_TABLE|key|field + + Asynchronous Message.1108 + PBH_TABLE|key|field + + + PBH_TABLE|key|field + + Asynchronous Message.1109 + PBH_TABLE|key|field + + + PBH_TABLE|key|field + + Sheet.1089 + . . . + + . . . + + Loop fragment.1115 + + + + + Sheet.1091 + transaction + + transaction + + Sheet.1092 + HSET/HDEL + HSET/HDEL + + + Asynchronous Message.1118 + PBH_RULE|key|field + + + PBH_RULE|key|field + + Asynchronous Message.1119 + PBH_RULE|key|field + + + PBH_RULE|key|field + + Asynchronous Message.1120 + PBH_RULE|key|field + + + PBH_RULE|key|field + + Sheet.1096 + . . . + + . . . diff --git a/doc/pbh/pbh-design.md b/doc/pbh/pbh-design.md index 1ffb411f8d4..548de5c7441 100644 --- a/doc/pbh/pbh-design.md +++ b/doc/pbh/pbh-design.md @@ -28,11 +28,19 @@ - [2.4.1.2 PBH rule](#2412-pbh-rule) - [2.4.1.3 PBH hash](#2413-pbh-hash) - [2.4.1.4 PBH hash field](#2414-pbh-hash-field) - - [2.4.2 Configuration sample](#242-configuration-sample) + - [2.4.2 State DB](#242-state-db) + - [2.4.2.1 PBH table](#2421-pbh-table) + - [2.4.2.2 PBH rule](#2422-pbh-rule) + - [2.4.2.3 PBH hash](#2423-pbh-hash) + - [2.4.2.4 PBH hash field](#2424-pbh-hash-field) + - [2.4.3 Data sample](#243-data-sample) + - [2.4.4 Configuration sample](#244-configuration-sample) - [2.5 Flows](#25-flows) - - [2.5.1 PBH add](#251-pbh-add) - - [2.5.2 PBH update](#252-pbh-update) - - [2.5.3 PBH remove](#253-pbh-remove) + - [2.5.1 Key modification](#251-key-modification) + - [2.5.1.1 PBH add](#2511-pbh-add) + - [2.5.1.2 PBH remove](#2512-pbh-remove) + - [2.5.2 Field modification](#252-field-modification) + - [2.5.2.1 PBH update](#2521-pbh-update) - [2.6 CLI](#26-cli) - [2.6.1 Command structure](#261-command-structure) - [2.6.2 Usage examples](#262-usage-examples) @@ -46,10 +54,11 @@ ## Revision -| Rev | Date | Author | Description | -|:---:|:----------:|:--------------:|:-------------------------------------------| -| 0.1 | 15/03/2021 | Nazarii Hnydyn | Initial version | -| 0.2 | 07/06/2021 | Nazarii Hnydyn | Update DB schema: introduce PBH hash field | +| Rev | Date | Author | Description | +|:---:|:----------:|:--------------:|:------------------------------------------------| +| 0.1 | 15/03/2021 | Nazarii Hnydyn | Initial version | +| 0.2 | 07/06/2021 | Nazarii Hnydyn | Update DB schema: introduce PBH hash field | +| 0.3 | 15/11/2021 | Nazarii Hnydyn | PBH modification flows: introduce field set/del | ## About this manual @@ -96,8 +105,8 @@ This document describes the high level design of PBH feature in SONiC [Figure 1: PBH design](#figure-1-pbh-design) [Figure 2: PBH OA design](#figure-2-pbh-oa-design) [Figure 3: PBH add flow](#figure-3-pbh-add-flow) -[Figure 4: PBH update flow](#figure-4-pbh-update-flow) -[Figure 5: PBH remove flow](#figure-5-pbh-remove-flow) +[Figure 4: PBH remove flow](#figure-4-pbh-remove-flow) +[Figure 5: PBH update flow](#figure-5-pbh-update-flow) ## List of tables @@ -203,8 +212,10 @@ A custom hashing can be configured for Regular/FG ECMP and LAG. ###### Figure 2: PBH OA design A `PbhOrch` class with a set of data structures will be implemented to handle PBH feature. -OA will be extended with a new PBH Config DB schema and SAI FG Hash API support. +OA will be extended with a new PBH Config DB/State DB schema and SAI FG Hash API support. PBH table/rule/hash/hash-field updates will be processed by OA based on Config DB changes. +Each update operation will be verified against generic/vendor specific capabilities. +Generic/Vendor specific capabilities by default will be stored in State DB by OA. Some object updates will be handled and some will be considered as invalid. ### 2.3.2 PBH orch @@ -244,6 +255,19 @@ On hash field create, `PbhOrch` will verify if the hash field already exists. Cr exists will be treated as an update. Regular hash field add/remove will update the internal class structures and appropriate SAI objects will be created or deleted. +PBH object modification concept allows to do a fine-grained field/value tuple management. +For that purpose a PBH capabilities table will be introduced. Each PBH key will have it's own set of +field capabilities defined in a State DB. + +PBH capabilities: +1. ADD - field can be set to the redis hash in case it does not exist yet +2. UPDATE - field can be set to the redis hash in case it already exists +3. REMOVE - field can be deleted from the redis hash in case it does exist + +In general, PBH capabilities represent a mix of SAI interface/vendor restrictions. +When special policy is not required, a generic SAI-based implementation will be used by OA. +Platform/Vendor identification will be done via `platform` environment variable. + **Skeleton code:** ```cpp class PbhOrch : public Orch @@ -285,7 +309,7 @@ class AclOrch : public Orch, public Observer ... bool updateAclTable(string table_id, AclTable &table); - bool updateAclRule(string table_id, string rule_id, bool enableCounter); + bool updateAclRule(shared_ptr updatedAclRule); ... }; @@ -358,7 +382,7 @@ public: bool validateAddMatch(const sai_attribute_t &attr); bool validateAddAction(const sai_attribute_t &attr); bool validate() override; - void update(SubjectType, void *) override; + void onUpdate(SubjectType, void *) override; }; ``` @@ -472,7 +496,245 @@ ip-mask = ipv4-addr / ipv6-addr **Note:** field _ip_mask_ is only valid when _hash_field_ equals _INNER_DST/SRC_IPV4_ or _INNER_DST/SRC_IPV6_ -### 2.4.2 Configuration sample +### 2.4.2 State DB + +#### 2.4.2.1 PBH table +```abnf +; defines schema for PBH table capabilities +key = PBH_CAPABILITIES|table ; must be unique + +; field = value +interface_list = capabilities +description = capabilities + +; value annotations +capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \ + "ADD" "," "UPDATE" \ + "ADD" "," "REMOVE" \ + "UPDATE" "," "ADD" \ + "UPDATE" "," "REMOVE" \ + "REMOVE" "," "ADD" \ + "REMOVE" "," "UPDATE" \ + "ADD" "," "UPDATE" "," "REMOVE" +``` + +#### 2.4.2.2 PBH rule +```abnf +; defines schema for PBH rule capabilities +key = PBH_CAPABILITIES|rule ; must be unique + +; field = value +priority = capabilities +gre_key = capabilities +ether_type = capabilities +ip_protocol = capabilities +ipv6_next_header = capabilities +l4_dst_port = capabilities +inner_ether_type = capabilities +hash = capabilities +packet_action = capabilities +flow_counter = capabilities + +; value annotations +capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \ + "ADD" "," "UPDATE" \ + "ADD" "," "REMOVE" \ + "UPDATE" "," "ADD" \ + "UPDATE" "," "REMOVE" \ + "REMOVE" "," "ADD" \ + "REMOVE" "," "UPDATE" \ + "ADD" "," "UPDATE" "," "REMOVE" +``` + +#### 2.4.2.3 PBH hash +```abnf +; defines schema for PBH hash capabilities +key = PBH_CAPABILITIES|hash ; must be unique + +; field = value +hash_field_list = capabilities + +; value annotations +capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \ + "ADD" "," "UPDATE" \ + "ADD" "," "REMOVE" \ + "UPDATE" "," "ADD" \ + "UPDATE" "," "REMOVE" \ + "REMOVE" "," "ADD" \ + "REMOVE" "," "UPDATE" \ + "ADD" "," "UPDATE" "," "REMOVE" +``` + +#### 2.4.2.4 PBH hash field +```abnf +; defines schema for PBH hash field capabilities +key = PBH_CAPABILITIES|hash-field ; must be unique + +; field = value +hash_field = capabilities +ip_mask = capabilities +sequence_id = capabilities + +; value annotations +capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \ + "ADD" "," "UPDATE" \ + "ADD" "," "REMOVE" \ + "UPDATE" "," "ADD" \ + "UPDATE" "," "REMOVE" \ + "REMOVE" "," "ADD" \ + "REMOVE" "," "UPDATE" \ + "ADD" "," "UPDATE" "," "REMOVE" +``` + +### 2.4.3 Data sample + +**Config DB:** +```bash +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_ip_proto' +1) "hash_field" +2) "INNER_IP_PROTOCOL" +3) "sequence_id" +4) "1" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_l4_dst_port' +1) "hash_field" +2) "INNER_L4_DST_PORT" +3) "sequence_id" +4) "2" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_l4_src_port' +1) "hash_field" +2) "INNER_L4_SRC_PORT" +3) "sequence_id" +4) "2" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_dst_ipv4' +1) "hash_field" +2) "INNER_DST_IPV4" +3) "ip_mask" +4) "255.0.0.0" +5) "sequence_id" +6) "3" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_src_ipv4' +1) "hash_field" +2) "INNER_SRC_IPV4" +3) "ip_mask" +4) "0.0.0.255" +5) "sequence_id" +6) "3" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_dst_ipv6' +1) "hash_field" +2) "INNER_DST_IPV6" +3) "ip_mask" +4) "ffff::" +5) "sequence_id" +6) "4" + +redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_src_ipv6' +1) "hash_field" +2) "INNER_SRC_IPV6" +3) "ip_mask" +4) "::ffff" +5) "sequence_id" +6) "4" + +redis-cli -n 4 HGETALL 'PBH_HASH|inner_v4_hash' +1) "hash_field_list@" +2) "inner_ip_proto,inner_l4_dst_port,inner_l4_src_port,inner_dst_ipv4,inner_src_ipv4" + +redis-cli -n 4 HGETALL 'PBH_HASH|inner_v6_hash' +1) "hash_field_list@" +2) "inner_ip_proto,inner_l4_dst_port,inner_l4_src_port,inner_dst_ipv6,inner_src_ipv6" + +redis-cli -n 4 HGETALL 'PBH_RULE|pbh_table|nvgre' + 1) "ether_type" + 2) "0x0800" + 3) "flow_counter" + 4) "DISABLED" + 5) "gre_key" + 6) "0x2500/0xffffff00" + 7) "hash" + 8) "inner_v6_hash" + 9) "inner_ether_type" +10) "0x86dd" +11) "ip_protocol" +12) "0x2f" +13) "packet_action" +14) "SET_ECMP_HASH" +15) "priority" +16) "2" + +redis-cli -n 4 HGETALL 'PBH_RULE|pbh_table|vxlan' + 1) "ether_type" + 2) "0x0800" + 3) "flow_counter" + 4) "ENABLED" + 5) "hash" + 6) "inner_v4_hash" + 7) "inner_ether_type" + 8) "0x0800" + 9) "ip_protocol" +10) "0x11" +11) "l4_dst_port" +12) "0x12b5" +13) "packet_action" +14) "SET_LAG_HASH" +15) "priority" +16) "1" + +redis-cli -n 4 HGETALL 'PBH_TABLE|pbh_table' +1) "description" +2) "NVGRE and VxLAN" +3) "interface_list@" +4) "Ethernet0,Ethernet4,PortChannel0001,PortChannel0002" +``` + +**State DB:** +```bash +redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|table' + 1) "interface_list" + 2) "UPDATE" + 3) "description" + 4) "UPDATE" + +redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|rule' + 1) "priority" + 2) "UPDATE" + 3) "ether_type" + 4) "ADD,UPDATE,REMOVE" + 5) "ip_protocol" + 6) "ADD,UPDATE,REMOVE" + 7) "ipv6_next_header" + 8) "ADD,UPDATE,REMOVE" + 9) "l4_dst_port" + 10) "ADD,UPDATE,REMOVE" + 11) "gre_key" + 12) "ADD,UPDATE,REMOVE" + 13) "inner_ether_type" + 14) "ADD,UPDATE,REMOVE" + 15) "hash" + 16) "UPDATE" + 17) "packet_action" + 18) "ADD,UPDATE,REMOVE" + 19) "flow_counter" + 20) "ADD,UPDATE,REMOVE" + +redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|hash' + 1) "hash_field_list" + 2) "UPDATE" + +redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|hash-field' + 1) "hash_field" + 2) "" + 3) "ip_mask" + 4) "" + 5) "sequence_id" + 6) "" +``` + +### 2.4.4 Configuration sample **Inner 5-tuple hashing:** ```json @@ -569,23 +831,27 @@ ip-mask = ipv4-addr / ipv6-addr ## 2.5 Flows -### 2.5.1 PBH add +### 2.5.1 Key modification + +#### 2.5.1.1 PBH add ![PBH add flow](images/pbh_add_flow.svg "Figure 3: PBH add flow") ###### Figure 3: PBH add flow -### 2.5.2 PBH update +#### 2.5.1.2 PBH remove -![PBH update flow](images/pbh_update_flow.svg "Figure 4: PBH update flow") +![PBH remove flow](images/pbh_remove_flow.svg "Figure 4: PBH remove flow") -###### Figure 4: PBH update flow +###### Figure 4: PBH remove flow -### 2.5.3 PBH remove +### 2.5.2 Field modification -![PBH remove flow](images/pbh_remove_flow.svg "Figure 5: PBH remove flow") +#### 2.5.2.1 PBH update -###### Figure 5: PBH remove flow +![PBH update flow](images/pbh_update_flow.svg "Figure 5: PBH update flow") + +###### Figure 5: PBH update flow ## 2.6 CLI @@ -602,7 +868,10 @@ config | |--- rule | |--- add OPTIONS - | |--- update OPTIONS + | |--- update + | | |--- field + | | |--- set OPTIONS + | | |--- del OPTIONS | |--- delete | |--- hash @@ -675,7 +944,11 @@ config pbh rule add 'pbh_table' 'nvgre' \ --hash 'inner_v6_hash' \ --packet-action 'SET_ECMP_HASH' \ --flow-counter 'DISABLED' -config pbh rule update 'pbh_table' 'nvgre' \ +config pbh rule update field del 'pbh_table' 'nvgre' \ +--ip-protocol +config pbh rule update field set 'pbh_table' 'nvgre' \ +--ether-type '0x86dd' \ +--ipv6-next-header '0x2f' \ --flow-counter 'ENABLED' config pbh rule delete 'pbh_table' 'nvgre' ``` @@ -924,6 +1197,11 @@ PBH basic configuration test: 3. Verify ASIC DB object count after PBH hash creation/removal 4. Verify ASIC DB object count after PBH hash field creation/removal +PBH basic update test: +1. Verify ASIC DB object state after PBH table update +2. Verify ASIC DB object state after PBH rule update +3. Verify ASIC DB object state after PBH hash update + PBH extended configuration test: 1. Create inner 5-tuple PBH hash fields 2. Create PBH hash From 736b9a8d72300d64b275233e1c2a0bbd32912bf9 Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Wed, 19 Jan 2022 11:15:48 -0800 Subject: [PATCH 106/175] Update Interface-Link-bring-up-sequence.md --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index f6f968168c6..85892d903b4 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -106,9 +106,13 @@ Recommend following this high-level work-flow sequence to accomplish the Objecti - xcvrd to subscribe to a new field “host_tx_ready” in port table state-DB - Orchagent will set the “host_tx_ready” to true/false based on the SET_ADMIN_STATE attribute return status to syncd/gbsyncd. (As part of SET_ADMIN_STATE attribute enable, the NPU Tx is enabled) - xcvrd process the “host_tx_ready” value change event and do optics datapath init / de-init using CMIS API -- Recommendation is to follow this proposal for all the known interface speeds - 400G/100G/40G/25G/10G +- Recommendation is to follow this proposal for all the known interfaces - 400G/100G/40G/25G/10G. Reason being: - 400G - as mentioned above the CMIS spec to be followed - - 100G/40G/25G/10G - deterministic approach to bring the interface will eliminate any link stability issue which will be difficult to chase in the production network + - 100G/40G/25G/10G - + - deterministic approach to bring the interface will eliminate any link stability issue which will be difficult to chase in the production network + - there is a possibility of interface link flaps with non-quiescent optical modules if this 'deterministic approach' is not followed + - It helps bring down the optical module laser when interface is adminstiratively shutdown. Per the workflow here, this is acheived by xcvrd listening to host_tx_ready field from PORT_TABLE of STATE_DB. Turning the laser off would reduce the power consumption and avoid any lab hazard + - Additionally provides uniform workflow across all interface types instead of just 400G - This synchronization will also benefit native 10G SFPs interfaces as they are "plug N play" and may not have quiescent functionality. (xcvrd can use the optional 'soft tx disable' ctrl reg to disable the tx) # Proposed Work-Flows From 28a67ee0c5730857a56b3d824a30eadf794a5319 Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Wed, 19 Jan 2022 13:26:47 -0800 Subject: [PATCH 107/175] Update Interface-Link-bring-up-sequence.md --- .../Interface-Link-bring-up-sequence.md | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 85892d903b4..15ad2046028 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -24,11 +24,12 @@ Deterministic Approach for Interface Link bring-up sequence | Rev | Date | Author | Change Description | |:---:|:-----------:|:----------------------------------:|------------------------------| | 0.1 | 08/16/2021 | Shyam Kumar | Initial version -| 0.2 | 12/13/2021 | Shyam Kumar, Jaganathan Anbalagan | Added uses-cases, workflows | +| 0.2 | 12/13/2021 | Shyam Kumar, Jaganathan Anbalagan | Added uses-cases, workflows +| 0.3 | 01/19/2022 | Shyam Kumar | Addressed review-comments | # About this Manual -Its a high-level design document describing the need to have determinstic approach for +This is a high-level design document describing the need to have determinstic approach for Interface link bring-up sequence and workflows for use-cases around it # Abbreviation @@ -110,9 +111,10 @@ Recommend following this high-level work-flow sequence to accomplish the Objecti - 400G - as mentioned above the CMIS spec to be followed - 100G/40G/25G/10G - - deterministic approach to bring the interface will eliminate any link stability issue which will be difficult to chase in the production network + e.g. If there is a PHY device in between, and this 'deterministic approach' is not followed, PHY may adapt to a bad signal or interface flaps may occur when the optics tx/rx enabled during PHY initialization. - there is a possibility of interface link flaps with non-quiescent optical modules if this 'deterministic approach' is not followed - It helps bring down the optical module laser when interface is adminstiratively shutdown. Per the workflow here, this is acheived by xcvrd listening to host_tx_ready field from PORT_TABLE of STATE_DB. Turning the laser off would reduce the power consumption and avoid any lab hazard - - Additionally provides uniform workflow across all interface types instead of just 400G + - Additionally provides uniform workflow (from SONiC NOS) across all interface types instead of just 400G - This synchronization will also benefit native 10G SFPs interfaces as they are "plug N play" and may not have quiescent functionality. (xcvrd can use the optional 'soft tx disable' ctrl reg to disable the tx) # Proposed Work-Flows @@ -136,5 +138,23 @@ Please refer to the flow/sequence diagrams which covers the following required ![LC boot-up sequence - 'admin disable' Config gets applied](https://user-images.githubusercontent.com/69485234/147166884-92c9af48-2d64-4e67-8933-f80531d821b4.png) +# Out of Scope +Following items are not in the scope of this document. They would be taken up separately +1. xcvrd restart + - If the xcvrd goes for restart, then all the DB events will be replayed. + Here the Datapath init/activate (for 400G), tx-disable register set (for 100G), will be a no-op if the optics is already in that state + +2. syncd/gbsyncd/swss docker container restart + - Cleanup scenario - the host_tx_ready field in STATE-DB should be updated to “False” to respective ports that a PHY/NPU interface with + - +3. CMIS API feature is not part of this design and the APIs will be used in this design. For CMIS HLD, Please refer to: + https://github.com/Azure/SONiC/blob/9d480087243fd1158e785e3c2f4d35b73c6d1317/doc/sfp-cmis/cmis-init.md + +4. Error handling of SAI attributes + a) At present, If there is a set attribute failure, orch agent will exit. + Refer the error handling API : https://github.com/Azure/sonic-swss/blob/master/orchagent/orch.cpp#L885 + b) Error handling for SET_ADMIN_STATUS attribute will be added in future. + c) A propabale way to handle the failure is to set a error handling attribute to respective container syncd/GBsyncd with attribute that is failed. + The platform layer knows the error better and it will try to recover. From b802395e168013d42ad9ecefeff3a29bb27c02e6 Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Wed, 19 Jan 2022 13:30:26 -0800 Subject: [PATCH 108/175] Update Interface-Link-bring-up-sequence.md Address review comments, added more details to 'Proposal' section, added 'Out of Scope' section --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 15ad2046028..35891d25979 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -142,14 +142,11 @@ Please refer to the flow/sequence diagrams which covers the following required Following items are not in the scope of this document. They would be taken up separately 1. xcvrd restart - If the xcvrd goes for restart, then all the DB events will be replayed. - Here the Datapath init/activate (for 400G), tx-disable register set (for 100G), will be a no-op if the optics is already in that state - + Here the Datapath init/activate (for 400G), tx-disable register set (for 100G), will be a no-op if the optics is already in that state 2. syncd/gbsyncd/swss docker container restart - Cleanup scenario - the host_tx_ready field in STATE-DB should be updated to “False” to respective ports that a PHY/NPU interface with - - 3. CMIS API feature is not part of this design and the APIs will be used in this design. For CMIS HLD, Please refer to: https://github.com/Azure/SONiC/blob/9d480087243fd1158e785e3c2f4d35b73c6d1317/doc/sfp-cmis/cmis-init.md - 4. Error handling of SAI attributes a) At present, If there is a set attribute failure, orch agent will exit. Refer the error handling API : https://github.com/Azure/sonic-swss/blob/master/orchagent/orch.cpp#L885 From 4c735ca12ffd7c36ffaf5a9ba728c6941e31191e Mon Sep 17 00:00:00 2001 From: jaganbal-a <97986478+jaganbal-a@users.noreply.github.com> Date: Thu, 20 Jan 2022 20:56:52 -0500 Subject: [PATCH 109/175] Update Interface-Link-bring-up-sequence.md --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 35891d25979..ac3273ea054 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -99,7 +99,7 @@ Interface link bring-up sequence and workflows for use-cases around it Have a determistic approach for Interface link bring-up sequence i.e. below sequence to be followed: 1. Initialize and enable NPU Tx and Rx path 2. For system with 'External' PHY: Initialize and enable PHY Tx and Rx on both line and host sides; ensure host side link is up - 3. Then only perform optics data path initialization/activation/Tx enable (for 400G) and Tx enable (for 100G) + 3. Then only perform optics data path initialization/activation/Tx enable (for CMIS complaint optical modules) and Tx enable (for SFF complaint optical modules) # Proposal From d9d1ba6cc7e109196a0915735e3adbd14ef0cd23 Mon Sep 17 00:00:00 2001 From: jaganbal-a <97986478+jaganbal-a@users.noreply.github.com> Date: Sat, 22 Jan 2022 14:39:05 -0500 Subject: [PATCH 110/175] Update Interface-Link-bring-up-sequence.md (#2) * Update Interface-Link-bring-up-sequence.md * Update Interface-Link-bring-up-sequence.md * Update Interface-Link-bring-up-sequence.md * Update Interface-Link-bring-up-sequence.md * Update Interface-Link-bring-up-sequence.md --- .../Interface-Link-bring-up-sequence.md | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index ac3273ea054..982af7d21ba 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -2,7 +2,7 @@ Deterministic Approach for Interface Link bring-up sequence # High Level Design Document -#### Rev 0.2 +#### Rev 0.3 # Table of Contents * [List of Tables](#list-of-tables) @@ -25,7 +25,7 @@ Deterministic Approach for Interface Link bring-up sequence |:---:|:-----------:|:----------------------------------:|------------------------------| | 0.1 | 08/16/2021 | Shyam Kumar | Initial version | 0.2 | 12/13/2021 | Shyam Kumar, Jaganathan Anbalagan | Added uses-cases, workflows -| 0.3 | 01/19/2022 | Shyam Kumar | Addressed review-comments | +| 0.3 | 01/19/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed review-comments | # About this Manual @@ -56,22 +56,22 @@ Interface link bring-up sequence and workflows for use-cases around it # Problem Definition -1. Presently in SONiC, there is no synchronization between 400G Datapath Init operation and enabling ASIC (NPU/PHY) Tx which may cause link instability during administrative interface enable “config interface startup Ethernet” configuration and bootup scenarios. +1. Presently in SONiC, there is no synchronization between Datapath Init operation of CMIS complaint optical module and enabling ASIC (NPU/PHY) Tx which may cause link instability during administrative interface enable “config interface startup Ethernet” configuration and bootup scenarios. - For 400G optics module, the Host (NPU/PHY) needs to provide a valid high-speed Tx input signal at the required signaling rate and encoding type prior to causing a DPSM to exit from DPDeactivated state and to move to DP Init transient state. + For CMIS-compliant active (optical) modules, the Host (NPU/PHY) needs to provide a valid high-speed Tx input signal at the required signaling rate and encoding type prior to causing a DPSM to exit from DPDeactivated state and to move to DP Init transient state. Fundamentally it means - have a deterministic approach to bring-up the interface. Also, this problem is mentioned ‘as outside-the-scope’ of ‘CMIS Application Initialization’ high-level design document **(https://github.com/ds952811/SONiC/blob/0e4516d7bf707a36127438c7f2fa9cc2b504298e/doc/sfp-cmis/cmis-init.md#outside-the-scope)** -2. During administrative interface disable “config interface shutdown Ethernet”, only the ASIC(NPU) Tx is disabled and not the optics laser for 100G/400G. +2. During administrative interface disable “config interface shutdown Ethernet”, only the ASIC(NPU) Tx is disabled and not the opticcal module Tx/laser. This will lead to power wastage and un-necessary fan power consumption to keep the module temperature in operating range # Background - Per the ‘QSFPDD spec’, ‘validation, diagnostics’ done by HW team' and 'agreement with vendors', - need to follow following bring-up seq to enable port/interface with 400G optics in LC/chassis: + Per the ‘CMIS spec’, ‘validation, diagnostics’ done by HW team' and 'agreement with vendors', + need to follow following bring-up seq to enable port/interface with CMIS compliant optical modules in LC/chassis: a) Enable port on NPU (bring-up port, serdes on the NPU ; enable signals) : syncd b) Enable port on PHY (bring-up port, serdes on the PHY ; enable signals) : gbsyncd @@ -80,14 +80,14 @@ Interface link bring-up sequence and workflows for use-cases around it In boards not having PHY, #b) not needed but #a) and #c) sequence to be followed. - ## Clause from QSFP-DD (CMIS4.0 spec) + ## Clause from CMIS4.0 spec Excerpt from CMIS4.0 spec providing detailed reasoning for the above-mentioned bring-up sequence ![61f5b485-cf3b-4ca8-beac-9102b6feabfe](https://user-images.githubusercontent.com/69485234/147173702-f124fc9d-ef27-4816-b1a1-b4a44a5833a7.PNG) - ## Clause from QSFP-DD (CMIS5.0 spec) + ## Clause from CMIS5.0 spec Excerpt from CMIS5.0 spec providing detailed reasoning for the above-mentioned bring-up sequence @@ -96,10 +96,10 @@ Interface link bring-up sequence and workflows for use-cases around it # Objective -Have a determistic approach for Interface link bring-up sequence i.e. below sequence to be followed: +Have a determistic approach for Interface link bring-up sequence for all interfaces types i.e. below sequence to be followed: 1. Initialize and enable NPU Tx and Rx path 2. For system with 'External' PHY: Initialize and enable PHY Tx and Rx on both line and host sides; ensure host side link is up - 3. Then only perform optics data path initialization/activation/Tx enable (for CMIS complaint optical modules) and Tx enable (for SFF complaint optical modules) + 3. Then only perform optics data path initialization/activation/Tx enable (for CMIS complaint optical modules) and Tx enable (for SFF complaint optical modules) # Proposal @@ -107,15 +107,16 @@ Recommend following this high-level work-flow sequence to accomplish the Objecti - xcvrd to subscribe to a new field “host_tx_ready” in port table state-DB - Orchagent will set the “host_tx_ready” to true/false based on the SET_ADMIN_STATE attribute return status to syncd/gbsyncd. (As part of SET_ADMIN_STATE attribute enable, the NPU Tx is enabled) - xcvrd process the “host_tx_ready” value change event and do optics datapath init / de-init using CMIS API -- Recommendation is to follow this proposal for all the known interfaces - 400G/100G/40G/25G/10G. Reason being: - - 400G - as mentioned above the CMIS spec to be followed - - 100G/40G/25G/10G - +- Recommendation is to follow this proposal for all the known interfaces types- 400G/100G/40G/25G/10G. Reason being: + - CMIS complaint optical modules:- + All CMIS complaint optical modules will follow this approach as recommended in the CMIS spec. + - SFF complaint optical modules:- - deterministic approach to bring the interface will eliminate any link stability issue which will be difficult to chase in the production network e.g. If there is a PHY device in between, and this 'deterministic approach' is not followed, PHY may adapt to a bad signal or interface flaps may occur when the optics tx/rx enabled during PHY initialization. - there is a possibility of interface link flaps with non-quiescent optical modules if this 'deterministic approach' is not followed - It helps bring down the optical module laser when interface is adminstiratively shutdown. Per the workflow here, this is acheived by xcvrd listening to host_tx_ready field from PORT_TABLE of STATE_DB. Turning the laser off would reduce the power consumption and avoid any lab hazard - - Additionally provides uniform workflow (from SONiC NOS) across all interface types instead of just 400G - - This synchronization will also benefit native 10G SFPs interfaces as they are "plug N play" and may not have quiescent functionality. (xcvrd can use the optional 'soft tx disable' ctrl reg to disable the tx) + - Additionally provides uniform workflow (from SONiC NOS) across all interface types with or without module presence. + - This synchronization will also benefit SFP+ optical modules as they are "plug N play" and may not have quiescent functionality. (xcvrd can use the optional 'soft tx disable' ctrl reg to disable the tx) # Proposed Work-Flows Please refer to the flow/sequence diagrams which covers the following required use-cases @@ -142,7 +143,7 @@ Please refer to the flow/sequence diagrams which covers the following required Following items are not in the scope of this document. They would be taken up separately 1. xcvrd restart - If the xcvrd goes for restart, then all the DB events will be replayed. - Here the Datapath init/activate (for 400G), tx-disable register set (for 100G), will be a no-op if the optics is already in that state + Here the Datapath init/activate for CMIS compliant optical modules, tx-disable register set (for SFF complaint optical modules), will be a no-op if the optics is already in that state 2. syncd/gbsyncd/swss docker container restart - Cleanup scenario - the host_tx_ready field in STATE-DB should be updated to “False” to respective ports that a PHY/NPU interface with 3. CMIS API feature is not part of this design and the APIs will be used in this design. For CMIS HLD, Please refer to: From 74a7e6639d2907393a60c74d74e6016c3096c483 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com> Date: Thu, 20 Jan 2022 14:18:11 +0800 Subject: [PATCH 111/175] Put port operational speed to STATE DB --- .../port-auto-negotiation-design.md | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/port_auto_neg/port-auto-negotiation-design.md b/doc/port_auto_neg/port-auto-negotiation-design.md index a621a2b0656..41a9ef83aea 100644 --- a/doc/port_auto_neg/port-auto-negotiation-design.md +++ b/doc/port_auto_neg/port-auto-negotiation-design.md @@ -139,7 +139,7 @@ The related port attributes are listed below: Please note that `SAI_PORT_ATTR_ADVERTISED_INTERFACE_TYPE` is a new attribute introduced in SAI 1.7.1. Vendors need to implement this attribute in their SAI implementation. -### Configuration and management +### Configuration and management #### CLI Enhancements @@ -183,7 +183,7 @@ Return: error message if interface_name or speed_list is invalid otherwise empty Note: - speed_list value "all" means all supported speeds + speed_list value "all" means all supported speeds ``` This command always replace the advertised speeds instead of append. For example, say the current advertised speeds value are "10000,25000", if user configure it with `config interface advertised-speeds Ethernet0 40000,100000`, the advertised speeds value will be changed to "40000,100000". @@ -227,7 +227,7 @@ Return: error message if interface_name or interface_type_list is invalid otherwise empty Note: - interface_type_list value "all" means all supported interface type + interface_type_list value "all" means all supported interface type ``` This command always replace the advertised interface types instead of append. For example, say the current advertised interface types value are "KR4,SR4", if user configure it with `config interface advertised-types Ethernet0 CR4`, the advertised interface types value will be changed to "CR4". @@ -346,7 +346,7 @@ The advantage here is that user can get a list of valid interface type from CLI. For speed and adv_speeds, there is a SAI API to get the supported speed list for a given port. The idea here is to query supported speed after orchagent creating port object, and the supported speed list will be save to STATE_DB for CLI to validate. A new field **supported_speeds** will be added to **PORT_TABLE**. If this field is present, CLI will use this field to validate the input speed and adv_speeds argument, otherwise, no validation will be performed on CLI side. The STATE_DB change will be described in [State DB Enhancements](#state-db-enhancements). -#### Config DB Enhancements +#### Config DB Enhancements SONiC already defined two fields related to port speed setting: **speed**, **autoneg**. 3 new fields **adv_speeds**, **interface_type**, **adv_interface_types** will be added to **PORT** table: @@ -396,9 +396,23 @@ To support validate interface speed on CLI side, a new field **supported_speeds* ; field = value ... supported_speeds = STRING ; supported speed list + speed = STRING ; operational speed An example value of supported_speeds could be "10000,25000,40000,100000". +Before this feature, port speed in APP DB indicates both the configured speed and the operational speed. It is OK without this feature because port operational speed must be configured speed or port operational status is down. However, this is not true with this feature. Consider following flow: + +1. Configure port speed to 100G +2. Configure advertised speed to 50G and enable auto negotiation +3. Port operational speed turns to 50G +4. Configure any port attribute, e.g mtu, portsyncd would put all port attributes to APP DB +5. `show interface status` displays port speed as 100G which is incorrect + +To overcome this issue, following changes are required: + +1. Put port operational speed to STATE DB PORT_TABLE +2. intfutil, portstat, voqutil shall be change to get port operational speed from STATE DB first. For backward compatible, intfutil, portstat, voqutil shall still get port operational speed from APP DB if port speed is not available in STATE DB or port operational state is down. + #### YANG Model Enhancements The port yang model needs to update according to DB schema change. The yang model changes of new fields are described below: @@ -440,7 +454,7 @@ In current SONiC implementation, if auto negotiation is enabled, it uses the `sp ... "autoneg": "1", "speed": "100000" -} +} ``` Will be migrated to: From 87ae10fe4c1292b7a8ff25cb68f8a2af317fa87c Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Tue, 25 Jan 2022 15:08:40 -0800 Subject: [PATCH 112/175] Update Interface-Link-bring-up-sequence.md Further review comments addressed --- .../Interface-Link-bring-up-sequence.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 982af7d21ba..dde52c092f1 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -21,11 +21,12 @@ Deterministic Approach for Interface Link bring-up sequence * [Table 2: References](#table-2-references) # Revision -| Rev | Date | Author | Change Description | -|:---:|:-----------:|:----------------------------------:|------------------------------| +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:----------------------------------:|-----------------------------------| | 0.1 | 08/16/2021 | Shyam Kumar | Initial version | 0.2 | 12/13/2021 | Shyam Kumar, Jaganathan Anbalagan | Added uses-cases, workflows -| 0.3 | 01/19/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed review-comments | +| 0.3 | 01/19/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed review-comments +| 0.4 | 01/26/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments # About this Manual @@ -76,7 +77,7 @@ Interface link bring-up sequence and workflows for use-cases around it a) Enable port on NPU (bring-up port, serdes on the NPU ; enable signals) : syncd b) Enable port on PHY (bring-up port, serdes on the PHY ; enable signals) : gbsyncd - Wait for signal to stabilize on PHY - c) Enable optical module (turn laser on/ enable tx) : xcvrd or platform bootstrap/infra + c) Enable optical module (data path initializatio, turn laser on/ enable tx) : xcvrd In boards not having PHY, #b) not needed but #a) and #c) sequence to be followed. @@ -101,13 +102,13 @@ Have a determistic approach for Interface link bring-up sequence for all interfa 2. For system with 'External' PHY: Initialize and enable PHY Tx and Rx on both line and host sides; ensure host side link is up 3. Then only perform optics data path initialization/activation/Tx enable (for CMIS complaint optical modules) and Tx enable (for SFF complaint optical modules) -# Proposal +# Plan -Recommend following this high-level work-flow sequence to accomplish the Objective: +Plan is to follow this high-level work-flow sequence to accomplish the Objective: - xcvrd to subscribe to a new field “host_tx_ready” in port table state-DB -- Orchagent will set the “host_tx_ready” to true/false based on the SET_ADMIN_STATE attribute return status to syncd/gbsyncd. (As part of SET_ADMIN_STATE attribute enable, the NPU Tx is enabled) +- Orchagent will set the “host_tx_ready” to true/false based on the SET_ADMIN_STATE attribute return status from syncd/gbsyncd. (As part of SET_ADMIN_STATE attribute enable, the NPU Tx is enabled) - xcvrd process the “host_tx_ready” value change event and do optics datapath init / de-init using CMIS API -- Recommendation is to follow this proposal for all the known interfaces types- 400G/100G/40G/25G/10G. Reason being: +- Per the discussion and agreement in sonic-chassis workgroup and OCP community, plan is to follow this proposal for all the known interfaces types- 400G/100G/40G/25G/10G. Reason being: - CMIS complaint optical modules:- All CMIS complaint optical modules will follow this approach as recommended in the CMIS spec. - SFF complaint optical modules:- @@ -145,7 +146,8 @@ Following items are not in the scope of this document. They would be taken up se - If the xcvrd goes for restart, then all the DB events will be replayed. Here the Datapath init/activate for CMIS compliant optical modules, tx-disable register set (for SFF complaint optical modules), will be a no-op if the optics is already in that state 2. syncd/gbsyncd/swss docker container restart - - Cleanup scenario - the host_tx_ready field in STATE-DB should be updated to “False” to respective ports that a PHY/NPU interface with + - Cleanup scenario - Check if the host_tx_ready field in STATE-DB need to be updated to “False” for any use-case, either in going down or coming up path + - Discuss further on the possible use-cases 3. CMIS API feature is not part of this design and the APIs will be used in this design. For CMIS HLD, Please refer to: https://github.com/Azure/SONiC/blob/9d480087243fd1158e785e3c2f4d35b73c6d1317/doc/sfp-cmis/cmis-init.md 4. Error handling of SAI attributes From c8fcff21f71cc2f1fbe5e3ab7ab4c6e93f97d4ad Mon Sep 17 00:00:00 2001 From: Akhilesh Samineni <47657796+AkhileshSamineni@users.noreply.github.com> Date: Wed, 26 Jan 2022 08:41:23 +0530 Subject: [PATCH 113/175] Updated the HLD with route and neighbor command outputs in BGP Unnumbered case (#911) *In BGP Unnumbered case, the IPv4 routes are pushed to Kernel and APPL_DB using ipv4 link-local address (169.254.0.1) as nexthops by the FRR. --- doc/ipv6/ipv6_link_local.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/ipv6/ipv6_link_local.md b/doc/ipv6/ipv6_link_local.md index 23293801a91..ea9df87b207 100644 --- a/doc/ipv6/ipv6_link_local.md +++ b/doc/ipv6/ipv6_link_local.md @@ -153,8 +153,9 @@ The below diagram shows the deployment use case. ![Deployment use case](images/bgp.jpg) -The following command shows the IPv4 routes learned via IPv6 link-local next hops on Router A: +The following command output shows the IPv4 routes learned via IPv6 link-local next hops in FRR and same IPv4 routes learned via IPv4 link-local next hops in Kernel and APPL_DB on Router A: +FRR : ``` sonic# show ip route Codes: K - kernel route, C - connected, S - static, R - RIP, @@ -165,7 +166,23 @@ Codes: K - kernel route, C - connected, S - static, R - RIP, B 192.168.0.0/24 [20/0] via fe80::5054:ff:fe03:6175, Ethernet0, 00:00:06 ``` +Kernel : +``` +192.168.0.0/24 proto bgp metric 20 + nexthop via 169.254.0.1 dev Ethernet0 weight 1 onlink +root@sonic:/home/admin# ip neigh show | grep -v eth0 +169.254.0.1 dev Ethernet24 lladdr 50:54:00:03:61:75 PERMANENT +``` +APPL_DB : +``` +root@sonic:/home/admin# sonic-db-cli APPL_DB keys NEIGH_TABLE* +1) "NEIGH_TABLE:Ethernet0:169.254.0.1" + +root@sonic:/home/admin# sonic-db-cli APPL_DB hgetall ROUTE_TABLE:192.168.0.0/24 +{'ifname': 'Ethernet0', 'nexthop': '169.254.0.1'} +root@sonic:/home/admin# +``` ## 2.2 Functional Description This document describes the functional changes required to support IPv6 link-local addresses. From 9091931ed841ff922331e49af504184beca8e1a3 Mon Sep 17 00:00:00 2001 From: Vadym Hlushko <62022266+vadymhlushko-mlnx@users.noreply.github.com> Date: Thu, 27 Jan 2022 13:34:45 +0200 Subject: [PATCH 114/175] SONiC NVGRE Tunnel HLD (#869) Signed-off-by: Vadym Hlushko --- doc/nvgre_tunnel/images/nvgre_cli_config.svg | 3 + doc/nvgre_tunnel/images/nvgre_cli_show.svg | 3 + doc/nvgre_tunnel/images/nvgre_orch.svg | 3 + .../images/nvgre_tunnel_create_uml.svg | 4 + .../images/nvgre_tunnel_delete_uml.svg | 4 + .../images/nvgre_tunnel_map_create_uml.svg | 3 + .../images/nvgre_tunnel_map_delete_uml.svg | 3 + doc/nvgre_tunnel/nvgre_tunnel.md | 448 ++++++++++++++++++ 8 files changed, 471 insertions(+) create mode 100644 doc/nvgre_tunnel/images/nvgre_cli_config.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_cli_show.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_orch.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_tunnel_create_uml.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_tunnel_delete_uml.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_tunnel_map_create_uml.svg create mode 100644 doc/nvgre_tunnel/images/nvgre_tunnel_map_delete_uml.svg create mode 100755 doc/nvgre_tunnel/nvgre_tunnel.md diff --git a/doc/nvgre_tunnel/images/nvgre_cli_config.svg b/doc/nvgre_tunnel/images/nvgre_cli_config.svg new file mode 100644 index 00000000000..309bc9cc065 --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_cli_config.svg @@ -0,0 +1,3 @@ + + +
CLI
CLI
sonic-utilities
sonic-utilities
ConfigDB
ConfigDB
OrchAgent
OrchAgent
notify
notify
Update NVGRE configuration values
Update NVGRE configuration values
NVGRE CLI config
NVGRE CLI config
execute config command
execute config...
call appropriate util script
call appropriat...
set attribute(s)
set attribute(s)
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_cli_show.svg b/doc/nvgre_tunnel/images/nvgre_cli_show.svg new file mode 100644 index 00000000000..5b43ae4dccc --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_cli_show.svg @@ -0,0 +1,3 @@ + + +
CLI
CLI
sonic-utilities
sonic-utilities
ConfigDB
ConfigDB
opt
opt
if NVGRE configuration
is needed
if NVGRE configuration...
format output
format output
NVGRE CLI show
NVGRE CLI show
execute show command
execute show co...
call appropriate util script
call appropriat...
get attribute(s)
get attribute(s)
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_orch.svg b/doc/nvgre_tunnel/images/nvgre_orch.svg new file mode 100644 index 00000000000..0d9d1efa7e3 --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_orch.svg @@ -0,0 +1,3 @@ + + +
CONFIG_DB
CONFIG_DB
ASIC_DB
ASIC_DB
NVGRETunnel
NVGRETunnel
NVGRETunnelMap
NVGRETunnelMap
Orchagent
Orchag...
nvgreorch
nvgreorch
orchdaemon
orchdaemon
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_tunnel_create_uml.svg b/doc/nvgre_tunnel/images/nvgre_tunnel_create_uml.svg new file mode 100644 index 00000000000..4cf0f3824b8 --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_tunnel_create_uml.svg @@ -0,0 +1,4 @@ + + + +
CONFIG_DB
CONFIG_DB
NvgreOrch
NvgreOrch
SAI
SAI
set configuration
set configuration
notify
notify
opt
opt
if tunnel already exist
if tunnel already exist
SysLog
SysLog
log WARNING message
log WARNING message
NVGRE tunnel add
NVGRE tunnel add
savedata
savedata
create tunnel
create tunnel
opt
opt
runtime error
runtime error
log ERROR message
log ERROR message
if SAI can't create a tunnel
if SAI can't create a tunnel
if tunnel does not exist
if tunnel does not exist
create tunnel termination
create tunnel t...
opt
opt
log ERROR message
log ERROR message
runtime error
runtime error
if SAI can't create a tunnel
termination
if SAI can't create a tunnel...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_tunnel_delete_uml.svg b/doc/nvgre_tunnel/images/nvgre_tunnel_delete_uml.svg new file mode 100644 index 00000000000..a4f6aeecf10 --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_tunnel_delete_uml.svg @@ -0,0 +1,4 @@ + + + +
CONFIG_DB
CONFIG_DB
NvgreOrch
NvgreOrch
SAI
SAI
set configuration
set configuration
notify
notify
SysLog
SysLog
NVGRE tunnel delete
NVGRE tunnel delete
clear internal cache
clear internal cache
delete tunnel
delete tunnel
opt
opt
runtime error
runtime error
log ERROR message
log ERROR message
if SAI can't delete a tunnel
if SAI can't delete a tunnel
if tunnel maps are
associated to this tunnel
if tunnel maps are...
log ERROR message
log ERROR message
orchagent exit
orchagent exit
opt
opt
if tunnel maps are not
associated to this tunnel
if tunnel maps are not...
delete tunnel termination
delete tunnel t...
runtime error
runtime error
log ERROR message
log ERROR message
if SAI can't delete a tunnel
termination
if SAI can't delete a tunnel...
opt
opt
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_tunnel_map_create_uml.svg b/doc/nvgre_tunnel/images/nvgre_tunnel_map_create_uml.svg new file mode 100644 index 00000000000..2cf0715a0c8 --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_tunnel_map_create_uml.svg @@ -0,0 +1,3 @@ + + +
CONFIG_DB
CONFIG_DB
NvgreOrch
NvgreOrch
SAI
SAI
set configuration
set configuration
notify
notify
opt
opt
if tunnel does NOT exist
if tunnel does NOT exist
SysLog
SysLog
log WARNING message
log WARNING message
NVGRE tunnel map add
NVGRE tunnel map add
if tunnel map already exist
if tunnel map already exist
savedata
savedata
create tunnel map
create tunnel m...
log WARNING message
log WARNING message
opt
opt
runtime error
runtime error
log ERROR message
log ERROR message
if SAI can't create
a tunnel map
if SAI can't create...
else
else
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/images/nvgre_tunnel_map_delete_uml.svg b/doc/nvgre_tunnel/images/nvgre_tunnel_map_delete_uml.svg new file mode 100644 index 00000000000..79af8d4cc8c --- /dev/null +++ b/doc/nvgre_tunnel/images/nvgre_tunnel_map_delete_uml.svg @@ -0,0 +1,3 @@ + + +
CONFIG_DB
CONFIG_DB
NvgreOrch
NvgreOrch
SAI
SAI
set configuration
set configuration
notify
notify
SysLog
SysLog
NVGRE tunnel map delete
NVGRE tunnel map delete
clear internal cache
clear internal cache
delete tunnel map
delete tunnel m...
opt
opt
runtime error
runtime error
log ERROR message
log ERROR message
if SAI can't delete a tunnel map
if SAI can't delete a tunnel map
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/nvgre_tunnel/nvgre_tunnel.md b/doc/nvgre_tunnel/nvgre_tunnel.md new file mode 100755 index 00000000000..3bcabdc9479 --- /dev/null +++ b/doc/nvgre_tunnel/nvgre_tunnel.md @@ -0,0 +1,448 @@ +# NVGRE tunnel in SONIC # + +## Table of Content + +- [Revision](#revision) +- [Scope](#scope) +- [Definitions/Abbreviations](#definitionsabbreviations) +- [Overview](#overview) +- [Requirements](#requirements) +- [Architecture Design](#architecture-design) +- [High-level design](#high-level-design) +- [SAI API](#sai-api) +- [CLI/YANG model Enhancements](#cli-yang-model-enhancements) +- [Warmboot and Fastboot Design Impact](#warmboot-and-fastboot-design-impact) +- [Restrictions Limitations](#restrictions-limitations) +- [Testing Requirements Design](#testing-requirements-design) +- [Open/Action items](#open-action-items) + +### Revision + +| Rev | Date | Author | Change Description | +| :---: | :-----: | :--------------: | ------------------ | +| 1.0 | 09/2021 | Vadym Hlushko | Phase 1 Design | + +### Scope + +This document provides general information about the NVGRE tunnel feature implementation in SONiC. + +### Definitions/Abbreviations + +| Abbreviation | Definition | +|--------------|---------------------------------------| +| SONiC | Software for Open Networking in Cloud | +| NVGRE | Network Virtualization using Generic Routing Encapsulation | +| VxLAN | Virtual Extensible LAN | +| VSID | Virtual Subnet Identifier | +| DB | Database | +| API | Application Programming Interface | +| SAI | Switch Abstraction Interface | +| YANG | Yet Another Next Generation | +| CLI | Command-line interface | + +### Overview + +NVGRE is a network virtualization method that uses encapsulation and tunneling to create large numbers of virtual LANs (VLANs) for subnets that can extend across dispersed data centers and layer 2 (the data link layer) and layer 3 (the network layer). The SONIC has no support of NVGRE tunnel feature and appropriate SAI implementation for it. + +From the architecture point of view the new orchagent daemon will be added to cover the NVGRE functionality. New daemon should handle the configuration taken from config DB, and call an appropriate SAI API, which will create tunnel and tunnel maps. + +### Requirements + +This section describes the SONiC requirements for NVGRE feature. + +At a high level the following should be supported: + +- User should be able to create NVGRE tunnel (L2 over L3 tunnel) +- User should be able to create VLAN to VSID mapper entries for the NVGRE tunnel +- Both VLAN and Bridge to VSID mappers should be supported by the NVGRE tunnel +- Only the decapsulation mappers supported +- YANG model should be created in order to auto-generate CLI by using the [SONiC CLI Auto-generation tool](https://github.com/Azure/SONiC/blob/master/doc/cli_auto_generation/cli_auto_generation.md). +- CLI for NVGRE tunnel + +Counters for NVGRE Tunnel are out of scope of this design document. + +### Architecture Design + +The new tables will be added to Config DB. Unless otherwise stated, the attributes are mandatory. + +#### NVGRE configDB table + +``` +NVGRE_TUNNEL|{{tunnel_name}} + "src_ip": {{ip_address}} + +NVGRE_TUNNEL_MAP|{{tunnel_name}}|{{tunnel_map_name}} + "vsid": {{vsid_id}} + "vlan": {{vlan_id}} +``` + +#### ConfigDB schemas + +``` +; Defines schema for NVGRE Tunnel configuration attributes +key = NVGRE_TUNNEL|tunnel_name ; NVGRE tunnel configuration +; field = value +src_ip = ipv4 or ipv6 ; IP source address + +;value annotations +h16 = 1*4HEXDIG +ls32 = h16 ":" h16 +dec-octet = DIGIT ; 0-9 + / %x31-39 DIGIT ; 10-99 + / "1" 2DIGIT ; 100-199 + / "2" %x30-34 DIGIT ; 200-249 +ipv4 = dec-octet "." dec-octet "." dec-octet "." dec-octet +ipv6 = 6( h16 ":" ) ls32 + / "::" 5( h16 ":" ) ls32 + / [ h16 ] "::" 4( h16 ":" ) ls32 + / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + / [ *4( h16 ":" ) h16 ] "::" ls32 + / [ *5( h16 ":" ) h16 ] "::" h16 + / [ *6( h16 ":" ) h16 ] "::" +``` + +``` +; Defines schema for NVGRE Tunnel map configuration attributes +key = NVGRE_TUNNEL|tunnel_name|tunnel_map_name ; NVGRE tunnel configuration +; field = value +vsid = DIGITS ; 1 to 16 million values +vlan = 1\*4DIGIT ; 1 to 4094 Vlan id +``` + +#### Orchestration agent + +The following orchestration agents will be added or modified. The flow diagrams are captured in a later section. + +##### Figure 1. Orchestration agents + +

+Figure 1. Orchestration agents +

+ +#### NvgreOrch + +`nvgreorch` - it is an orchestration agent that handles the configuration requests directly from ConfigDB. The `nvgreorch` is responsible for creating the tunnel and attaches encap and decap mappers. Both VLAN and Bridge tunnel maps are created for NVGRE tunnel by default, so it would be possible to apply both VLAN/VSID and Bridge/VSID map entries. + +#### Orchdaemon + +`orchdaemon` - it is the main orchestration agent, which handles all Redis DB's updates, then calls appropriate orchagent, the new `nvgreorch` should be registered inside an `orchdaemon`. + +### High-Level Design + +The following sub-modules will be modified: +* [sonic-swss](https://github.com/Azure/sonic-swss) - will be extended with the new orchestration agent for NVGRE. +* [sonic-swss-common](https://github.com/Azure/sonic-swss-common) - will be extended with the new tables for ConfigDB. +* [sonic-utilities](https://github.com/Azure/sonic-utilities) - will be extened with the new CLI. + +#### Sequence diagrams + +##### Figure 2. NVGRE Tunnel creation flow + +

+Figure 2. NVGRE Tunnel creation flow +

+ +##### Figure 3. NVGRE Tunnel Map creation flow + +

+Figure 3. NVGRE Tunnel Map creation flow +

+ +##### Figure 4. NVGRE Tunnel delete flow + +Note that deleting a tunnel requires the user to remove all the configuration that are associated with this tunnel, it will not be done for the user automatically. + +

+Figure 4. NVGRE Tunnel delete flow +

+ +##### Figure 5. NVGRE Tunnel Map delete flow + +

+Figure 5. NVGRE Tunnel Map delete flow +

+ +##### Figure 6. NVGRE Tunnel CLI config + +

+Figure 6. NVGRE Tunnel CLI config +

+ +##### Figure 7. NVGRE Tunnel CLI show + +

+Figure 7. NVGRE Tunnel CLI show +

+ +### SAI API + +The NVGRE Tunnel feature require at least `SAI 1.9` or above. + +| NVGRE component | SAI attribute | +|--------------|---------------------------------------| +| NVGRE tunnel type | SAI_TUNNEL_TYPE_NVGRE | +| Decap mapper | SAI_TUNNEL_MAP_TYPE_VSID_TO_VLAN_ID | +| Decap mapper | SAI_TUNNEL_MAP_TYPE_VSID_TO_BRIDGE_IF | +| NVGRE tunnel termination entry type | SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP | + + +### CLI/YANG model Enhancements + +#### NVGRE Tunnel YANG model + +```yang +module sonic-nvgre-tunnel { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-nvgre-tunnel"; + prefix nvgre; + + import ietf-inet-types { + prefix inet; + } + + import sonic-vlan { + prefix vlan; + } + + description "NVGRE Tunnel YANG Module for SONiC OS"; + + revision 2021-10-31 { + description + "First Revision"; + } + + container sonic-nvgre-tunnel { + + container NVGRE_TUNNEL { + + description "NVGRE_TUNNEL part of config_db.json"; + + list NVGRE_TUNNEL_LIST { + + key "tunnel_name"; + + leaf tunnel_name { + description "NVGRE Tunnel name"; + + type string { + length 1..255; + } + } + + leaf src_ip { + description "Source IP address"; + + mandatory true; + type inet:ip-address; + } + + } + /* end of NVGRE_TUNNEL_LIST */ + + } + /* end of container NVGRE_TUNNEL */ + + container NVGRE_TUNNEL_MAP { + + description "NVGRE_TUNNEL_MAP part of config_db.json"; + + list NVGRE_TUNNEL_MAP_LIST { + + key "tunnel_name tunnel_map_name"; + + leaf tunnel_name { + description "NVGRE Tunnel name"; + + type leafref { + path /nvgre:sonic-nvgre-tunnel/nvgre:NVGRE_TUNNEL/nvgre:NVGRE_TUNNEL_LIST/nvgre:tunnel_name; + } + } + + leaf tunnel_map_name { + description "NVGRE Tunnel map name"; + + type string { + length 1..255; + } + } + + leaf vlan_id { + description "VLAN identifier"; + + mandatory true; + type uint16 { + range 1..4094; + } + } + + leaf vsid { + description "Virtual Subnet Identifier"; + + mandatory true; + type uint32 { + range 0..16777214; + } + } + + } + /* end of NVGRE_TUNNEL_MAP_LIST */ + + } + /* end of container NVGRE_TUNNEL_MAP */ + + } + /* end of container sonic-nvgre-tunnel */ + +} +/* end of module sonic-nvgre-tunnel */ +``` + +#### CLI tree + +Commands summary (Phase #2): + +``` + - config nvgre-tunnel add/del --src-ip + - config nvgre-tunnel-map add/del --vlan_id --vsid + - show nvgre-tunnel + - show nvgre-tunnel-map +``` + +##### Show CLI command + +Show command should be extended in order to add "nvgre-tunnel" and "nvgre-tunnel-map" aliases: + +``` +admin@sonic:~$ show nvgre-tunnel +TUNNEL NAME SRC IP +------------- -------- +tunnel1 10.0.0.1 +tunnel2 2.2.2.2 +tunnel3 3.3.3.3 + +============================================= + +admin@sonic:~$ show nvgre-tunnel-map +TUNNEL NAME TUNNEL MAP NAME VLAN ID VSID +------------- ----------------- --------- ------ +tunnel_1 Vlan1000 1000 5000 +``` + +##### Config CLI command + +Config command should be extended in order to add "nvgre-tunnel" and "nvgre-tunnel-map" aliases: + +``` +admin@sonic:~$ config nvgre-tunnel --help +Usage: nvgre-tunnel [OPTIONS] COMMAND [ARGS]... + + NVGRE_TUNNEL part of config_db.json + +Options: + --help Show this message and exit. + +Commands: + add Add object in NVGRE_TUNNEL. + delete Delete object in NVGRE_TUNNEL. + +============================================= + +admin@sonic:~$ config nvgre-tunnel add --help +Usage: add [OPTIONS] TUNNEL_NAME + + Add object in NVGRE_TUNNEL. + +Options: + --src-ip Source IP address[mandatory] + --help Show this message and exit. + +============================================= + +admin@sonic:~$ config nvgre-tunnel-map --help +Usage: nvgre-tunnel-map [OPTIONS] COMMAND [ARGS]... + + NVGRE_TUNNEL_MAP part of config_db.json + +Options: + --help Show this message and exit. + +Commands: + add Add object in NVGRE_TUNNEL_MAP. + delete Delete object in NVGRE_TUNNEL_MAP. + +============================================= + +admin@sonic:~$ config nvgre-tunnel-map add --help +Usage: add [OPTIONS] TUNNEL_NAME TUNNEL_MAP_NAME + + Add object in NVGRE_TUNNEL_MAP. + +Options: + --vlan-id VLAN identifier[mandatory] + --vsid Virtual Subnet Identifier[mandatory] + --help Show this message and exit. +``` + +#### Config DB Enhancements + +The ConfigDB will be extended with next objects: + +```json +{ + "NVGRE_TUNNEL": { + "tunnel1": { + "src_ip": "2.2.2.2" + } + }, + "NVGRE_TUNNEL_MAP": { + "tunnel1|Vlan2000": { + "vlan_id": "2000", + "vsid": "2000", + } + } +} +``` + +### Warmboot and Fastboot Design Impact + +No impact on Warmboot and Fastboot features. + +### Restrictions/Limitations + +The number of the tunnels are not limited by SONiC, but if ASIC vendor reach the max resources, the SAI will return an error, when the user will try to create a new tunnel or tunnel map and orchagent will abort. + +### Testing Requirements/Design + +The tests will be implemented under the VS environment and will be placed - [sonic-swss/tests](https://github.com/Azure/sonic-swss/tree/master/tests) sub-module. + +#### Unit Test cases + +VS test cases: +- create NVGRE Tunnel + - create a tunnel with invalid source IP address + - create a tunnel with valid params +- remove NVGRE Tunnel + - remove existing tunnel + - remove unexisting tunnel + - remove a tunel with which have associated with a tunel maps +- create NVGRE Tunnel Map + - create a tunnel map with invalid VLAN identifier + - create a tunnel map with invalid VSID number + - create a tunnel map with unexisting NVGRE Tunnel name + - create valid tunnel map +- remove NVGRE Tunnel Map + - remove existing tunnel + - remove unexisting tunnel + +#### System Test cases + +NVGRE decap: +- apply NVGRE config +- send encapsulated traffic +- validate if decapsulation processed correctly + +### Open/Action items From c272efa5a54bb79aad8e47ece84b4240f24be656 Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Fri, 28 Jan 2022 14:11:42 -0800 Subject: [PATCH 115/175] Update Interface-Link-bring-up-sequence.md Addressed further review comments --- .../Interface-Link-bring-up-sequence.md | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index dde52c092f1..db63a672ea5 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -13,7 +13,8 @@ Deterministic Approach for Interface Link bring-up sequence * [Problem Definition](#problem-definition) * [Background](#background) * [Objective](#objective) - * [Proposal](#proposal) + * [Plan](#plan) + * [Pre-requisite](#pre-requisite) * [Proposed Work-Flows](#proposed-work-flows) # List of Tables @@ -27,6 +28,7 @@ Deterministic Approach for Interface Link bring-up sequence | 0.2 | 12/13/2021 | Shyam Kumar, Jaganathan Anbalagan | Added uses-cases, workflows | 0.3 | 01/19/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed review-comments | 0.4 | 01/26/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments +| 0.5 | 01/28/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments # About this Manual @@ -52,6 +54,7 @@ Interface link bring-up sequence and workflows for use-cases around it | **Document** | **Location** | |---------------------------------------------------------|---------------| +| CMIS v4 | [QSFP-DD-CMIS-rev4p0.pdf](http://www.qsfp-dd.com/wp-content/uploads/2019/05/QSFP-DD-CMIS-rev4p0.pdf) | | CMIS v5 | [CMIS5p0.pdf](http://www.qsfp-dd.com/wp-content/uploads/2021/05/CMIS5p0.pdf) | @@ -119,11 +122,20 @@ Plan is to follow this high-level work-flow sequence to accomplish the Objective - Additionally provides uniform workflow (from SONiC NOS) across all interface types with or without module presence. - This synchronization will also benefit SFP+ optical modules as they are "plug N play" and may not have quiescent functionality. (xcvrd can use the optional 'soft tx disable' ctrl reg to disable the tx) +# Pre-requisite + +As mentioned above in 'Background' and 'Plan' sections, need to follow specified bring-up sequence. +Work flows are designed considering SONiC NOS operating in sync mode. + +In case SONiC NOS operates in async mode, then expected behavior is - the return status of the set ADMIN_STATE attribute update in ASIC-DB (syncd/GBsyncd) will be treated to set the host_tx_ready in Orchagent. + # Proposed Work-Flows + Please refer to the flow/sequence diagrams which covers the following required use-cases - Transceiver initialization - admin enable configurations - admin disable configurations + - No transceiver present # Transceiver Initialization (at platform bootstrap layer) @@ -139,6 +151,11 @@ Please refer to the flow/sequence diagrams which covers the following required ![LC boot-up sequence - 'admin disable' Config gets applied](https://user-images.githubusercontent.com/69485234/147166884-92c9af48-2d64-4e67-8933-f80531d821b4.png) +# No transceiver present +if transceiver is not present: + - All the workflows mentioned above will reamin same ( or get exercised) till host_tx_ready field update + - xcvrd will not perform any action on receiving host_tx_ready field update + # Out of Scope Following items are not in the scope of this document. They would be taken up separately @@ -157,4 +174,3 @@ Following items are not in the scope of this document. They would be taken up se c) A propabale way to handle the failure is to set a error handling attribute to respective container syncd/GBsyncd with attribute that is failed. The platform layer knows the error better and it will try to recover. - From faf87310154cd56c4f0b49ca94a9e353f8f1a7b0 Mon Sep 17 00:00:00 2001 From: Kerry Meyer Date: Mon, 31 Jan 2022 10:42:42 -0800 Subject: [PATCH 116/175] HLD for the SONiC Management Framework "show tech-support" command (#756) This initial version of the SONiC Management Framework "show tech-support" command describes the SONiC Management Framework interface for initiating the collection of technical support information. The specification describes the associated Yang model and flow of control for relaying the command to the SONiC host and receiving a completion status and the location of the resulting techsupport "bundle". --- ...nagement Framework Show Techsupport HLD.md | 379 ++++++++++++++++++ doc/mgmt/images/showtech-flow-diagram.JPG | Bin 0 -> 113683 bytes 2 files changed, 379 insertions(+) create mode 100644 doc/mgmt/SONiC Management Framework Show Techsupport HLD.md create mode 100644 doc/mgmt/images/showtech-flow-diagram.JPG diff --git a/doc/mgmt/SONiC Management Framework Show Techsupport HLD.md b/doc/mgmt/SONiC Management Framework Show Techsupport HLD.md new file mode 100644 index 00000000000..f2b3061ddf9 --- /dev/null +++ b/doc/mgmt/SONiC Management Framework Show Techsupport HLD.md @@ -0,0 +1,379 @@ +# Show Techsupport +Diagnostic information aggregated presentation +# High Level Design Document +#### Rev 0.1 +# Table of Contents + + - [List of Tables](#list-of-tables) + - [Revision](#revision) + - [About this Manual](#about-this-manual) + - [Scope](#scope) + - [Definition/Abbreviation](#definition-abbreviation) + - [1 Feature Overview](#1-feature-overview) + * [1.1 Requirements](#11-requirements) + + [1.1.1 Functional Requirements](#111-functional-requirements) + + [1.1.2 Configuration and Management Requirements](#112-configuration-and-management-requirements) + + [1.1.3 Scalability Requirements](#113-scalability-requirements) + + [1.1.4 Warm Boot Requirements](#114-warm-boot-requirements) + * [1.2 Design Overview](#12-design-overview) + + [1.2.1 Basic Approach](#121-basic-approach) + + [1.2.2 Container](#122-container) + + [1.2.3 SAI Overview](#123-sai-overview) + - [2 Functionality](#2-functionality) + * [2.1 Target Deployment Use Cases](#21-target-deployment-use-cases) + * [2.2 Functional Description](#22-functional-description) + - [3 Design](#3-design) + * [3.1 Overview](#31-overview) + * [3.2 DB Changes](#32-db-changes) + + [3.2.1 CONFIG DB](#321-config-db) + + [3.2.2 APP DB](#322-app-db) + + [3.2.3 STATE DB](#323-state-db) + + [3.2.4 ASIC DB](#324-asic-db) + + [3.2.5 COUNTER DB](#325-counter-db) + * [3.3 Switch State Service Design](#33-switch-state-service-design) + + [3.3.1 Orchestration Agent](#331-orchestration-agent) + + [3.3.2 Other Process](#332-other-process) + * [3.4 SyncD](#34-syncd) + * [3.5 SAI](#35-sai) + * [3.6 User Interface](#36-user-interface) + + [3.6.1 Data Models](#361-data-models) + + [3.6.2 CLI](#362-cli) + - [3.6.2.1 Configuration Commands](#3621-configuration-commands) + - [3.6.2.2 Show Commands](#3622-show-commands) + - [3.6.2.3 Debug Commands](#3623-debug-commands) + - [3.6.2.4 IS-CLI Compliance](#3624-is-cli-compliance) + + [3.6.3 REST API Support](#363-rest-api-support) + - [4 Flow Diagrams](#4-flow-diagrams) + * [4.1 Show Techsupport Process Flow](#41-show-techsupport-process-flow) + - [5 Error Handling](#5-error-handling) + - [6 Serviceability and Debug](#6-serviceability-and-debug) + - [7 Warm Boot Support](#7-warm-boot-support) + - [8 Scalability](#8-scalability) + - [9 Unit Test](#9-unit-test) + - [10 Internal Design Information](#10-internal-design-information) + * [10.1 Overview](#101-overview) + * [10.2 Management Framework Context](#102-management-framework-context) + * [10.3 Host Context](#103-host-context) + +
Table of contents generated with markdown-toc + +# List of Tables + +## Revision +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.1 | 10/06/2019 | Kerry Meyer | Initial version | + +# About this Manual +This manual describes the user interface for obtaining aggregated diagnostic information for the SONiC subsystem via the Management Framework infrastructure. +# Scope +The scope of the information contained in this document is the high level design for the "show techsupport" command implementation under the control of the Management Framework infrastructure. It is intended to cover the general approach and method for providing a flexible collection of diagnostic information items. It also considers the basic mechanisms to be used for obtaining the various types of information to be aggregated. It does not address specific details for collection of all supported classes of information. + +# Definition/Abbreviation + +# 1 Feature Overview + +Provide Management Framework functionality to process the "show techsupport" command: + - Create an aggregated file containing the information items needed for analysis and diagnosis of problems occurring during switch operations. + - Support reduction of aggregated log file information via an optional "--since" parameter specifying the desired logging start time. + +NOTE: The underlying feature for which this Management Framework feature provides "front end" client interfaces is unchanged by the addition of these interfaces. (The "since " option available through these interfaces, however, is restricted to the IETF/YANG date/time format.) Please refer to the following document for a description of the "show techsupport" base feature: + +https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md#troubleshooting-commands + +DEPENDENCY ON SONIC-HOSTSERVICES: + +For details, Please refer to: + +[3.3.2 Other Process](#332-other-process) + + +## 1.1 Requirements + +### 1.1.1 Functional Requirements + +Provide a Management Framework based interface for the "show tech-support" command. + +### 1.1.2 Configuration and Management Requirements +Provide the ability to invoke the command via the following client interfaces: + + - Management Framework CLI (same syntax as the existing Click-based + API except for tighter restriction of the "DateTime" format to + conform with the Yang/IETF DateTime standard) + - REST API + - gNOI + +(See Section 3 for additional details.) + +### 1.1.3 Scalability Requirements + +Time and storage space constraints: The large number of information items collected and the potentially large size of some of the items (e.g. interface information display in a large system) present an exposure to the risk of long processing times and significant demands on disk storage space. The Management Framework interface invokes the same command used for the Click-based interface. It adds no significant additional overhead or processing time. The storage space requirements are unchanged. +### 1.1.4 Warm Boot Requirements +N/A +## 1.2 Design Overview +### 1.2.1 Basic Approach +This feature will be implemented using the Management Framework infrastructure supplemented with customized access mechanisms for handling "non-DB" data items. + +### 1.2.2 Container +The user interface (front end) portion of this feature is implemented within the Management Framework container. + +### 1.2.3 SAI Overview +N/A (non-hardware feature) + +# 2 Functionality +## 2.1 Target Deployment Use Cases +This feature provides a quick and simple mechanism for network administrators or other personnel with no detailed knowledge of switch internal details to gather an extensive set of information items by using a single command. These items provide critical information to help development and sustaining engineering teams in the analysis and debugging of problems encountered in deployment and test environments. +## 2.2 Functional Description +The set of items to be gathered for a given software release is defined by the development team. It is specified in a way that enables run-time access to the desired set of information items to be collected. The definition of the set of information items to be collected includes specification of the access function to be used for each item in the list. Each access function gathers a subset of the required information, formats it as needed, and packs it into the output file. The location of the resulting output file is provided to the requesting client at the completion of command execution. + +The output file name has the following form: + +` +/var/dump/sonic_dump_sonic_YYYYMMDD_HHMMSS.tar.gz +` + +Example: + +`/var/dump/sonic_dump_sonic_20191118_221625.tar.gz +` +See section 3.6.2.2 for an explanation of the output file name format. + +To view the contents of the file, the user must copy it to a local file in the client file system. If the file is to be extracted within the directory to which it is copied, the directory should have at least 50 MB of available space. To extract the file inside of the directory to which it has been copied while displaying a list of output files, the following command can be used: + +` +tar xvzf filename.tar.gz +` +The files are extracted to a directory tree, organized based on the type of information contained in the files. Example file categories for which sub-directories are provided in the output file tree include: + +- log files ("log" directory ) +- Linux configuration files ("etc" directory) +- generic application "dump" output ("dump" directory) +- network hardware driver information ("sai" directory) +- detailed information on various processes ("proc" directory). + +To extract the file contents to an alternate location, the following form of the "tar" command can be used: + +` + tar xvzf filename.tar.gz -C /path/to/destination/directory +` +Some of the larger "extracted" files are compressed in gzip format. This includes log files and core files and also includes other files containing a large amount of output (e.g. a dump of all BGP tables). These files have a ".gz" file type. They can be extracted using: + +` +gunzip +` + + +# 3 Design +## 3.1 Overview +The "show techsupport" command causes invocation of an RPC sent from the management framework to a process in the host to cause collection of a list of flexibly defined sets of diagnostic information (information "items"). The collected list of items is stored in a compressed "tar" file with a unique name. The command output provides the location of the resulting compressed tar file. + +The "since" option can be used, if desired, to restrict the time scope for log files and core files to be collected. This option is passed to the host process for use during invocation of the applicable information gathering sub-functions. + +## 3.2 DB Changes +N/A +### 3.2.1 CONFIG DB +### 3.2.2 APP DB +### 3.2.3 STATE DB +### 3.2.4 ASIC DB +### 3.2.5 COUNTER DB + +## 3.3 Switch State Service Design +N/A +### 3.3.1 Orchestration Agent +### 3.3.2 Other Process +The "show techsupport" feature requires RPC support in a process running within the host context. The host process handling the RPC is responsible for dispatching "show techsupport" requests from the management framework container to trigger allocation of an output file, gathering and packing of the required information into the output file, and sending a response to the management framework RPC agent to specify the name and path of the output file. + +To enable this functionality, The "sonic-hostservices" service must be operational in the host context. If the "Active:" status for the service is not "active" within the host, the user must activate it before attempting to use the Management Framework front end for the "show techsupport" facility. + +The status can be queried from the host via: + +` +systemctl status sonic-hostservices +` + +The service can be activated via: + +` +systemctl start sonic-hostservices +` + +## 3.4 SyncD +N/A + +## 3.5 SAI +N/A + +## 3.6 User Interface +### 3.6.1 Data Models +The following Sonic Yang model is used for implementation of this feature: + +```module: sonic-show-techsupport + + rpcs: + +---x sonic-show-techsupport-info + +---w input + | +---w date? yang:date-and-time + +--ro output + +--ro output-filename? string +``` + + + +### 3.6.2 CLI +#### 3.6.2.1 Configuration Commands +N/A +#### 3.6.2.2 Show Commands + +Command syntax summary: + +` +show techsupport [since ] +` + +Command Description: + +Gather information for troubleshooting. Display the name of a file containing the resulting group of collected information items in a compressed "tar" file. + + +Syntax Description: + +| Keyword | Description | +|:--------------|:----------- | +| since | This option uses a text string containing the desired starting Date/Time for collected log files and core files. The format of the Date/Time in the string is defined by the Yang/IETF date-and-time specification (REF http://www.netconfcentral.org/modules/ietf-yang-types, based on http://www.ietf.org/rfc/rfc6020.txt). If "since is specified, this value is passed to the host process for use during invocation of the applicable log/core file gathering sub-functions.| + +Command Mode: User EXEC + +Output format example and summary: + +``` +Example: + +Output stored in: /var/dump/sonic_dump_sonic_20191008_082312.tar.gz + +-------------------------------------------------- + +Output file name sub-fields are defined a follows: + +- YYYY = Year +- MM = Month (numeric) +- DD = Day of the Month +- HH = hour of the current time (based on execution of the Linux "**date**" command) at the start of command execution +- MM = minute of the current time (based on execution of the Linux "**date**" command) at the start of command execution +- SS = second of the current time (based on execution of the Linux "**date**" command) at the start of command execution +``` + +Command execution example (basic command): + +``` +sonic# show techsupport + +Output stored in: /var/dump/sonic_dump_sonic_20191008_082312.tar.gz + +``` +Command execution Example (using the "since" keyword/subcommand): + +``` +sonic# show tech-support + since Collect logs and core files since a specified date/time + | Pipe through a command + + +sonic# show tech-support since + String date/time in the format: + + "YYYY-MM-DDTHH:MM:SS[.ddd...]Z" or + "YYYY-MM-DDTHH:MM:SS[.ddd...]+hh:mm" or + "YYYY-MM-DDTHH:MM:SS[.ddd...]-hh:mm" Where: + + YYYY = year, MM = month, DD = day, + T (required before time), + HH = hours, MM = minutes, SS = seconds, + .ddd... = decimal fraction of a second (e.g. ".323") + Z indicates zero offset from local time + +/- hh:mm indicates hour:minute offset from local time + +sonic# show tech-support since 2019-11-27T22:02:00Z +Output stored in: /var/dump/sonic_dump_sonic_20191127_220334.tar.gz +``` +Command execution example invocation via REST API: + +``` +REST request via CURL: + +curl -X POST "https://10.11.68.13/restconf/operations/sonic-show-techsupport:sonic-show-techsupport-info" -H "accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d "{ \"sonic-show-techsupport:input\": { \"date\": \"2019-11-27T22:02:00.314+03:08\" }}" + +Request URL: + +https://10.11.68.13/restconf/operations/sonic-show-techsupport:sonic-show-techsupport-info + +Response Body: + +{ + "sonic-show-techsupport:output": { + "output-filename": "/var/dump/sonic_dump_sonic_20191128_013141.tar.gz" + } +} +``` + +Command execution example invocation via gNOI API: + +``` +root@sonic:/usr/sbin# ./gnoi_client -module Sonic -rpc showtechsupport -jsonin "{\"input\":{\"date\":\"2019-11-27T22:02:00Z\"}}" -insecure +Sonic ShowTechsupport +{"sonic-show-techsupport:output":{"output-filename":"/var/dump/sonic_dump_sonic_20191202_194856.tar.gz"}} +``` + +NOTE: See section 3.6.1 for a description of the limitations of the current implementation. A supplementary capability to transfer the tech support file and other diagnostic information files to the client via the Management Framework interface is highly desirable for a future release. + +#### 3.6.2.3 Debug Commands +N/A +#### 3.6.2.4 IS-CLI Compliance +The current Management Framework implementation differs from the IS-CLI. + + Instead of dumping the technical support information to the output buffer, this implementation dumps the information to a compressed "tar" file and sends the name of the file to the output buffer. This implementation matches the current SONiC host implementation. A supplementary capability to enable transfer of the specified file to the client is highly desirable for full functionality of this command when using a REST API or gNMI/gNOI client interface. Without this capability, it is necessary to open a shell on the host and use the SONiC host CLI interface to transfer the file. + +### 3.6.3 REST API Support +REST API support is provided. The REST API corresponds to the SONiC Yang model described in section 3.6.1. + +# 4 Flow Diagrams +## 4.1 Show Techsupport Process Flow +![ShowTechsupport process flow](showtech_flow_diagram.jpg) + +# 5 Error Handling +N/A + +# 6 Serviceability and Debug +Any errors encountered during execution of the "show tech-support" command that prevent retrieval or saving of information are reported in the command output at completion of the operation. + +# 7 Warm Boot Support +N/A + +# 8 Scalability +Refer to section 1.1.3 + +# 9 Unit Test + +| Case | Trigger | Result | +|:-----------|:--------|:-------| +| Basic command execution | Execute the "show techsupport" command with no parameters. | Confirm that the command is accepted without errors and a "result" file name is returned. Confirm that the result file contains the expected set of items. (Examine/expand the contents of the file to ensure that the top level directory tree is correct and that the number of sub-files within the tar file is correct.)| +"since" option (postive test case) | Execute the command with the "--since" TEXT option with a valid date string specifying a time near the end of one of the unfiltered output items from the first test.| Same as the "Basic command execution" case. Additionally, confirm that the expected time filtering has occurred by examining one of the affected sub-files.| +"since" option (negative test case #1)|Execute the command with the "--since" TEXT option with an invalid date string.|Verify that an error is returned.| +"since" option (negative test case #2)|Execute the command with the "--since" TEXT option with no date string.|Verify that an error is returned.|Execute the command with the "--since" option with no date string.| Verify that an error is returned.| + + + + + +# 10 Internal Design Information +Please refer to the diagram in Section 4.1, referenced below: + +[4.1 Show Techsupport Process Flow](#41-show-techsupport-process-flow) + +## 10.1 Overview +The Management Framework container (a Docker container) uses the SONiC D-Bus RPC mechanism specified in "[SONiC Docker to Host communication](https://github.com/mikelazar/SONiC/blob/69bb868dec98fc05b8b046f0925ca2e89604c49a/doc/mgmt/Docker%20to%20Host%20communication.md)" to trigger execution of the "generate_dump" Bash script on the SONiC host and to receive a response providing the result. + +## 10.2 Management Framework Context + Execution in the SONiC Management Framework docker of the "show tech-support" CLI command or the equivalent REST/gNOI invocation causes the corresponding "actioner" script to be run from the context of the Management Framework docker. This script invokes the REST API generated from the "show tech-support" Yang definition. The corresponding API handler function, registered as a SONiC D-Bus client, initiates an asynchronous D-Bus host query and relays the response, containing the location of a "techsupport bundle" file if execution is successful, back to the Management Framework interface (CLI, REST, or gNOI) from which the request was received. (In the event of an error, it instead returns the error message received from the "show techsupport" servlet running within the context of the server process for the SONiC D-Bus host services object.) + +## 10.3 Host Context +Within the SONiC host context, execution of the "show techsupport" command is initiated when the SONiC D-Bus host facility dispatches a request received from the Management Framework docker by invoking a script (servlet) registered with the SONiC D-Bus host server for handling of the "show techsupport" command. This servlet invokes the "generate_dump" Bash script, spawning a process that collects a "bundle" of items providing diagnostic information for processes running on the switch, packs the collected information into a compressed .tar file, and returns the location of the resulting file to the "show techsupport" D-Bus servlet script on successful completion. (In the event of an error, it instead returns an error message describing the error.) The servlet, via the SONiC host services D-Bus server, then sends the resulting RPC response back to the "show techsupport" client in the SONiC Management Framework docker via the SONic D-Bus RPC infrastructure. diff --git a/doc/mgmt/images/showtech-flow-diagram.JPG b/doc/mgmt/images/showtech-flow-diagram.JPG new file mode 100644 index 0000000000000000000000000000000000000000..74e0356fecdbf3d75478373a0160783fdf483735 GIT binary patch literal 113683 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:JpsN(T{CtZlDN(OMD-`YjHA7?hEjMozK!O<0? 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 s Date: Wed, 2 Feb 2022 12:44:48 -0800 Subject: [PATCH 117/175] Update Interface-Link-bring-up-sequence.md Added additional work-flow (Ability to enable/disable this feature) --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index db63a672ea5..a7674a72770 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -29,6 +29,7 @@ Deterministic Approach for Interface Link bring-up sequence | 0.3 | 01/19/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed review-comments | 0.4 | 01/26/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments | 0.5 | 01/28/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments +| 0.6 | 02/02/2022 | Shyam Kumar | Added feature-enablement workflow # About this Manual @@ -132,11 +133,25 @@ In case SONiC NOS operates in async mode, then expected behavior is - the return # Proposed Work-Flows Please refer to the flow/sequence diagrams which covers the following required use-cases + - Enabling this feature - Transceiver initialization - admin enable configurations - admin disable configurations - No transceiver present +# Feature enablement + This feature (optics Interface Link bring-up sequence) would be enabled on per platform basis. + There could be cases where vendor(s)/platform(s) may take time to shift from existing codebase to the model (work-flows) described in this document. + In order to avoid any breakage and ensure gradual migration to this model, there would be new config to enable/disable this feature. + High-Level workflow: + 1. Have a new field for this 'link_bringup_sequence' feature in config file + 2. By default it would be set to FALSE + 3. xcvrd to subscribe to state-change of this feature + 4. Platform while booting up, will set this feature to TRUE (as part of platform bootstrap layer) + 5. xcvrd on receving state-change notification of this feature, would act accordingly i.e. + - if the state is found as FALSE, ignore host_tx_ready field state + - if the state is found as TRUE, register to host_tx_ready field update notifications + # Transceiver Initialization (at platform bootstrap layer) From 4a39c0845ceee1fc1cde16fdbf29e5af95d13fee Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Wed, 2 Feb 2022 17:41:10 -0800 Subject: [PATCH 118/175] Update Interface-Link-bring-up-sequence.md Added Sequence diagram (Workflow) to enable/disable this feature --- .../Interface-Link-bring-up-sequence.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index a7674a72770..4ef3da945ee 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -142,20 +142,17 @@ Please refer to the flow/sequence diagrams which covers the following required # Feature enablement This feature (optics Interface Link bring-up sequence) would be enabled on per platform basis. There could be cases where vendor(s)/platform(s) may take time to shift from existing codebase to the model (work-flows) described in this document. - In order to avoid any breakage and ensure gradual migration to this model, there would be new config to enable/disable this feature. - High-Level workflow: - 1. Have a new field for this 'link_bringup_sequence' feature in config file - 2. By default it would be set to FALSE - 3. xcvrd to subscribe to state-change of this feature - 4. Platform while booting up, will set this feature to TRUE (as part of platform bootstrap layer) - 5. xcvrd on receving state-change notification of this feature, would act accordingly i.e. - - if the state is found as FALSE, ignore host_tx_ready field state - - if the state is found as TRUE, register to host_tx_ready field update notifications - + In order to avoid any breakage and ensure gradual migration of different platforms/vendors to this model, there would be new field (flag) in xcvrd to enable/disable this feature. + When xcvrd spawns on LC/board, it would invoke platform plugin to check with the platform (hwsku) whether this feature is yet supported on underlying platform (board/LC) or not + + Workflow : + ![Enabling 'Interface link bring-up sequence' feature(3)](https://user-images.githubusercontent.com/69485234/152266723-050377ce-d4de-4c67-a405-5acc66474d46.png) + + # Transceiver Initialization (at platform bootstrap layer) - ![LC boot-up sequence - optics INIT (platform bootstrap)](https://user-images.githubusercontent.com/69485234/147166795-5665670d-dd2b-4b6f-976c-eabcc65d5448.png) +![LC boot-up sequence - optics INIT (platform bootstrap)](https://user-images.githubusercontent.com/69485234/152261613-e20dcda9-2adc-42aa-a1f1-4b8a47dd32af.png) # Applying 'interface admin startup' configuration From fdc4e1534697de7f2b0f5bba16670e099efefaee Mon Sep 17 00:00:00 2001 From: jaganbal-a <97986478+jaganbal-a@users.noreply.github.com> Date: Wed, 2 Feb 2022 23:43:42 -0500 Subject: [PATCH 119/175] Update Interface-Link-bring-up-sequence.md (#3) Added breakout handling section. --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 4ef3da945ee..3f26a27d697 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -2,7 +2,7 @@ Deterministic Approach for Interface Link bring-up sequence # High Level Design Document -#### Rev 0.3 +#### Rev 0.7 # Table of Contents * [List of Tables](#list-of-tables) @@ -30,6 +30,7 @@ Deterministic Approach for Interface Link bring-up sequence | 0.4 | 01/26/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments | 0.5 | 01/28/2022 | Shyam Kumar, Jaganathan Anbalagan | Addressed further review-comments | 0.6 | 02/02/2022 | Shyam Kumar | Added feature-enablement workflow +| 0.7 | 02/02/2022 | Jaganathan Anbalagan | Added Breakout Handling # About this Manual @@ -130,6 +131,11 @@ Work flows are designed considering SONiC NOS operating in sync mode. In case SONiC NOS operates in async mode, then expected behavior is - the return status of the set ADMIN_STATE attribute update in ASIC-DB (syncd/GBsyncd) will be treated to set the host_tx_ready in Orchagent. +# Breakout Handling + - The new 'host_tx_ready' field of Port table in state-DB is created for every interface . + - Xcvrd processes the 'host_tx_ready' change event and is responsible to disable Tx/laser for all optical lanes or respective optical lane that belongs to the interface in case of breakout. + - Currently the logical mapping between the interface and optical lane is not present in xcvrd. Creating this logical mapping in xcvrd will address breakout interface handling. + # Proposed Work-Flows Please refer to the flow/sequence diagrams which covers the following required use-cases From 1bdd505e6a5d634d0746cf0454043a76745bdf5d Mon Sep 17 00:00:00 2001 From: Shyam <69485234+shyam77git@users.noreply.github.com> Date: Wed, 2 Feb 2022 20:50:07 -0800 Subject: [PATCH 120/175] Update Interface-Link-bring-up-sequence.md Updated 'Table of Contents' with 'Breakout handling ' item --- doc/sfp-cmis/Interface-Link-bring-up-sequence.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md index 3f26a27d697..aef89584627 100644 --- a/doc/sfp-cmis/Interface-Link-bring-up-sequence.md +++ b/doc/sfp-cmis/Interface-Link-bring-up-sequence.md @@ -15,6 +15,7 @@ Deterministic Approach for Interface Link bring-up sequence * [Objective](#objective) * [Plan](#plan) * [Pre-requisite](#pre-requisite) + * [Breakout handling](#breakout-handling) * [Proposed Work-Flows](#proposed-work-flows) # List of Tables From e1744f1ff05916d2b61b429f67e569fb3e29d0a6 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com> Date: Mon, 7 Feb 2022 18:37:36 +0800 Subject: [PATCH 121/175] Adjust system health HLD for SYSTEM READY feature (#930) For SYSTEM READY feature. Currently, there is a booting stage in system health service to indicate that the system is loading SONiC component. This booting stage is no longer needed because SYSTEM READY feature will treat that stage as system "NOT READY". --- doc/system_health_monitoring/system-health-HLD.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/system_health_monitoring/system-health-HLD.md b/doc/system_health_monitoring/system-health-HLD.md index a5da35d903f..25b11be2f65 100644 --- a/doc/system_health_monitoring/system-health-HLD.md +++ b/doc/system_health_monitoring/system-health-HLD.md @@ -148,12 +148,14 @@ Considering that different vendors platform may have different LED color capabil } ``` +The field "booting" is deprecated because there is no booting stage anymore. For backward compatible, user can still configure this field but it won't take effect. + ## 2. System health monitor service business logic System health monitor daemon will run on the host, and periodically (every 60 seconds) check critical services, processes status, output of the command "monit summary", PSU, Fan, and thermal status which is stored in the state DB. If anything is abnormal, system status LED will be set to fault status. When fault condition relieved, system status will be set to normal status. -Since system health is depending on Monit service, it shall start after Monit service. Before the switch boot up finish, the system health monitoring service shall get the monit service startup delay and make sure monit service run first. +System health service shall start after database.service and updategraph.service. Monit service has a default 300 seconds start delay, system health service shall not wait for Monit service as Monit service only monitors part of the system. But system health service shall treat system as "Not OK" until Monit service start to work. Empty FEATURE table will be considered as fault condition. A service whose critical_processes file cannot be parsed will be considered as fault condition. Empty or absence of critical_processes file is not a fault condition and shall be skipped. @@ -163,7 +165,6 @@ Incomplete data in the DB will also be considered as fault condition, e.g., PSU Monit, thermalctld and psud will raise syslog when fault condition encountered, so system health monitor will only generate some general syslog on these situation to avoid redundant. For example, when fault condition meet, "system health status change to fault" can be print out, "system health status change to normal" when it recovered. -this service will be started after system boot up(after database.service and updategraph.service). ## 3. System health data in redis database From 66277d7344541d30c5aa2f2e14ee150651cf1730 Mon Sep 17 00:00:00 2001 From: davidpil2002 <91657985+davidpil2002@users.noreply.github.com> Date: Tue, 8 Feb 2022 10:55:03 +0200 Subject: [PATCH 122/175] Password Hardening HLD (#874) --- doc/passw_hardening/chage.JPG | Bin 0 -> 23269 bytes doc/passw_hardening/hld_password_hardening.md | 843 ++++++++++++++++++ doc/passw_hardening/passh_arc_sonic.jpg | Bin 0 -> 27790 bytes doc/passw_hardening/ph_diagram.jpg | Bin 0 -> 24820 bytes doc/passw_hardening/sonic-passwh.yang | 92 ++ 5 files changed, 935 insertions(+) create mode 100644 doc/passw_hardening/chage.JPG create mode 100644 doc/passw_hardening/hld_password_hardening.md create mode 100644 doc/passw_hardening/passh_arc_sonic.jpg create mode 100644 doc/passw_hardening/ph_diagram.jpg create mode 100644 doc/passw_hardening/sonic-passwh.yang diff --git a/doc/passw_hardening/chage.JPG b/doc/passw_hardening/chage.JPG new file mode 100644 index 0000000000000000000000000000000000000000..43ea4159fd65a1cd1ccb463c94718abc50aa23a3 GIT binary patch literal 23269 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 kP4=LI3%jsjG!WkUo1EY1{Fa^HE9Table of Content + + +* 1. [Table of Content](#TableofContent) + * 1.1. [Revision](#Revision) + * 1.2. [Scope](#Scope) + * 1.3. [Definitions/Abbreviations](#DefinitionsAbbreviations) + * 1.4. [Overview](#Overview) + * 1.5. [Requirements](#Requirements) + * 1.6. [Architecture Design](#ArchitectureDesign) + * 1.7. [High-Level Design](#High-LevelDesign) + * 1.7.1. [Flow description:](#Flowdescription:) + * 1.7.2. [Password Hardening Constrains](#PasswordHardeningConstrains) + * 1.8. [Init Flow](#InitFlow) + * 1.8.1. [Compilation](#Compilation) + * 1.8.2. [dependencies](#dependencies) + * 1.8.3. [Feature default](#Featuredefault) + * 1.9. [SAI API](#SAIAPI) + * 1.10. [Configuration and management](#Configurationandmanagement) + * 1.10.1. [PASSWH configDB table](#PASSWHconfigDBtable) + * 1.10.2. [ConfigDB schemas](#ConfigDBschemas) + * 1.10.3. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) + * 1.10.4. [Config DB Enhancements](#ConfigDBEnhancements) + * 1.11. [Warmboot and Fastboot Design Impact](#WarmbootandFastbootDesignImpact) + * 1.12. [Restrictions/Limitations](#RestrictionsLimitations) + * 1.13. [Upgrade Flow](#UpgradeFlow) + * 1.14. [Test Plan](#TestPlan) + * 1.14.1. [Unit Test cases](#UnitTestcases) + * 1.14.2. [System Test cases](#SystemTestcases) + * 1.15. [3rd Party Components](#rdPartyComponents) + * 1.15.1. [pam-cracklib](#pam-cracklib) + * 1.15.2. [PW Age/History](#PWAgeHistory) + * 1.15.3. [PW History](#PWHistory) + + + + + + +### 1.1. Revision +| Rev | Date | Author | Change Description | +| :---: | :-----: | :--------------: | ------------------ | +| 0.1 | 11/2020 | David Pilnik | Phase 1 Design | + +### 1.2. Scope + +This password hardening hld doc described the requirements, architecture and configuration details of password hardening feature in switches Sonic OS based. + +### 1.3. Definitions/Abbreviations + PW - password + PASSWH - Password Hardening + +### 1.4. Overview + +Password Hardening, a user password is the key credential used in order to verify the user accessing the switch and acts as the first line of defense in regards to securing the switch. +The complexity of the password, it's replacement capabilities and change frequency define the security level of the first perimeter of the switch. +Therefore - in order to further improve and harden the switch - a secure mechanism is required to enforce PW policies. + +### 1.5. Requirements +| Requirement | Capabilities | Config Parameters | Notes +| ------ | ------| ------ | ------ | +| PW Length | The PW length should have a minimum length requirement

The PW length should have a maximum length requirement| The user should be able to configure the minimum PW length

The user should be able to configure the maximum PW length | Min PW length is between 0 to 32 chars (default 8)

Max PW length is between 64 to 80 chars (default 64) +| PW Aging | The PW should have an expiration date, after which the user is required to change the PW

A warning to change the PW should be presented to the user a fixed time before the expiration date arrives. This warning should appear in every login so long as the PW expiration time <= warning time. |The user should be able to configure the expiration time of the PW. The user will be able to configure "no aging" for the PW

The user should be able to configure the amount of days to present the warning before the PW expires | PW age time is to be between 1 to 365 days (default 180)

PW warning show is to be between 1 to 30 days (default 15) +| PW constraints | The PW class represents the possible characters comprising the PW. There are 4 character classes that can make up the PW:small characters, big characters, numbers and special chars presented on a standard keyboard

The account name and PW need to be different

The new PW is to be different from current PW|The user should be able to define which characters classes are required for the PW out of the 4 provided



The user will be able to enable or disable this feature|Legal special characters `~!@#$%^&*()-_=+\|[{}];:',<.>/? and white space



An error will be shown to the user if it tries to set the same PW as the username



default - enable, default remember last 10 password + +### 1.6. Architecture Design +Arc design diagram\ +![passh_arc_sonic](passh_arc_sonic.jpg) + +(flow description in the chapter below) + +### 1.7. High-Level Design + +In this section we will present the design (as thorough as possible) for the secure PW implementation. + +User password as explained before is the first line defence, in order to support it according to the requirement section and user preferences, the secure password feature needs a strength-checking for password. + +The feature will use 2 linux libs: pam-cracklib, chage and pam_pwhistory.so + +pam-cracklib: This module can be plugged into the password stack of a given application to provide some plug-in strength-checking for passwords. + +The action of this module is to prompt the user for a password and check its strength against a system dictionary and a set of rules for identifying poor choices. +This module supports many options, including the requirements of PW Length & PW constraints. (see option strength-checking below) + +chage: support the requirement of PW Aging, change user password expiry information + +pam_pwhistory - PAM module to remember last passwords (seen that Debian already supported it without installing this package) + +Note: +See linux 3d party component chapter for more description + + +##### Flow diagram: + +![password hardening flow](ph_diagram.jpg) + +#### 1.7.1. Flow description: +When the feature is enabled, Users by using Sonic CLI will set new password policies/configuration (see PW options below) saving those in CONF_DB in PASSWH_TABLE. + +The daemon named hostcfgd daemon will be extended to listen to password hardening policies/configurations from PASSWH table, parse the inputs and set the new policies to PAM lib using pam-cracklib, chage, pwhistory libs. + +Note: + +The Daemon is running in the host (without container) that matches this feature, because it is basically writing policies at PAM lib installed in the host. + +In addition, hostcfgd will avoid future conflicts with other feature related to PAM lib, because this daemon is also writing to PAM files for support other features, so it is better to save this convention and also manage the password hardening policies in this daemon. +#### 1.7.2. Password Hardening Constrains +The PW Hardening features will support different options by encapsulating cracklib, chage and pwhistory options according to the constrains definitions below. + +##### PW enable + +Enable/Disable password hardening feature + +Note: when this feature is disable will be just the default password validation without strength-checking for passwords. + +##### PW Class +PW class is the type of characters the user is required to enter when setting/updating a PW. + +There are 4 classes: + +Small characters - a-z + +Big characters - A-Z + +Numbers - 0-9 + +Special Characters `~!@#$%^&*()-_+=\|[{}];:',<.>/? and white space + +Each of these classes will receive a Regexp to represent the class. + +The user will be able to choose whether to enforce all PW class characters in the PW or only a subset of the characters. + +Note: +In order to implement it, the daemon will encapsulate some pam-cracklib options. +i.e: + +To request at least one character of every class, the PASSWD daemon will set: +pam-cracklib options: lcredit=-1, ucredit=-1, dcredit=-1. +(meaning that the user needs at least one character of the types.) +See explanation of cracklib options in 3rd Party component chapter. + +##### PW Length +PW length is a base requirement for the PW. + +All password length enforcements and changes will be applied the next time the user would require a PW change or would want to change his own password + +* Minimum Length + + The minimum length of the PW should be subject to a user change. + + The user will be able to change the password minimum length if he has the necessary permissions to change the PW. + + Implementation: + In order to implement it, the cracklib option minlen=N should be set. + + + Note: + Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change + +##### PW Age +Along with every PW set to a user, attached to it is the age of the PW - the amount of time that has passed since a PW change has occurred. + +This PW change can either be from the initial config wizard or from the CLI. + +* PW Age Change + Once a PW change takes place - the DB record for said PW is updated with the new PW value and a fresh new age (=0). + + Every login (and PW entry) will check the PW age field to see if it has exceeded its maximum time alive (the amount of time before the PW needs to change). + + If so - a prompt will be shown to the user forcing it to change the PW before logging into the switch. Prompt PW change view will be explained in TBD. + + To support it, can be use chage lib option "--maxdays" + +* PW Age Change Warning + The switch will provide a warning for PW change before and (this is to allow a sufficient warning for upgrading the PW which might be relevant to numerous switches). + + Along with this warning - the user will also be able to control how long before the PW expiration this warning will appear. + + To support it, can be use chage option "--warndays" + +Aging(expire) implementation : + +For implement the "aging" we need to change the /etc/login.def file and set max days and warning days, this changes affection globally, meaning all new users. +For read the information per user we will use the "chage" library. +In addition, when we change the file /etc/login.def its change globally by only new users, so basically for change existing users expired day we need to iterate every one of them using the "chage" lib. + +See the example below regarding global expiration time and warning time: + + # /etc/login.def + # Password aging controls: + # + # PASS_MAX_DAYS Maximum number of days a password may be used. + # PASS_MIN_DAYS Minimum number of days allowed between password changes. + # PASS_WARN_AGE Number of days warning given before a password expires. + # + PASS_MAX_DAYS 1 + PASS_MIN_DAYS 0 + PASS_WARN_AGE 7 + +As a result of the changes above, new users will have an expiration time of 1 day, so warning time notification will be prompt in the terminal: + + root@arc-switch1004:/home/admin# adduser test_user1 + root@arc-switch1004:/home/admin# su test_user1 + Warning: your password will expire in 1 day + +Regaring the policy when expiration time end (PASS_MAX_DAYS): + +The maximum number of days a password may be used. If the +password is older than this, a password change will be +forced. In other words, the user remained block until he update a new password. + +##### PW username-match +By enabling this feature, the user will not be permitted to set the same username & password + + +##### PW Saving +Saved previous passwords in the DB to verify that the user cannot used old password + +Implementation: will be supported by using pam_pwhistory.so, remember=N option (N- number of old passwords to be saved). +See that in Debian it's not necessary to install this package. It's enough to add the remember=N option to the common-password file. + +Note: +For saving password with sha512, need to modify the /etc/pam.d/system-auth-a file to contain this line: + + password sufficient pam_unix.so sha512 shadow use_authtok + +### 1.8. Init Flow +#### 1.8.1. Compilation +This feature will be enabled by default in the compilation stage, this means that it will be compiled, and will be not compiled only when the user specifically adds the relevant compilation flag "INCLUDE_PASSWH=n" in sonic-buildimage/rules/config file. + +In addition, the feature will have CLI as a "plugin", meaning that when the feature is not compiled will be not appear in the CLI of the switch, and vice versa. + +Feature enable details: +when compilation flag is enabled(default value), users can still enable or disable this feature in runtime. +By default if the feature was compiled, the feature status will be disabled, meaning that the switch will boot with the feature compiled, but disable. +the disable default configuration can be founded in init_cfg.json.j2 file. +In case, the user want to enable the feature it can be done by using the Sonic CLI (details in CLI chapter). + +#### 1.8.2. Dependencies +Service dependencies: same dependencies as HOSTCFGD, INIT_CONF and NTP service. + +Note: +NTP service should be secure, because it can influence expiration time of some policies. + +#### 1.8.3. Feature Default +When a user decides to add the feature in the compilation the feature will be enabled by default. + +Description of default values in init_cfg.json regarding Password Hardening: +``` +feature enable: True +expiration: 180 // days unit +expiration warning: 15 //days unit +history: 10 // num of old password that the system will recorded +len_max: 61 +len_min: 8 +username password match: True +lower class: True +upper class: True +digit class: True +special class: True +``` +Notes: +- Old users (existing users before feature was enabled) will not be influenced by this feature, only new users will have to set passwords according to the password hardening policies, or old user when changing to new password will be force to be according the new policies. +- Default password of the system will remained with default value even when the feature is enable. It will be secure password only when the user decide to change the password. + +### 1.9. SAI API +no changed. + +### 1.10. Configuration and management + +#### 1.10.1. PASSWH configDB table + +``` +PASSWH:{ + policies:{ + "enable": {{True/False}} + "expiration": {{days}} + "expiration_warning": {{days}} + "history": {{num_passw_history}} + "len_max": {{num}} + "len_min": {{num}} + "username_passw_match": {{True/False}} + "lower_class": {{True/False}} + "upper_class": {{True/False}} + "digit_class": {{True/False}} + "special_class": {{True/False}} + } +} +``` +#### 1.10.2. ConfigDB schemas + +``` +; Defines schema for PASSWH configuration attributes in PASSWH table: +key = "POLICIES" ;password hardening configuration +; field = value +FEATURE_ENABLE = "True" / "False" ; Feature feature enable/disable +EXPIRATION = 3*DIGIT ; password expiration in days units, should be 365 days max +EXPIRATION_WARNING = 2*DIGIT ; password expiration warning 1 month(30 days) in days units +PASSW_HISTORY = 2*DIGIT ; number of old password to be stored (0-99) +LEN_MIN = 2*DIGIT ; max characters in password (0-32 chars) +LEN_MAX = 2*DIGIT ; min characters in password (64-80 chars) +USERNAME_PASSW_MATCH = "True" / "False" +LOWER_CLASS = "True" / "False" +UPPER_CLASS = "True" / "False" +DIGITS_CLASS = "True" / "False" +SPECIAL_CLASS = "True" / "False" +``` + + +#### 1.10.3. CLI/YANG model Enhancements +```yang +//filename: sonic-passw.yang +module sonic-passwh { + yang-version 1.1; + namespace "http://github.com/Azure/sonic-passwh"; + prefix passwh; + + description "PASSWORD HARDENING YANG Module for SONiC OS"; + + revision 2021-10-12 { + description + "First Revision"; + } + typedef feature_state { + type enumeration { + enum enabled; + enum disabled; + } + } + + container sonic-passwh { + container PASSWH { + description "PASSWORD HARDENING part of config_db.json"; + container POLICIES { + leaf state { + description "state of the feature"; + type feature_state; + default "disabled"; + } + leaf expiration { + description "expiration time (days unit)"; + default 180; + type uint32 { + range 1..365; + } + } + leaf expiration_warning { + description "expiration warning time (days unit)"; + default 15; + type uint8 { + range 1..30; + } + } + leaf history_cnt { + description "num of old password that the system will recorded"; + default 10; + type uint8 { + range 1..100; + } + } + leaf len_max { + description "password max length"; + default 64; + type uint8 { + range 64..80; + } + } + leaf len_min { + description "password min length"; + default 8; + type uint8 { + range 1..32; + } + } + leaf username_passw_match{ + description "username password match"; + default true; + type boolean; + } + leaf lower_class{ + description "password lower chars policy"; + default true; + type boolean; + } + leaf upper_class{ + description "password upper chars policy"; + default true; + type boolean; + } + leaf digits_class{ + description "password digits chars policy"; + default true; + type boolean; + } + leaf special_class{ + description "password special chars policy"; + default true; + type boolean; + } + }/*container policies */ + } /* container PASSWH */ + }/* container sonic-passwh */ +}/* end of module sonic-passwh */ +``` + +##### Config CLI +###### PW enable + +Passwoed Hardening enable feature, set configuration: + +``` +root@r-panther-13:/home/admin# config passwh policies state --help +Usage: config passwh policies state [OPTIONS] STATE + + state of the feature + +Options: + -?, -h, --help Show this message and exit. +``` + +PW Classes: + +PW class is the type of characters the user is required to enter when setting/updating a PW. + +There are 4 classes. (see description in arc section) + +The user will be able to choose whether to enforce all PW class characters in the PW or only a subset of the characters. + +A CLI command will be available to the user for this configuration. Once a user has selected the class types he wants to enforce (from a pre-defined options list), this will enforce the PW selected by the user to have at least 1 character from each class in the selected option. + +The CLI classes options will be as follows: + +None - Meaning no required classes. + +lower- lowerLowercase Characters + +upper - Uppercase + +digit - Numbers + +special - Special symbols (seen in requirement chapter) + +multiple char enforcement + +There will be no enforcement of multiple characters from a specific class or a specific character (be either letter or symbol) to appear in the PW. + +The CLI command to configure the PW class type will be along the following lines: + +Set classes configuration: +``` +============================================================================== +root@r-panther-13:/home/admin# config passwh policies lower-class --help +Usage: config passwh policies lower-class [OPTIONS] LOWER_CLASS + + password lower chars policy + +Options: + -?, -h, --help Show this message and exit. +============================================================================== +root@r-panther-13:/home/admin# config passwh policies upper-class --help +Usage: config passwh policies upper-class [OPTIONS] UPPER_CLASS + + password upper chars policy + +Options: + -h, -?, --help Show this message and exit. +============================================================================== +root@r-panther-13:/home/admin# config passwh policies digits-class --help +Usage: config passwh policies digits-class [OPTIONS] DIGITS_CLASS + + password digits chars policy + +Options: + -h, -?, --help Show this message and exit. +============================================================================== +root@r-panther-13:/home/admin# config passwh policies special-class --help +Usage: config passwh policies special-class [OPTIONS] SPECIAL_CLASS + + password special chars policy + +Options: + -?, -h, --help Show this message and exit. +============================================================================== +``` + +Note: Meaning: no must use of lower, no must use of upper, must use digit, must use special characters + +###### PW Length + +Set len-min configuration: +``` +root@r-panther-13:/home/admin# config passwh policies len-min --help +Usage: config passwh policies len-min [OPTIONS] LEN_MIN + + password min length + +Options: + -?, -h, --help Show this message and exit. +``` + +Note: Where length is a number between 0 and 32. + +Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change + +###### PW Age + +* PW age expire + +Set configuration: +``` +root@r-panther-13:/home/admin# config passwh policies expiration --help +Usage: config passwh policies expiration [OPTIONS] EXPIRATION + + expiration time (days unit) + +Options: + -h, -?, --help Show this message and exit. +``` + +Notes: Where age is in days and between 1 and 365 days (default 180). +* PW Age Change Warning + +Set configuration: +``` +root@r-panther-13:/home/admin# config passwh policies expiration-warning --help +Usage: config passwh policies expiration-warning [OPTIONS] EXPIRATION_WARNING + + expiration warning time (days unit) + +Options: + -?, -h, --help Show this message and exit. +``` + +Notes: The warning_days can be configured between 1 and 30 days (default 15). + + +###### PW username-match + +Set configuration: + +``` +root@r-panther-13:/home/admin# config passwh policies username-passw-match --help +Usage: config passwh policies username-passw-match [OPTIONS] + USERNAME_PASSW_MATCH + + username password match + +Options: + -h, -?, --help Show this message and exit. +``` + +###### PW Saving +Set configuration: + +``` +root@r-panther-13:/home/admin# config passwh policies history --help +Usage: config passwh policies history [OPTIONS] HISTORY + + num of old password that the system will recorded + +Options: + -h, -?, --help Show this message and exit. +``` +##### Show CLI + +Show command should be extended in order to add "passwh" alias: + +``` +root@r-panther-13:/home/admin# show passwh policies +STATE EXPIRATION EXPIRATION WARNING HISTORY LEN MAX LEN MIN USERNAME PASSW MATCH LOWER CLASS UPPER CLASS DIGITS CLASS SPECIAL CLASS +------- ------------ -------------------- --------- --------- --------- ---------------------- ------------- ------------- -------------- --------------- +enabled 30 10 4 100 30 false true true true true +``` + +##### CLI permissions + The CLI commands should be allowed only to the admin user. Other users should be able to view the parameters but not change them. + +#### 1.10.4. Config DB Enhancements + +The ConfigDB will be extended with next objects: + +```json +{ + "PASSWH": { + "policies":{ + "enable": "True", + "expiration": "30", + "expiration_warning": "10", + "history": "10", + "len_max": "30", + "len_min": "15", + "username_passw_match": "True", + "lower class": "True", + "upper class": "True", + "digit class": "True", + "special class": "True", + } + } +} +``` + + +### 1.11. Warmboot and Fastboot Design Impact +Not relevant. + +### 1.12. Restrictions/Limitations +The secure password feature is not supported on remote AAA. + +LDAP/Radius/Tacacs is under customer responsibility. + +### 1.13. Upgrade Flow +When user with the correspond permission is doing upgrade from image with password hardening enable to password enable as well, the configuration related to the feature should be remain the same as was set before the update. + +When user is doing upgrade from image with password hardening feature disable to enable, old password will remain exactly as was set before, the feature is setting rules/policies to new passwords or to new users, so old passwords will remained as was set before. + +Upgrade image from feature enable to image with feature disable, from the security POV should assume that the user that is doing this image update have the corresponding permissions. +From the feature POV, old password records that were set using the feature will remain the same, and new passwords will be set without the password hardening policies, because the feature is disable in the new image. + +Note: +First time, the default password will remained the same, even when the feature is enabled, and if the user will like to have a secure password he will need to change it, and in result that the feature is enabled the current policies will required an strong password this time. + +### 1.14. Test Plan +#### 1.14.1. Unit Test cases +- Configuration – good flow + - Enable/Disable feature + - Perform show command + - Verify default values + - Configure passwh classes of every existing types + - Configure passwh length min using different valid values + - Configure passwh age expiration using different valid values + - Configure passwh age warning using different valid values + - Configure passwh username-password-match + - Configure passwh history using different valid values + +- Configuration - Negative flow + - Configure min password with random false values + - Configure age expiration password with random false values + - Configure age warning password with random false values + - Configure complexity-class password with random false values + - Configure history password with random false values + +##### Notes: +- After creating a new policy is necessary to set a new password to a user to verify that the policy match the configured. +- Valid values: could be random values from valid ranges. +- The set configuration should be validate using the show command. + +#### 1.14.2. System Test cases +- Test all passwh policies together + - Configure all the passwh options. + - Create a new user and change an existing user password. + - Validate that policies match the configured + + +### 1.15. 3rd Party Components +In this section you can find most of the options of pam-cracklib, chage and pwhistory, we are going to use just the options mention in the Arc chapter, the other option maybe could be use for future features + +#### 1.15.1. pam-cracklib + +Options: + +##### debug +This option makes the module write information to syslog(3) indicating the behavior of the module (this option does not write password information to the log file). +##### authtok_type=XXX +The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". The example word UNIX can be replaced with this option, by default it is empty. +##### retry=N +Prompt user at most N times before returning with error. The default is 1. +##### difok=N +This argument will change the default of 5 for the number of character changes in the new password that differentiate it from the old password. +##### minlen=N +The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit). The default for this parameter is 9 which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system. Note that there is a pair of length limits in Cracklib itself, a "way too short" limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to minlen. If you want to allow passwords as short as 5 characters you should not use this module. +##### dcredit=N +(N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. +(N < 0) This is the minimum number of digits that must be met for a new password. + +##### ucredit=N +(N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. +(N < 0) This is the minimum number of upper case letters that must be met for a new password. + +##### lcredit=N +(N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. +(N < 0) This is the minimum number of lower case letters that must be met for a new password. + +##### ocredit=N +(N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. +(N < 0) This is the minimum number of other characters that must be met for a new password. + +##### minclass=N +The minimum number of required classes of characters for the new password. The default number is zero. The four classes are digits, upper and lower letters and other characters. The difference to the credit check is that a specific class if of characters is not required. Instead N out of four of the classes are required. +maxrepeat=N +Reject passwords which contain more than N same consecutive characters. The default is 0 which means that this check is disabled. +##### maxsequence=N +Reject passwords which contain monotonic character sequences longer than N. The default is 0 which means that this check is disabled. Examples of such sequence are '12345' or 'fedcb'. Note that most such passwords will not pass the simplicity check unless the sequence is only a minor part of the password. +##### maxclassrepeat=N +Reject passwords which contain more than N consecutive characters of the same class. The default is 0 which means that this check is disabled. +reject_username +Check whether the name of the user in straight or reversed form is contained in the new password. If it is found the new password is rejected. +##### gecoscheck +Check whether the words from the GECOS field (usually full name of the user) longer than 3 characters in straight or reversed form are contained in the new password. If any such word is found the new password is rejected. +##### enforce_for_root +The module will return error on failed check also if the user changing the password is root. This option is off by default which means that just the message about the failed check is printed but root can change the password anyway. +##### use_authtok +This argument is used to force the module to not prompt the user for a new password but use the one provided by the previously stacked password module. +##### dictpath=/path/to/dict +Path to the cracklib dictionaries. +Module Types Provided +Only the password module type is provided. + +##### Return Values +###### PAM_SUCCESS +The new password passes all checks. +###### PAM_AUTHTOK_ERR +No new password was entered, the username could not be determined or the new password fails the strength checks. +###### PAM_AUTHTOK_RECOVERY_ERR +The old password was not supplied by a previous stacked module or got not requested from the user. The first error can happen if use_authtok is specified. +###### PAM_SERVICE_ERR +A internal error occurred. + +#### 1.15.2. PW Age/History + +![chage options](chage.JPG) + +The options which apply to the chage command are: + + -d, --lastday LAST_DAY + +Set the number of days since January 1st, 1970 when the password was last changed. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). + + -E, --expiredate EXPIRE_DATE + +Set the date or number of days since January 1, 1970 on which the users account will no longer be accessible. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). A user whose account is locked must contact the system administrator before being able to use the system again. + +Passing the number -1 as the EXPIRE_DATE will remove an account expiration date. + + -h, --help + +Display help message and exit. + + -i, --iso8601 + +When printing dates, use YYYY-MM-DD format. + + -I, --inactive INACTIVE + +Set the number of days of inactivity after a password has expired before the account is locked. The INACTIVE option is the number of days of inactivity. A user whose account is locked must contact the system administrator before being able to use the system again. + +Passing the number -1 as the INACTIVE will remove an accounts inactivity. + + -l, --list + +Show account aging information. + + -m, --mindays MIN_DAYS + +Set the minimum number of days between password changes to MIN_DAYS. A value of zero for this field indicates that the user may change their password at any time. + + -M, --maxdays MAX_DAYS + +Set the maximum number of days during which a password is valid. When MAX_DAYS plus LAST_DAY is less than the current day, the user will be required to change their password before being able to use their account. This occurrence can be planned for in advance by use of the -W option, which provides the user with advance warning. + +Passing the number -1 as MAX_DAYS will remove checking a passwords validity. + + -R, --root CHROOT_DIR + +Apply changes in the CHROOT_DIR directory and use the configuration files from the CHROOT_DIR directory. + + -W, --warndays WARN_DAYS + +Set the number of days of warning before a password change is required. The WARN_DAYS option is the number of days prior to the password expiring that a user will be warned their password is about to expire. + +If none of the options are selected, chage operates in an interactive fashion, prompting the user with the current values for all of the fields. Enter the new value to change the field, or leave the line blank to use the current value. The current value is displayed between a pair of [ ] marks. + +Notes: If we want to do "age" configuration globally and not per user, it necessary to modify this file: /etc/login.defs, example: + + PASS_MAX_DAYS 90 + PASS_WARN_AGE 7 + +#### 1.15.3. PW History +pam_pwhistory: PAM module to remember last passwords + +##### DESCRIPTION + +This module saves the last passwords for each user in order to force password change history and keep the user from alternating between the same password too frequently. + +This module does not work together with kerberos. In general, it does not make much sense to use this module in conjunction with NIS or LDAP, since the old passwords are stored on the local machine and are not available on another machine for password history checking. + +OPTIONS + +##### debug + +Turns on debugging via syslog(3). +use_authtok + +When password changing enforce the module to use the new password provided by a previously stacked password module (this is used in the example of the stacking of the pam_cracklib module documented below). +##### enforce_for_root +If this option is set, the check is enforced for root, too. +##### remember=N + +The last N passwords for each user are saved in /etc/security/opasswd. The default is 10. Value of 0 makes the module to keep the existing contents of the opasswd file unchanged. +##### retry=N + +Prompt user at most N times before returning with error. The default is 1. +authtok_type=STRING + +See pam_get_authtok(3) for more details. +MODULE TYPES PROVIDED +Only the password module type is provided. + +##### RETURN VALUES + PAM_AUTHTOK_ERR + +No new password was entered, the user aborted password change or new password couldn't be set. + PAM_IGNORE + +Password history was disabled. + PAM_MAXTRIES + +Password was rejected too often. + PAM_USER_UNKNOWN + +User is not known to system. +##### EXAMPLES +An example password section would be: + + #%PAM-1.0 + password required pam_pwhistory.so + password required pam_unix.so use_authtok + + In combination with pam_cracklib: + + #%PAM-1.0 + password required pam_cracklib.so retry=3 + password required pam_pwhistory.so use_authtok + password required pam_unix.so use_authtok + + +##### FILES +File with password history + /etc/security/opasswd \ No newline at end of file diff --git a/doc/passw_hardening/passh_arc_sonic.jpg b/doc/passw_hardening/passh_arc_sonic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..209cf7150c52e0d642a0b1af69d68e26aadfce6c GIT binary patch literal 27790 zcmdSA2S8L$vM)TSAW3nEk|oCh$r=8Vhs=<(zzlgnq9VxvNDjl0qvVX_3`&jyLy#zv zgGkOGym9Ycb@%>v@9w+rd*AmJVQRXnyM9&Oefo5rKG&1iUjX-%;K@N{opPBgAe<`yJ$mX&^j4t zp4Iv{-r_g@soN7bv`)_teaj~IpY ztN?)hJOJR10RTWW3;^I7{T1l1y1)A3ANcwJU55(orxW_e8sGqc0UiLr07rl&fD6s> z0v-Z*0D{*u02#o|8$amB|C?yKg>~x(VPj!oV&P!p;^JWA;NapD;N#-m#lyk51H5yW z;NCspJzRW3BEow_X#U=hMlgQVym<>7UGW|s4j#Jn-=ypJ03bHT+6{)A81#S}K#ZF} zjOz{nHM;w5{`kfCYXkt8ShsK8xQUH{gBHW?0RUJSH!v`9aBpMZ!NtTxclV8(x6mp; zLLyQ+-7#!pGI}1J*fha%eLU~aERVluO`JJ4n*(B^NTVf;oIXbhNGXqg}oJ>@WN-Nw9)iN^UC z4KxHGq2?_jVme6l2+t$ux8<0;eC97d?2^!HAy9j-Di*G%0r=?lZUAor0aAdgf)~HF z{9jpur1ks)zCxwTZl1gVcWZZ&g6&2L|DNS~ZA5QwFBIy}hy*j{SxnYSrVjY9N_vhu zeV729#St806IV4KsHhKZ9ZI$*=7uV5%n6OQUbu-<+J4e-9+KnPdh;4Cx_MV*Jy#;y z5xhaMeHX^7lyILi;sd=uuMha3Cg1WY z#Iq>vPSw|Z;kC?!W0?;%sqVL_4z*}{%3nOrV=%Mt6dxb@*(BYU8MTJj5zpBoq5AJ1 zYDJe-FQ(b8{e%>?3(qro)Ga~WUBPKlo4;SlsxQ}6B2~s#f78JUC(>&XQWqNfBGr&m z0P!rGv6=}h6U^FEi=CMgEh<+mcbb>d>iuVqA{Qu9pQ_UvsP*%5rqy%lX3CJe15qXu zr7Ew??UmslA_fw&?bQ0ERf3@lE`<#0_~FOR4aKI@IzB`L%0c6eT@LC_NJmE9;hOBX z$}o6hgSrB*QdFiotJmI>L>j~V-ctVQ(pKUFo0dO|!(gGiwZ>#i?|RPgsQyPkR#ic6 z@_zS+(@{F#`pmpV69VCkQOah7ko|DwFEas*Z#U{EB$T@L?eo^Yl!zIqD(G3mG5U3f z3-_Hj6n&g$W!QIe5(NX8@C1W~Q%|JBhT+;UtQkGxv#M*rpT${bGwzYko#LnWJGZ{~ zmG{GO%SpXs982+J+shih+B^xzeflz%iOLoNR$_o?%i4;rns8{j&D@{5+~}W3X~_vE zL^2cp&F5@}3S|1B&MVtTRP; zIlk&s1iu-Pjs1W%Uc{tq|B|JTQndzt+GP~im9?WoN%m4m}dVHU)=hO6_x`6AiLHcXllRm^JUbg@CEHA14*C72h?nCcm;kpPM zH~kGZ&Lj)ulEI?0lFQC>FZN)qi(Zx;p81GFs55^$Jq{S*4OZ)1WIUetxdz0oN(I>Dy?{WXIcBSyKUT?qiD<<) zYQKCXz3jhzev9Dko1s`|_&d>_gn$Vl-_1>OS!UQDd9fnFDmBKShS+ZDQxz1LPpM8N z(q+amCND>JUgh+A>NUVZ=RTaZ)q5dLzw9XB#VrL9%FWMao2hx$cU^?Wn_9=k)IPG$ z-<=@u<+{O;5`N^weWW&8`R1n<-j{X}ruVY0(Jdt_R|V4^Pu3WGjQYQ8Rc$SJ-?wJ0 z!;bjb4Artzk*8mwM`{Z9Yy9PS4B$uk^V<0HJlm=EpA84>nx`NZxtY5;D*6nFbpy}I zy@#tB+5=~b8v+nB?$u-;3`vpsk-hb#%dmQaUl4z5n>jIc6gNecJZRZIv(L3DkL6uM zsgCB9ekmn)M~Ic(7jqtliavs{)6>Cf&ViVQFodjGsg1||I^AK&w@{n93~OpnusfA% z7aS{spFHE(S?)te)@&p~;Sqe){+DwzmKFUI3_M$0O2ih9^B$JAokElhlDY@Ik$ znAoWCAnB$nwHQD~1Tq?k_h%h)KU@X6IAQF=079W{1p@18gN#Vc(X%!qsblWY4}AuDg;j z%3?EN+VyEkbS(WNJauGUr8_oDM zZ(+`2nfZ5(7Uxmb=-eeSA*}ET>(S*gE-|lCc`o)9)>-Gj9gjU0Ku%H1#{lYy%y_=g zJA$7SU~R^LRh`p8tw&2=7ulKTjM-6gJO>;@fQG&#!t3s6VChk^p^PYlJWDv6bWz3? zEny&vfuTDJahdX%`#r1i>iFjj^Q#)A?^=IErgBj4otaU(Hl z@0JYFTZ+&ms*fh0AJn9J=bwB(F|1>i&6{_Q$B$uy;JxiQbfJtsQ(hsy7*J=lr$|Ra zpQYf_-xZ708gHcOn!r<;PGJl30k1$7DrQ}kRCCAn-pV_11Y>h^?aqFa5t>)7s}YTZ znC@21OWHj_4;YD6*~oWe5~k~R*3b4+M!LifLLC)SAR=6}>Bt?>$$6dR@O>s~cvmsa zqa^dm8QapTrgEPg0YQ!+SL9pPj!gGF;{IHx^c%?02u7sR-jM%5b@6SicU=_|)~OsC z3qo(SNB3%S&uJrS!&Mz(W_uZ{w)}4AWejB-q@?CUFL3NhyS4j5=O>ERdR5aG^O^?Y zkCPtNPX{`+#5+54FuDg=imBBM{|>J-~0DKE-JTu{el2^OUsT64EecAX-^`_XAO^eh(J9CAGd3c2N8nAjW|9RS0?9iLG z$aQN?u=MCA!BK_Y))%s2VlG#^9gT5I{rl*)Y|V{Y*58@waLlw^n`h$dCu($Dri(-eZ&~1B0DZ5ZNdCh+Soht8o)a5 zrttC(Wqs$)E(ac!AA~1)7M488t6^>8aLAO&$NjK^UT~JF#Mss~C^%kR&cSGhP~f>( zAPoHG^GEfbgTY#03tAXW$<(8{T}mX( zC^1>t>ROyOyY>cjTo(vtBKl-pRI% zdmIsB(3~Pm2-1f+i%&9!bp8B;#_Q=5>gGcF{f7J;rn3GfcVVcRA;L^wEz*{{V@i*@ ze;51Q_*EoB@cbC*9_M|A1%Yl)E<&CC93yWcZe(P(|BG=R9wBAp&bbT#HhP1du%J>K zYoI)KacjS9vS70MR@NMky+)<7H|E8-M0;OxfA(oq%(}GPfYzbwuADz@-?J6l^a*S7 z=Fa#3ZTH<~s#b-6a|rQz2Jd?V!kQTrHo@gSijLlb!cg+Eu=1#{0HCNf97bQ!PSupK z+{kI?Qe=u;INdi~9{x(eu?9(Wuh6_KQo07v8OssfULUG-;ifCByZU@0g}&?Ne*E77 zxG6q(V9(-U)=@434!d;AE_QeZw!SxpfEe1c)KlihFp=knvw^dZHS>cCqu4U^8kTcs zv?}H|e2u;eLB;(d7Hc)HRFAo%f?SpkCe!&C8AX+SB^B&CBGM2Ln6M(lW%xeq4BP+x zhL)^B*L{=R6d*cf#fZ+!c^B$$D|09kNEq25rid2ulb^NZ(98&@cN(xsX|#MvEG~L8 z*R@Yv6`D}uvf-Y&;OOAfD_%%6+Lp;jZzv=Y4(8=!A|0peH!~*`%rSqbY6V$UOhOXs z$~A%mH{;(mL=6^6+R$-*OqL=ly+UX<$WCh*YD*Z z{W(Yb_uFKX1UHl94)xxg-{pSC1-Oy^#Z|E-WcM2IsPp*d`_*V4l7*|+p<8$_0C}fW zDDKQAsbOcI7rP?aW^&K`G8Qjxd;zds-R2KnFC#dlGJE`IRyrimR;Y;BEjMBVU=ae{ zG=Xj2&!>(87m@9FKG0EucQJg+k+E7f5TXj=*u*U*F!_9^l#V2)^moSYR-+D#C+O^= zZMk0hif$F(vgBu}NVbH1%ZK|(BBNBc+!Q8;DzUwEdE}BeB;xW2LS4YXLp0F8_x_<@ z*m=OYV)tgq!V?VjU+^)0a~JbHK zCXoof))3!9Z~cICaHMZ-5Ep>sRH1uoW`E)u@W)%LzS8>Y&{?SbCys4x93oGND_X|s z_}ZB^4&h%)42AQrwz>~6-yFGztp_D#GR5-vXcG3PbQU?{=dJ86nHn_6<}It)asxRp zv!`|H1z+tGLS$u)Jk?!ksM~GxDplMg{V+Mv2kBS`WH)t=I-h1~|zI+)N{^ zr|z0RZdT4bbd~IhGYR){oi227a~t%`X_>WjXWX25l#Q&)@)=~b2a`uT$Y-AQxM7J_ z@~GL+{H*1Qhq-A&mX&xcTd`$7lQymula*^f2s&P(EMU={zQdT4L%D6sV5m3{Y9T=O zQ6`42kEdAa2AsDkq#};+v!f_CbdCAo)F7VuS5b~ z9dU(@3|!E=g@x5J%!X-~9r=OFm5=vSvb1^Fy=pxr)oOfZZT92)XnLk{isQT$me)7V zZrQU(99pEHe#S29XT*ZP5JeP^hPeK5@K^jY3HscS^=7J}3YHf<RRwI5k#1=-acl4Jt!TSbxDTo#$1AZ0*ft~& z)%$nYC%%_I0N@Tj_;GnANF^^wneF!)@ac+{n(Ghz3|r#0GQ{nY?=^@f&ylO&Ee<-K zw`AaYwG$ezOWE_7e{7v8(J|t#$FtF{qe^Eb9nms!_^7+vI==b#gyN1uW|Y{ph~3L zA}!F>YodR3n*JJ)>OdaUAeP<0r%uqx#tJU6W6WWyPfY8OeNbO1;zP)%{7HHBGoRnb z88)8t6c!r8;NHFT3Qd}24?<%kLJFN&2xmG5VvenvkT=ovTlPaT7xyAo!Q^?tv2gNg zzx&q!CFQT^^?OgDkuuMN#xH1Us#m2*M7NCT6C{mT@KtFNbQJ1`dCSVrART;}tRgrA zrvvf(zr_I|kZ~Py2S5U2sYqe7HCx&uE9}JYl|bY=#Hx<)Qs>Dnnt9DNuVLts?3>h2y8qw5i#S(TMMpqQD~k%x0cp)Y7z z*Jm1~#u^p{r-NoO(9e1fOr(mxHo7q(7aLvqSRHhy7A(>|DZ}x_(}i4_d0CrIUN%P@ z$;7h4OJ2hKW^Fg?vugPpOsC*h$21{hMqUv|RU~hIiW_oT3sf`c0T)DoDIrm>+*NawB~yd=YmV>; zJd9bf>ll37yhD0=1gW`1@adGD#gaVe8M6nFUQ9-LmXeG+kU_7EU1P{g-Rd1FCr}Sg zc_c|b0ulpLdqU?Vs>;TLs3r`?+94p%?xm9EV;gBIMXf!k%55%-CK*7ZLy&68OUQ6nQeKQM|TmBt(BIUVXxsh)q-rg>X?qI z`Zj2e(0f?-PIA&84(oapge5hzLEYV2}Z;x90NTiD1j)W_9B@3n$?b|&@! z#sKtEa{F{B-z+=KH@_4u{BXs$Nw&d2TgVac9z8RC$q|ZUS@iT9d{R*mdVAfJ!Izd+ zgH?;+`u?KTjp_m|XVRZ~-#X*KfdfjPDj?3iZJGs)si!f`Qyob&5Uuw5=xApamkZ?; zx)7ZWH9v}o{qplI&$@jI7|^z#p(+~VL}QOT4yN`XC7)Nx0}ia0t;$jg4I55v>$Wb_ zcXtS}Rt;6K|CW@N!&#Vn^7U?~V6Q6GjmOJ-4h#7`!}7?CF<3jwRAjsLOP$rjqIIIX zdnbi=H;JFYC6}BOcu%SuF5o4=sD;yfqb9~2N8~o_-JwMiJmFDgH@pH5dplLdOE*F+ zuEHTDB$0WD5yjL4=jvgMQJ(95rnmI1Jlai%aXl_uZ;{JV_%a24G-ms_Si3a>*c&8*J8iP|;CngP|6)GC2lYR6;- z&;ivt(pv1`MyYrmH9dMl{9XIB9PcoO=DX89V}RanWaL!sO3BqrX$75D%&Ev#Jc7-y zz{x*fR=1i@_h1UmxQc+guO|5-Snz?}B(8a~4?Q2wDsw?DqG$d?EV zBm=`MYS&+K7G@=TDm`p|9503yk@V*7>L3G^MIAY(s7{Hsh?*kLds$(K zD9cq?h+BDQE>AYt07BHl@)KrQhqk|Q<&I1@$Bir2MY9D7=09hnly4ie38``}VT0Xz z#YoN?v*gTf>XE&nOI>)LBbQ$vCuX`*tdwb0+U3gX`=K(ZDv82ep=&RH$RFXKKQLs$ zz&B~9|1r@*KeZ#}RXOQ?aSoj-RkD5WL0cZ2me#4|7c57G%?pnpgEpW7=L-vGCrXBrK({$Kp$x9(@RQ6WhJ;g8F zg)bg@4{#$MjF}8|7Zk5-s(Cm~e<7`{6cJCew{?N)R5+ub&kQ~P!a^(`H;D7}YBGgT zgw)oe_-$Ts<=1?JT8_vAd4xprpa7g?bxI_3hd9YFAx1!Hg*02FC#OP_(g+w?@Z#Zp zGqJ}YNB06j~V`yFs6=u#E8q#~nm-PdqZ3x_-ST;S|a-Q|Qxwdf3l zpR3I2LBN$q^m)zWNt$3%nPMq=KDBxht0g=`93@+;7;piz->p;a>}@mpu%)G^+TZ?vkk89<9n`=4e9GnO06i9$Su0U7saT)`hOzEFG}$ly9UTS z*SSJ$`I!@}ZSxd2e-`*Y*$@zPBDFLCo1783G42VbU%Bx1D75#F9k6W_;p{ZFRPOga zV`RFevR@QD!+qc=7zOj5z@=DpBDnl4Wb z3TtLD^9FNEE+cF^DY0@MBpW#t&#v6_X5(T|P%8*s@qlFlx+_$DlY=xw*bi=a_D}cM zxswU#99(=!fFDxkafziQ>Cjc!AS=K%)8p^6cM(BB7nN{FS1QM~1Ca>vOAB zJW(yUM6Er{hF6LX$l;gbf7dVFN?XKAD&X;?kHB2`vO%S)$ES#icm0~-2;DwA&Hy%f zCl-qZ`gO@@q3vd&vZYairH^E1(+ZnYubERz>h+#!O^j|Fx$I9(-K?A4Y{VPy3cjoC z98agLlDpWDXQ*YP6jdt6oarnMezc9KvyCu=#V^ zlH^-o1kZV99X~p0^7<-#!cWKH*GRsal`TFeD7q*6kMVQ>%ZUafS8Uswrff^H*-j2Aj+Bn!H zAv^$>9^=l~lxq}#K0c$h``iAMcviFH{Scp>C(8$V@5x$Cln+%lOgi%ZSbBOuPZ7gR zZ%67C(8=YOQ8f2A%NM4Q7L`hVmGD=VPQm^M#h!8f*=NFt>A3xY)>o?UGWqr$v*VHd zUQxJLz`YB>%j(u)R()4PTXIrLpU6%KbJHZw+ywcv-u>fOBt=mW`M<{ zYIUycpOT1?7bkb%Sd|!b4ZsvNIfREkr;&OG`bMnoR%~AY`NO1%c;o3v4QTz@)%#~` zsGTeaqv5^pFU90&rG^Sha=;iKyIMK(@{_f1mo6~AW#aeapLP~7ja_^-C$#NOzqRk<~>jF>YY)Z%?8Ek3`A+`|6^K1A>6%ZCKgr~`=} zu}hdblQNQ~mB4I5J}kMFQK~YIR@`%J`WlGbGIj)+>X0Y@r=1+Yp96g{&3bm_qY7tN z#H)Rk%5^T-*-St?N$|^4%Ku}IP*OPTRBmcd-)R%(n)xAQ{=Eesn{CyVY<5tPJMM8!Qf~_doTFRl1wa6ueL|CW zx_!9SZY9q7>pbTI2kTPzah3D_(AydBE|~0@x>98W6MPg6iSzK@Ab2%}eb^R2m$?=c znWzodIF_a3`T$o~%ih;a-4=Qhq)Njr$Bxnz&Ru5=wxwjqzCmb!Go3iprgbbM*=4T6 znS-~vhHrrZRF@}N(xBMjq3L5LxKbXmH<~cdQHlSynWw)bud{DoXk)q|HtIw5yI_(v z<4{sYD=J&yG*Pv%zFto@)E8RG+}D9l@1CPOCNsB(~jMa%TT%z7ck0WB=br!w>aT^BH>vCC6|$R zX=g`uwF$L17F2GDGt{SM_L#&z*we!`&hmL`&iyUV{LE089{XM6xm@1G#xG0xDGq66 z&YjUN%x3inb>9Ft@;gyC7T1P6Jzm461VHWqp9NmS;`Vv-c5jLi6pyg1*(| zmld?xibo?R+MbQQ*2D8cD9enfFwbK*cfFm~8`VNTv5TgsCSmycydm{f0pgW~XxykN zTLJEqUXUO{D`ZMihvN~=y?bib!f#rb*d6<1QkWGQLTAsw5;fdi++3ZvPsex*c5#Av(}+-6DDP;`w$09m&8IK4#vq8oisr z8yT`GUOU;DN*{S$Q+E|Xz9a-xmHXP~xH6@fEYaJl(fRc&J z|10TZSySm9yO^18!pzpkZ+Q0oa>d)XtEv5eWXBTDq(*7XPYfg4sJeTv5)KF&#yo)N zgxZzm@-;xk^Ua){7`7`d%em!%3?gXEStaty=2BY&9Z_O*CiNZut6iON=&wNhz!OxY~0}yves4Z!dD3<5%zxJ5p_eG)YYrj6(V-oMA^UmkoYB z^DAWU(Q)}t!icq*Um!DSMPmDHm0*v{>ty-)n|NGl&|L#6svZbv{8jI_PjX*)sJ`WK zC2xbix@u`!=JPHF9D%0x4g|Obg_mQi$yhg>PU*5pue(V{aHH)`3bem0ZY)q|SQ#!0 zYwc4wAotGpVHA9++dAr?^#Iw()Zu{{az(s(q9)dV4Ip^a>AKH}lparQGI56=8g_ot z&ITZ(bIBcKq+BXlV<@@lIg4u0j~zL}N^q_Lr`?3_n$;bSRq##r&puAbm<@jJy9Vgb zlZ;3pW=KXQ5Ql(uHKKyjwEoaAdF}<0us6pSBDegCpUR^KA~df7L!J%#4woh4e<&+m z1}^nI_3HzplUl{H)0)&3mbqdulZu*`5R^&EH2|m18zhKKn)5XK0LPhA)*D0ckv81~ zmY*o68BoFGqEre(*4cG8BTxh3j$*Y6?4`tUovk;N;U|!qca{mHpit2Q_t+*aU1N@9 zrcNm)x&3(7N&%oR8#&7=ojC;vv}k$fj==Oh83X_*Mxir9g6eNfb{InzDm%a4&kyfXIerq3!LT4id%$JAY0?cNz^S_iB)UpLw#8T*EJZ+fVUeF! z^qaFtbp*>t*r{p=+(c2KE}GssN9adkUeVFyI1kCY{b&6K>eCCJQX|Egm#$y~-<9jO zvJ?RSmju&9>vA+!S!Z~OH7l*t&OxEycoyvk4`NOvYtnoelU=2;a#09@8Xx8urkboJTc{ymP{0YRCs(;->^nbmbh5>U zfdI8V^K?_0CL+DqM`2jDIarnR8sOr|s`o*Nut*If%`z!IxNX4MmP-WJ7K965c5&+R zsZOGaIIu>|4A#ZgRM9GF$CCBj==g^|@ea~3hiX*!%ovX4SdZL+W=9k13_hoyjC7r? zp_e!pRq1yOAJQV%4Le*rUoK16VDJ;l719s}I;Nc}p6UZTL%)X)bpsJgO@dLgY9ZW7zQnMYA( zFSPj^HH(hKNI52tP(@8 z6^1LN)*$v^^Y(cGd+7Ie9dg|ux8?H=^q3*L96JiQ`a+TaXBGeTvYu+`h&A>7SD%XM zse)lNyp~ql&XkKLo%UWy(5hD(+CABJ5bOpMn_2tpGcIb;SLg9;SuYVwan4(IC6+?G z#C2bpsxG(~kpVe!D+~+_bf0?V7Td9VEZdWVuv^u9{gtO|8R8r0v zhfl6xPx}Q(FwQuzb<$NbzU|=mmgFJ7efaLrko@aqw;aLYBUZ$u!lmjuG<~_#e9_Du zQEAMdVXz8B=6TOGfX(}rA^_T87Cmq7Npwz^Kfw{pMZ^&sJlE^${&`HOoWex6LxER_ zP~)VpD%r{RJ2avZq*(HC;S){ja5r;P)j@b)&N($&xB{!Y5C9t)exy zu`gg%<2UERp>4^AGb?lMc#qPhrx)B1vDt&n;B`Kds)B@Eda;!( z#X^hlxo=1MX}pW!F02m}pPXwi2NG_M`H2)j?WC%@*Z6rPi^hC<%b?0HatbRKBGh~- zTx4Bkh&G!QW|NL(lJ2MLY)USFs$hCAUpN#fa^JQWIEb%actq=BKXuo}!bdOvBF3~Q z9x!gO+s$xCgkI!r@R4cOwyGE1Pc_0X6h)Hvm(BAS6@FU#sYY*nQ^&fUDvW! z{CQ-(z}B0eYRWI{icc-015=`@hC9y7G*6hDqkgIdKe?lmj_>kt6v6NlrU*yXlDgep z!@_sQzH~!~dPI20goaZ~CcReClqBx}0wF-F)?xOr9FVF*9sekh_y5PP{)|X87sijC zlmAB@C!p)i)6=e|hCKqaw4OhGiBvG$`$(v58_F1Z5~A<{oZeGG&nuNu%P?N>jlpEB zz3xqCkE%IAjS>hco5?WQzsx&t$(>?-V=A{5xY^oSb}olUA+%NXfjWj-w8UnVN0(+L z1%P=p{IAYD*hxAK7y4Ox$5mKY2JgjCB$?mhqMy7)Y3!7GU$#yBJS3YCRyP>P-aF#vq8-AvA{F@u&~G#BFdi6%`eWJxNK3R39jvN__J zEMHYLmQ(18(o{40Ruv%SxTGd5I~ueXP6^y;&;~OWBU4chypPkm#%|soQ901OQ!IGb z+)~TZAeP5smgtdqBPn%AHAnc##3tfg_mvb0C}T#Fczbmf)`V}xCEJPKRQdl+_&`av zdo)FthSz{>je=0CByWYnYXE8M2C<;Nx6N+4zT-#>%V_3Dz>V|Mzp3|6zWnMtOAT_L zweHZ?J!h#b9zCV4yzX!8(|V0GQnt^~8$5Kf<~NG$v0>*eWIG+dR68%JjHs(fTp^Co z%!%t$C&Wh@MV~45bi4or*LK=CW&ZKn>1GSVgmR=PpVekBn@@l)ualn9gZ=-DyKW8iSRjXSTYLpW!TN?;u#0HM>ii6d*rFw@0Nk5qtS2=#im z73k$W_ftFr7j#X9ESR)LJI<7n9&-!k&U*KUTJkB48M7?LeZM6yD_Z&xU+HRiyQI+5 zGgqTOc4baoR&VfFlrWQuHjY0!o*jtme*BEDq2f zJ6_TjAy2GSXVnTv4w!H*D#jq1V$kSbJ>b^h^5B;r#~yzp(n0>yNS!N?ABt7Gvr<)( zVcaj&>@b9qQ#=RS&EAm(9elUXSV-c}r`Z|jPZ)lyq%JBuy-m6XG+OV8-P6+(W`p9~EKO*i zp`3=VCvD74=KwZz8PaRAr0JLTv6~{OPNoF>qIrIUMLb6t z(^EO+wt|4b?ZJeTocXP{gQ|}XtRyy`Ua&g#d8*4`8YrjS;&K)PeRwd@U!IwdTxssW zRdmjrZg6b4%tMWk6J|v}sfjTvk~pWdwUV`xRj^pi%{Z&1Ic)rn6j~9_d;6*>=i|++ zq@>rY174_|V~xKT7yrL2zJZ6EoNQGJRqg05U~u)=m!oXTY47fH@WJg+)sl%E@N|j zvHmO0zxDZ@Gj+E0$3_2Rxl4(SEv|DXp~kEKczw)M#kguC{{DxJ;4wB_7ano2rUNuK zvAC8y>R8ha8~gcFC!0lOP%O?p#S<5NCQw_H*$3zG9F`9U*$AUE{NvfkNA!%*OpLN} z!?H5Ik=DB6?s7Awm&@f@Q{yU&MXrYc%+7!J4iY-Wa$-G460#(>6ZHhwliYah49vIc z67|>#olD@*Iy+%Z^jY4Z|FzAS19Ln<*M;> zpLI*kAQWYF+FV18kWpzUs#Dh+gqgL%#wbY5G`FnFFW;cp8h}WXSqoks@ji>}l?3te zrT9qhw=OBRY+6M4Ew(&y9gzv)<18n+{4b-d*(LZUyzL=LTxu}_%nxV7`YmK2gLXP9 z)xLVh&*{>^`77Pr437nNe+T|=@x;{6`r!|oS$aUul0F}Xl9sqLLA z>)IZ9?sldz_3c(8{;%pIOC6bPiJgUhUf)Y2j$Waz0d2m9pVgNhNhMq2T>*o2z6ire z3FKd^`brs5RIrgdc*lTpsuI6@F@{~0|6M+Ww}kbi*Rs8V%itnc+xVz=OpOI z+JgUT#T4ItyOs`2`RuBoCd7z{UJ{Etvnr?k*_ERyFSWUnL}&=VEa_@_*^7TGw!f6| zlhFyShNdNmfWZ)TG9_|xoCE#R+u#wELz(4Sgjbxx$S|yZg|yk^BT4SGWsEgv=T3nR zNtqNbnY}bt7*HN-LThsi02^Hs&=cFRW@X5gI?hMJ9FFTjM=_?>NTSQS6J=sV7_hv28@#4 z+z+ZgWi5~D%NXXH9G2>GVci=WQv`wwj6(}70j4r^&g3_7)e`IvqVRi*y>yMV6INP! ztQi77xa4z3MW`?%7J$CzH~S=GUwnH11M|O6(CPN?<7?CK9GktVM8~FzDH@2dfcV|& zdLIu0-9)DqMvm3>33=7rYrvdurJdwk&br0XQf8ob);@(r#`2&u?E*Nyr|7G{nc!OS zi@!79S19qdAswCD8rZm!INsM4yaw#a7xL!%d~HZFyRuea@@a|ow1|r;oZP4XekZoRHx>{Z)OR7+8UbQ zZ01Hh411JZpj;$*+Sm}QUpKr}YE`#Yutsjbm%0$O6qv;e3hugWJoKUB^_GUU+zgvo zsB=uP7$=Sej*=3yei~w`F;ed_oAydf+_uV^MIYZmQ%9?0<>#E?=WQpJcm5I#)xv%$ zw)NpZtY?2>7dcAvuG1lyijrtOdN>K+k8mEFF0R~93%`ZwN7_Hx^HEmho=ItCAXq!d zF+aY7q!lm7zzu{2&799b-wXDH>0{ch7k(@jkU!qE3t2q>18~0r@UQk`kfV=vvvS5! zz;+ksNT!jYR!G9!67VZXz?RfabyO1a_dt)hUQduU-tRZB?Gx$N71N3H)f&loF;st) z_MehpUHqFTVKh69c=e^}#v^G;;~~h2whqpM6~49&HPzRG&i&0^11QLyB|g^xs;}PSG>yFp#8X2S%>Ix~v{;W}oR>P({1e8L*8Dyqc01SY8Z1ubZ}B(L$KXs%l_>&}npV)^_WsqN_o zJCJn=bFcE?zrY@+{I8yUS9=SKR*$Rxu*lB)-1tOv3SvforjqO&7;F|5TYu?qJxqD0 z#q_Uz2e>WZ9>(zu_>BXaDQlpbGhw0-ZKLTZFDhpc9NeHw?=%kpti6lcQY3_xlS52k zv2}qEFUk8xd%FI+zL^_5ii zxhkct^3r=Mo^B4B=+yJ>tum^bL$J$3|J zX111tjJ8$4I}pJf>N~ndTiNMK+VTo0nIkgS!4uSqgIfjSBp??Ot}NB1&Mce$ZjANZ zH4-ZN>?8OFgTRoE!JLG%mN6s_`RQrzJ|cldL=s8$+I`vK)l57@JcvQ)uRxo-`t9RW z1n%AIZ%k8v7x&e&AeOAP1cFq0bj9w;$K;b6B{zHEb69Ug{g+oMky((Ty_nu;mMsCC z?^<##Tc%nglmci^6ESXXf9v*iNn38;X#v%9eb-}YKiJzh+BtgiJ!`tLe)$5&u|_me z)9ZYkO*Wf$F)xN!Z`u}ko*Ue`A|bW*+{4JYX@U0!`9Jbb!gPD~X*}DuisZ%O3}R>8 z#al{>mZ{|$phqxGTWFJFsx^9bLir=+X&Ctb$lNWHA@mEZvE`^f<Ci=$^g3tB2CwtE-Kb(l^Xd<`Wc-Jbo``ATa{z*z2mAL@p_^{c;!)22a%&-H%x7t?>p}9?pq66%&y%x{H`# zr#Z*R?Q5S=AW_o>Z20@3dfyX8Myuyb>-8t~-W$>j_F45t(y0zxITo_AnmM>wYLF|_Y+G_cf5qF?J#R;i~Ege8=iu&ZW!^jtw>y=CYx zlM57%6Sk>9-cJUu0b=FnHTS=t(sgJUZ=H`9HaYbC~&v1BhalgvL+3u#!HvJby9pe3@Ziq3DvYq-%Mt{3f|M;@-) zFBrAy(-AdG##FKaFK`}<}9{~mp$ct(P8fM`4<9vFag4)L`Qv zUaZ3_2631SiBocrqky*a*`5$PGWZXLAsmVe;b9itDv*xj%Pn zk*x7<11hSD6&a&6z8}4n2~nyyC_N%7Pp0bf0LJNz%A42gpt8Fn799=UKdQ!rsE98h zQZzFVGs~lCr!oB5bu}p(VZ5UNoria%gVT5{rpv#E`A#Hh%2wppDr2&<58kRGFL+}D zvo*3)LgdbBI(U&Ig25d6vh$O{p@`?2BY`=XyGB(taHaz$K|&lxGfg1S2Yop8Tyswx z-TAY=6$q}IkvZPaFRjN%-<@io{vo`raZz=U9L|~9RQEBbcHo>sGyB-!N@nBY_Tz}2 z#{T4E-wo%JJkRENDq6glFOr~^=33&a$N)Y6%f?Fm%98~OUNIlVkDKnn_Xk6Y*voV3 z(1-2fBlSVLvblBP6W?acJRk0`T1{Js&a<|t3?OBzzLnyJ9A@2i6%hZfa}YA6tlTdR z&t=Ao%%Q^Zc>?}?q_vD-jOiMwlSRgpJ%TT@CRtpnRdozm;&gfy@g?7n^E5%9;M2jY z;@vi{NfF&F5h$(7j^X)Sfe4UGQOg-T(_fxqiP7zKW>x~}GHVtltjdH~dUiBH2KG6? zJQv5gw-WrO*ZsdPr^$Vq`(kM9fUsL3RaRHWvmS9FA2T=YyBNpn`|fOi5ZP;Hb<k9YHfEiF1Fyo$y$qJWvi7;Ga0LC z{9=*^E4wjvTHaJ;w{IZRXoz?vs`X$J(Pw9a{#wQ!`Qr`W@&)azzJV-DP&!M3NAZ$O;bk*g{A_A@NZ~6)7nZ zTQE(F_T9j17P6r78Zd>#Y5<;bJ-ubbVZTGR%Gxll^L|b>q^sta?P4!bE>6x2;YI}4 zix|7_C|eg=Rw?p13{6a$RMB6rd)?!%?Vk(6XNV4uwK(e$OBM26qF>j(;DW{~-x_q4 z3l}B#eZ3Jag2Y{iP!{=hU^*LWv~53=-q^5Wx);2vHbp3aDJH~zP7ZY zFcnhdbS6omJrc0T^?FD~&rN*(LxE*wReqO>ZBD$7jPjN_R7hxYJ#l;oQs1vCI_*XL zEM>n_s_C2kZN;_*?>VZK$Lp&0i2zD&pIMfk4G6BkL@awy@wa>mi*YLn4F3F~bd0Ug zrxnBILWW^d%4PU3%M{ET(lKRJtLx+~A`LQo5_n7|TAz6F11DB5PL5OLZ8xuRUIFDt zM7KhcwxUUJ$iPcPgG%G|FrtNHF}}*ZrOX~iGt#}Fa$GQG-Hf3LnAZr6(>mOA{D1F> zlNl;8W|-1_o>(Ca{I-)=Y8}d-P7oqR{w+#re3@qUIq}NRGul_0k?9D!^Zt|&G7q|q zNrsJU*+96!&VxH8jKjzM{4maA)R?5+&8hv)NJn9IvD?ufEDkO)&oYmF$^`SwyV*SN zk`xy)@GN*=wwgOwUR$U1AWh3(6JrOGN;V?1G;W4ozIXG|)pm^3@-l<3|1IY}y&