msgid ""
msgstr ""
"Project-Id-Version: SONiC入门指南\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2023-06-25 20:04-0700\n"
"Last-Translator: r12f <r12f.code@gmail.com>\n"
"Language-Team: Chinese\n"
"Language: cn\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: src\SUMMARY.md:1
msgid "Summary"
msgstr "总结"

#: src\SUMMARY.md:3 src\1-intro.md:1
msgid "Getting Started with SONiC"
msgstr "SONiC入门指南"

#: src\SUMMARY.md:4 src\1-1-install.md:1
msgid "Installation"
msgstr "安装"

#: src\SUMMARY.md:5
msgid "Hello World! Virtually"
msgstr "虚拟环境中的Hello World!"

#: src\SUMMARY.md:6
msgid "Commands Cheatsheet (WIP)"
msgstr "命令速查表 (WIP)"

#: src\SUMMARY.md:7
msgid "Core Components Introduction"
msgstr "核心组件介绍"

#: src\SUMMARY.md:8
msgid "Redis Database"
msgstr "Redis数据库"

#: src\SUMMARY.md:9
msgid "Services and Workflows"
msgstr "服务和工作流"

#: src\SUMMARY.md:10
msgid "Key Containers"
msgstr "关键容器"

#: src\SUMMARY.md:11 src\2-4-sai-intro.md:1
msgid "SAI"
msgstr "SAI"

#: src\SUMMARY.md:12 src\3-dev-guide.md:1
msgid "Developer Guide"
msgstr "开发者指南"

#: src\SUMMARY.md:13 src\3-1-code-repos.md:1
msgid "Code Repositories"
msgstr "代码仓库"

#: src\SUMMARY.md:14 src\3-2-build.md:1
msgid "Build"
msgstr "编译"

#: src\SUMMARY.md:15
msgid "Testing (WIP)"
msgstr "测试 (WIP)"

#: src\SUMMARY.md:16
msgid "Debugging (WIP)"
msgstr "调试 (WIP)"

#: src\SUMMARY.md:17
msgid "SAI Debugging (WIP)"
msgstr "SAI调试 (WIP)"

#: src\SUMMARY.md:18
msgid "Service Communication"
msgstr "服务间通信"

#: src\SUMMARY.md:19 src\4-1-communicate-via-kernel.md:1
msgid "Communicate via Kernel"
msgstr "通过内核通信"

#: src\SUMMARY.md:20 src\4-1-1-exec.md:1
msgid "Command Line Invocation"
msgstr "命令行调用"

#: src\SUMMARY.md:21 src\4-1-2-netlink.md:1
msgid "Netlink"
msgstr "Netlink"

#: src\SUMMARY.md:22 src\4-2-redis-based-channels.md:1
msgid "Redis-based Channels"
msgstr "基于Redis的通道"

#: src\SUMMARY.md:23 src\4-2-1-redis-wrappers.md:1
msgid "Redis Wrappers"
msgstr "Redis封装"

#: src\SUMMARY.md:24 src\4-2-2-subscribe-state-table.md:1
msgid "SubscribeStateTable"
msgstr "SubscribeStateTable"

#: src\SUMMARY.md:25
msgid "NotificationProducer/Consumer"
msgstr "NotificationProducer/Consumer"

#: src\SUMMARY.md:26
msgid "Producer/ConsumerTable"
msgstr "Producer/ConsumerTable"

#: src\SUMMARY.md:27
msgid "Producer/ConsumerStateTable"
msgstr "Producer/ConsumerStateTable"

#: src\SUMMARY.md:28
msgid "ZMQ-based Channels (WIP)"
msgstr "基于ZMQ的通道 (WIP)"

#: src\SUMMARY.md:29
msgid "Orch Layer"
msgstr "Orch层"

#: src\SUMMARY.md:30
msgid "Event Polling and Error Handling"
msgstr "事件轮询和错误处理"

#: src\SUMMARY.md:31
msgid "Core Components Deep Dive"
msgstr "深入核心组件"

#: src\SUMMARY.md:32 src\5-1-syncd-and-sai.md:1
msgid "Syncd and SAI"
msgstr "Syncd和SAI"

#: src\SUMMARY.md:33 src\5-2-bgp.md:1
msgid "BGP"
msgstr "BGP"

#: src\SUMMARY.md:34 src\5-2-1-bgp-cli.md:1
msgid "BGP CLI and vtysh"
msgstr "BGP CLI和vtysh"

#: src\SUMMARY.md:35 src\5-2-2-route-update-in-frr.md:1
msgid "Route Update in FRR"
msgstr "FRR中的路由更新"

#: src\SUMMARY.md:36 src\5-2-3-route-update-in-sonic.md:1
msgid "Route Update in SONiC"
msgstr "SONiC中的路由更新"

#: src\SUMMARY.md:37
msgid "Boot Process (WIP)"
msgstr "启动过程 (WIP)"

#: src\SUMMARY.md:38
msgid "Cold Boot (WIP)"
msgstr "冷启动 (WIP)"

#: src\SUMMARY.md:39
msgid "Fast Boot (WIP)"
msgstr "快速启动 (WIP)"

#: src\SUMMARY.md:40
msgid "Warm Boot (WIP)"
msgstr "热启动 (WIP)"

#: src\1-1-install.md:3
msgid ""
"If you already own a switch or are planning to purchase one and install "
"SONiC on it, please read this section carefully. Otherwise, feel free to "
"skip it. :D"
msgstr ""

#: src\1-1-install.md:5
msgid "Switch Selection and SONiC Installation"
msgstr ""

#: src\1-1-install.md:7
msgid ""
"First, please confirm if your switch supports SONiC. The list of currently "
"supported switch models can be found [here](https://sonic-net.github.io/"
"SONiC/Supported-Devices-and-Platforms.html). If your switch model is not on "
"the list, you will need to contact the manufacturer to see if they have "
"plans to support SONiC. There are many switches that do not support SONiC, "
"such as:"
msgstr ""

#: src\1-1-install.md:9
msgid ""
"Regular switches for home use. These switches have relatively low hardware "
"configurations (even if they support high bandwidth, such as [MikroTik "
"CRS504-4XQ-IN](https://mikrotik.com/product/crs504_4xq_in), which supports "
"100GbE networks but only has 16MB of flash storage and 64MB of RAM, so it "
"can basically only run its own RouterOS)."
msgstr ""

#: src\1-1-install.md:10
msgid ""
"Some data center switches may not support SONiC due to their outdated models "
"and lack of manufacturer plans."
msgstr ""

#: src\1-1-install.md:12
msgid ""
"Regarding the installation process, since each manufacturer's switch design "
"is different, the underlying interfaces are also different, so the "
"installation methods vary. These differences mainly focus on two areas:"
msgstr ""

#: src\1-1-install.md:14
msgid ""
"Each manufacturer will have their own [SONiC Build](https://sonic-net.github."
"io/SONiC/Supported-Devices-and-Platforms.html), and some manufacturers will "
"extend development on top of SONiC to support more features for their "
"switches, such as [Dell Enterprise SONiC](https://www.dell.com/en-us/shop/"
"povw/sonic) and [EdgeCore Enterprise SONiC](https://www.edge-core.com/sonic."
"php). Therefore, you need to choose the corresponding version based on your "
"switch model."
msgstr ""

#: src\1-1-install.md:15
msgid ""
"Each manufacturer's switch will also support different installation methods, "
"some using USB to flash the ROM directly, and some using ONIE for "
"installation. This configuration needs to be done according to your specific "
"switch."
msgstr ""

#: src\1-1-install.md:17
msgid ""
"Although the installation methods may vary, the overall steps are similar. "
"Please contact your manufacturer to obtain the corresponding installation "
"documentation and follow the instructions to complete the installation."
msgstr ""

#: src\1-1-install.md:19
msgid "Configure the Switch"
msgstr ""

#: src\1-1-install.md:21
msgid ""
"After installation, we need to perform some basic settings. Some settings "
"are common, and we will summarize them here."
msgstr ""

#: src\1-1-install.md:23
msgid "Set the admin password"
msgstr ""

#: src\1-1-install.md:25
msgid ""
"The default SONiC account and password is `admin` and `YourPaSsWoRd`. Using "
"default password is obviously not secure. To change the password, we can run "
"the following command:"
msgstr ""

#: src\1-1-install.md:31
msgid "Set fan speed"
msgstr ""

#: src\1-1-install.md:33
msgid ""
"Data center switches are usually very noisy! For example, the switch I use "
"is Arista 7050QX-32S, which has 4 fans that can spin up to 17000 RPM. Even "
"if it is placed in the garage, the high-frequency whining can still be heard "
"behind 3 walls on the second floor. Therefore, if you are using it at home, "
"it is recommended to adjust the fan speed."
msgstr ""

#: src\1-1-install.md:35
msgid ""
"Unfortunately, [SONiC does not have CLI control over fan speed](https://"
"github.com/sonic-net/SONiC/blob/master/thermal-control-design.md), so we "
"need to manually modify the configuration file in the pmon container to "
"adjust the fan speed."
msgstr ""

#: src\1-1-install.md:38
msgid "# Enter the pmon container"
msgstr ""

#: src\1-1-install.md:40
msgid ""
"# Use pwmconfig to detect all PWM fans and create a configuration file. The "
"configuration file will be created at /etc/fancontrol."
msgstr ""

#: src\1-1-install.md:43
msgid ""
"# Start fancontrol and make sure it works. If it doesn't work, you can run "
"fancontrol directly to see what's wrong."
msgstr ""

#: src\1-1-install.md:45 src\1-1-install.md:46
msgid "1"
msgstr ""

#: src\1-1-install.md:47
msgid "# Exit the pmon container"
msgstr ""

#: src\1-1-install.md:50
msgid ""
"# Copy the configuration file from the container to the host, so that the "
"configuration will not be lost after reboot."
msgstr ""

#: src\1-1-install.md:51
msgid ""
"# This command needs to know what is the model of your switch. For example, "
"the command I need to run here is as follows. If your switch model is "
"different, please modify it accordingly."
msgstr ""

#: src\1-1-install.md:56
msgid "Set the Switch Management Port IP"
msgstr ""

#: src\1-1-install.md:58
msgid ""
"Data center switches usually can be connected via Serial Console, but its "
"speed is very slow. Therefore, after installation, it is better to set up "
"the Management Port as soon as possible, then use SSH connection."
msgstr ""

#: src\1-1-install.md:60
msgid ""
"Generally, the management port is named eth0, so we can use SONiC's "
"configuration command to set it up:"
msgstr ""

#: src\1-1-install.md:63
msgid "# sudo config interface ip add eth0 <ip-cidr> <gateway>"
msgstr ""

#: src\1-1-install.md:63
msgid "# IPv4"
msgstr ""

#: src\1-1-install.md:66
msgid "# IPv6"
msgstr ""

#: src\1-1-install.md:71
msgid "Create Network Configuration"
msgstr ""

#: src\1-1-install.md:73
msgid ""
"A newly installed SONiC switch will have a default network configuration, "
"which has many issues, such as using 10.0.0.0 IP on Ethernet0, as shown "
"below:"
msgstr ""

#: src\1-1-install.md:84
msgid ""
"Therefore, we need to update the ports with a new network configuration. A "
"simple method is to create a VLAN and use VLAN Routing:"
msgstr ""

#: src\1-1-install.md:87
msgid "# Create untagged VLAN"
msgstr ""

#: src\1-1-install.md:89
msgid "# Add IP to VLAN"
msgstr ""

#: src\1-1-install.md:92
msgid "# Remove all default IP settings"
msgstr ""

#: src\1-1-install.md:94
msgid "'{print \"sudo config interface ip remove\", $1, $2}'"
msgstr ""

#: src\1-1-install.md:95
msgid "# Add all ports to the new VLAN"
msgstr ""

#: src\1-1-install.md:97
msgid "'{print \"sudo config vlan member add -u 2\", $1}'"
msgstr ""

#: src\1-1-install.md:98
msgid ""
"# Enable proxy ARP, so the switch can respond to ARP requests from hosts"
msgstr ""

#: src\1-1-install.md:101
msgid "# Save the config, so it will be persistent after reboot"
msgstr ""

#: src\1-1-install.md:106
msgid "That's it! Now we can use `show vlan brief` to check it:"
msgstr ""

#: src\1-1-install.md:119
msgid "Configure the Host"
msgstr ""

#: src\1-1-install.md:121
msgid ""
"If you only have one host at home using multiple NICs to connect to the "
"switch for testing, we need to update some settings on the host to ensure "
"that traffic flows through the NIC and the switch. Otherwise, feel free to "
"skip this step."
msgstr ""

#: src\1-1-install.md:123
msgid ""
"There are many online guides for this, such as using DNAT and SNAT in "
"iptables to create a virtual address. However, after some experiments, I "
"found that the simplest way is to move one of the NICs to a new network "
"namespace, even if it uses the same IP subnet, it will still work."
msgstr ""

#: src\1-1-install.md:125
msgid ""
"For example, if I use Netronome Agilio CX 2x40GbE at home, it will create "
"two interfaces: `enp66s0np0` and `enp66s0np1`. Here, we can move "
"`enp66s0np1` to a new network namespace and configure the IP address:"
msgstr ""

#: src\1-1-install.md:128
msgid "# Create a new network namespace"
msgstr ""

#: src\1-1-install.md:130
msgid "# Move the interface to the new namespace"
msgstr ""

#: src\1-1-install.md:133
msgid "# Setting up IP and default routes"
msgstr ""

#: src\1-1-install.md:140
msgid ""
"That's it! We can start testing it using iperf and confirm on the switch:"
msgstr ""

#: src\1-1-install.md:143
msgid "# On the host (enp66s0np0 has IP 10.2.0.10 assigned)"
msgstr ""

#: src\1-1-install.md:145
msgid "# Test within the new network namespace"
msgstr ""

#: src\1-1-install.md:155
msgid "# Confirm on the switch"
msgstr ""

#: src\1-1-install.md:167
msgid ""
"[SONiC Thermal Control Design](https://github.com/sonic-net/SONiC/blob/"
"master/thermal-control-design.md)"
msgstr ""

#: src\1-1-install.md:168
msgid ""
"[Dell Enterprise SONiC Distribution](https://www.dell.com/en-us/shop/povw/"
"sonic)"
msgstr ""

#: src\1-1-install.md:169
msgid ""
"[Edgecore Enterprise SONiC  Distribution](https://www.edge-core.com/sonic."
"php)"
msgstr ""

#: src\1-1-install.md:170
msgid "[Mikrotik CRS504-4XQ-IN](https://mikrotik.com/product/crs504_4xq_in)"
msgstr ""

#: src\1-2-hello-world-virtually.md:1
msgid "Hello, World! Virtually"
msgstr ""

#: src\1-2-hello-world-virtually.md:3
msgid ""
"Although SONiC is powerful, most of the time the price of a switch that "
"supports SONiC OS is not cheap. If you just want to try SONiC without "
"spending money on a hardware device, then this chapter is a must-read. In "
"this chapter, we will summarize how to build a virtual SONiC lab using GNS3 "
"locally, allowing you to quickly experience the basic functionality of SONiC."
msgstr ""

#: src\1-2-hello-world-virtually.md:5
msgid ""
"There are several ways to run SONiC locally, such as docker + vswitch, p4 "
"software switch, etc. For first-time users, using GNS3 may be the most "
"convenient way, so here, we will use GNS3 as an example to explain how to "
"build a SONiC lab locally. So, let's get started!"
msgstr ""

#: src\1-2-hello-world-virtually.md:7
msgid "Prepare GNS3"
msgstr ""

#: src\1-2-hello-world-virtually.md:9
msgid ""
"First, in order to easily and intuitively establish a virtual network for "
"testing, we need to install GNS3."
msgstr ""

#: src\1-2-hello-world-virtually.md:11
msgid ""
"[GNS3, short for Graphical Network Simulator 3, is (obviously) a graphical "
"network simulation software](https://www.gns3.com/). It supports various "
"virtualization technologies such as QEMU, VMware, VirtualBox, etc. With it, "
"when we build a virtual network, we don't have to run many commands manually "
"or write scripts. Most of the work can be done through its GUI, which is "
"very convenient."
msgstr ""

#: src\1-2-hello-world-virtually.md:13
msgid "Install Dependencies"
msgstr ""

#: src\1-2-hello-world-virtually.md:15
msgid ""
"Before installing it, we need to install several other software: docker, "
"wireshark, putty, qemu, ubridge, libvirt, and bridge-utils. If you have "
"already installed them, you can skip this step."
msgstr ""

#: src\1-2-hello-world-virtually.md:17
msgid ""
"First is Docker. You can install it by following the instructions in this "
"link: [https://docs.docker.com/engine/install/](https://docs.docker.com/"
"engine/install/)"
msgstr ""

#: src\1-2-hello-world-virtually.md:19
msgid ""
"Installing the others on Ubuntu is very simple, just execute the following "
"command. Note that during the installation of ubridge and Wireshark, you "
"will be asked if you want to create the wireshark user group to bypass sudo. "
"Be sure to choose Yes."
msgstr ""

#: src\1-2-hello-world-virtually.md:25
msgid "Once completed, we can proceed to install GNS3."
msgstr ""

#: src\1-2-hello-world-virtually.md:27
msgid "Install GNS3"
msgstr ""

#: src\1-2-hello-world-virtually.md:30
msgid ""
"On Ubuntu, the installation of GNS3 is very simple, just execute the "
"following commands:"
msgstr ""

#: src\1-2-hello-world-virtually.md:38
msgid ""
"Then add your user to the following groups, so that GNS3 can access docker, "
"wireshark, and other functionalities without using sudo."
msgstr ""

#: src\1-2-hello-world-virtually.md:46
msgid ""
"If you are not using Ubuntu, you can refer to [their official documentation]"
"(https://docs.gns3.com/docs/getting-started/installation/linux/) for more "
"detailed installation instructions."
msgstr ""

#: src\1-2-hello-world-virtually.md:48
msgid "Prepare the SONiC Image"
msgstr ""

#: src\1-2-hello-world-virtually.md:50
msgid ""
"Before testing, we need a SONiC image. Since SONiC supports various vendors "
"with different underlying implementations, each vendor has their own image. "
"In our case, since we are creating a virtual environment, we can use the "
"VSwitch-based image to create virtual switches: sonic-vs.img.gz."
msgstr ""

#: src\1-2-hello-world-virtually.md:52
msgid ""
"[The SONiC image project is located here](https://github.com/sonic-net/sonic-"
"buildimage). Although we can compile it ourselves, the process can be slow. "
"To save time, we can directly [download the latest image from here](https://"
"sonic-build.azurewebsites.net/ui/sonic/pipelines/142/builds?"
"branchName=master). Just find the latest successful build and download the "
"sonic-vs.img.gz file from the Artifacts section."
msgstr ""

#: src\1-2-hello-world-virtually.md:54
msgid "Next, let's prepare the project:"
msgstr ""

#: src\1-2-hello-world-virtually.md:59
msgid ""
"# Place the downloaded image in this directory and then run the following "
"command to extract it."
msgstr ""

#: src\1-2-hello-world-virtually.md:62
msgid ""
"# The following command will generate the GNS3 image configuration file."
msgstr ""

#: src\1-2-hello-world-virtually.md:67
msgid ""
"After executing the above commands, you can run the `ls` command to see the "
"required image file."
msgstr ""

#: src\1-2-hello-world-virtually.md:74
msgid "# <= This is the GNS3 image configuration file"
msgstr ""

#: src\1-2-hello-world-virtually.md:75
msgid "# <= This is the image we extracted"
msgstr ""

#: src\1-2-hello-world-virtually.md:79
msgid "Import the Image"
msgstr ""

#: src\1-2-hello-world-virtually.md:81
msgid ""
"Now, run `gns3` in the command line to start GNS3. If you are SSHed into "
"another machine, you can try enabling X11 forwarding so that you can run "
"GNS3 remotely, with the GUI displayed locally on your machine. And I made "
"this working using MobaXterm on my local machine."
msgstr ""

#: src\1-2-hello-world-virtually.md:83
msgid ""
"Once it's up and running, GNS3 will prompt us to create a project. It's "
"simple, just enter a directory. If you are using X11 forwarding, please note "
"that this directory is on your remote server, not local."
msgstr ""

#: src\1-2-hello-world-virtually.md:85
msgid "![](assets/chapter-1/gns3-new-project.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:87
msgid ""
"Next, we can import the image we just generated by going to `File -> Import "
"appliance`."
msgstr ""

#: src\1-2-hello-world-virtually.md:89
msgid "![](assets/chapter-1/gns3-import-appliance-menu.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:91
msgid ""
"Select the `SONiC-latest.gns3a` image configuration file we just generated "
"and click `Next`."
msgstr ""

#: src\1-2-hello-world-virtually.md:93
msgid "![](assets/chapter-1/gns3-import-appliance-select-image.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:95
msgid "Now you can see our image, click `Next`."
msgstr ""

#: src\1-2-hello-world-virtually.md:97
msgid "![](assets/chapter-1/gns3-import-appliance-image.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:99
msgid ""
"At this point, the image import process will start, which may be slow "
"because GNS3 needs to convert the image to qcow2 format and place it in our "
"project directory. Once completed, we can see our image."
msgstr ""

#: src\1-2-hello-world-virtually.md:101
msgid "![](assets/chapter-1/gns3-import-appliance-done.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:103
msgid "Great! We're done!"
msgstr ""

#: src\1-2-hello-world-virtually.md:105
msgid "Create the Network"
msgstr ""

#: src\1-2-hello-world-virtually.md:107
msgid "Alright! Now that everything is set up, let's create a virtual network!"
msgstr ""

#: src\1-2-hello-world-virtually.md:109
msgid ""
"The GNS3 graphical interface is very user-friendly. Basically, open the "
"sidebar, drag in the switch, drag in the VPC, and then connect the ports. "
"After connecting, remember to click the Play button at the top to start the "
"network simulation. We won't go into much detail here, let's just look at "
"the pictures."
msgstr ""

#: src\1-2-hello-world-virtually.md:111
msgid "![](assets/chapter-1/gns3-console.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:113
msgid ""
"Next, right-click on the switch, select `Custom Console`, then select Putty "
"to open the console of the switch we saw earlier. Here, the default username "
"and password for SONiC are `admin` and `YourPaSsWoRd`. Once logged in, we "
"can run familiar commands like `show interfaces status` or `show ip "
"interface` to check the network status. Here, we can also see that the "
"status of the first two interfaces we connected is `up`."
msgstr ""

#: src\1-2-hello-world-virtually.md:115
msgid "Configure the Network"
msgstr ""

#: src\1-2-hello-world-virtually.md:117
msgid ""
"In SONiC software switches, the default ports use the 10.0.0.x subnet (as "
"shown below) with neighbor paired."
msgstr ""

#: src\1-2-hello-world-virtually.md:128
msgid ""
"Similar to what we mentioned in [installation](./1-1-install.md), we are "
"going to create a simple network by creating a small VLAN and including our "
"ports in it (in this case, Ethernet4 and Ethernet8):"
msgstr ""

#: src\1-2-hello-world-virtually.md:131
msgid "# Remove old config"
msgstr ""

#: src\1-2-hello-world-virtually.md:134
msgid "# Create VLAN with id 2"
msgstr ""

#: src\1-2-hello-world-virtually.md:137
msgid "# Add ports to VLAN"
msgstr ""

#: src\1-2-hello-world-virtually.md:141
msgid "# Add IP address to VLAN"
msgstr ""

#: src\1-2-hello-world-virtually.md:146
msgid "Now, our VLAN is created, and we can use `show vlan brief` to check:"
msgstr ""

#: src\1-2-hello-world-virtually.md:152
msgid ""
"==========+==============+===========+================+============="
"+=======================+"
msgstr ""

#: src\1-2-hello-world-virtually.md:158
msgid "Now, let's assign a 10.0.0.x IP address to each host."
msgstr ""

#: src\1-2-hello-world-virtually.md:161
msgid "# VPC1"
msgstr ""

#: src\1-2-hello-world-virtually.md:163
msgid "# VPC2"
msgstr ""

#: src\1-2-hello-world-virtually.md:168
msgid "Alright, let's start the ping!"
msgstr ""

#: src\1-2-hello-world-virtually.md:170
msgid "![](assets/chapter-1/gns3-ping.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:172
msgid "It works!"
msgstr ""

#: src\1-2-hello-world-virtually.md:174
msgid "Packet Capture"
msgstr ""

#: src\1-2-hello-world-virtually.md:176
msgid ""
"Before installing GNS3, we installed Wireshark so that we can capture "
"packets within the virtual network created by GNS3. To start capturing, "
"simply right-click on the link you want to capture on and select `Start "
"capture`."
msgstr ""

#: src\1-2-hello-world-virtually.md:178
msgid "![](assets/chapter-1/gns3-capture.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:180
msgid ""
"After a moment, Wireshark will automatically open and display all the "
"packets in real-time. Very convenient!"
msgstr ""

#: src\1-2-hello-world-virtually.md:182
msgid "![](assets/chapter-1/gns3-capture-live.png)"
msgstr ""

#: src\1-2-hello-world-virtually.md:184
msgid "More Networks"
msgstr ""

#: src\1-2-hello-world-virtually.md:186
msgid ""
"In addition to the simplest network setup we discussed above, we can "
"actually use GNS3 to build much more complex networks for testing, such as "
"multi-layer ECMP + eBGP, and more. XFlow Research has published a very "
"detailed document that covers these topics. Interested folks can refer to "
"the document: [SONiC Deployment and Testing Using GNS3](https://"
"xflowresearch.com/wp-content/uploads/2023/05/SONiC-Deployment-and-Testing-"
"Using-GNS3.pdf)."
msgstr ""

#: src\1-2-hello-world-virtually.md:190
msgid "[GNS3](https://www.gns3.com/)"
msgstr ""

#: src\1-2-hello-world-virtually.md:191
msgid ""
"[GNS3 Linux Install](https://docs.gns3.com/docs/getting-started/installation/"
"linux/)"
msgstr ""

#: src\1-2-hello-world-virtually.md:192
msgid ""
"[SONiC Deployment and Testing Using GNS3](https://xflowresearch.com/wp-"
"content/uploads/2023/05/SONiC-Deployment-and-Testing-Using-GNS3.pdf)"
msgstr ""

#: src\1-3-command-cheatsheet.md:2
msgid "Common Commands"
msgstr ""

#: src\1-3-command-cheatsheet.md:4
msgid ""
"To help us check and configure the state of SONiC, SONiC provides a large "
"number of CLI commands for us to use. These commands are mostly divided into "
"two categories: `show` and `config`. Their formats are generally similar, "
"mostly following the format below:"
msgstr ""

#: src\1-3-command-cheatsheet.md:11
msgid ""
"The SONiC documentation provides a very detailed list of commands: [SONiC "
"Command Line Interface Guide](https://github.com/sonic-net/sonic-utilities/"
"blob/master/doc/Command-Reference.md), but due to the large number of "
"commands, it is not very convenient for us to ramp up, so we listed some of "
"the most commonly used commands and explanations for reference."
msgstr ""

#: src\1-3-command-cheatsheet.md:34
msgid "Basic system information"
msgstr ""

#: src\1-3-command-cheatsheet.md:37
msgid "# Show system version, platform info and docker containers"
msgstr ""

#: src\1-3-command-cheatsheet.md:39
msgid "# Show system uptime"
msgstr ""

#: src\1-3-command-cheatsheet.md:42
msgid "# Show platform information, such as HWSKU"
msgstr ""

#: src\1-3-command-cheatsheet.md:47
msgid "Config"
msgstr ""

#: src\1-3-command-cheatsheet.md:50
msgid "# Reload all config."
msgstr ""

#: src\1-3-command-cheatsheet.md:50
msgid ""
"# WARNING: This will restart almost all services and will cause network "
"interruption."
msgstr ""

#: src\1-3-command-cheatsheet.md:53
msgid ""
"# Save the current config from redis DB to disk, which makes the config "
"persistent across reboots."
msgstr ""

#: src\1-3-command-cheatsheet.md:54
msgid "# NOTE: The config file is saved to `/etc/sonic/config_db.json`"
msgstr ""

#: src\1-3-command-cheatsheet.md:59
msgid "Docker Related"
msgstr ""

#: src\1-3-command-cheatsheet.md:62
msgid "# Show all docker containers"
msgstr ""

#: src\1-3-command-cheatsheet.md:64
msgid "# Show processes running in a container"
msgstr ""

#: src\1-3-command-cheatsheet.md:67
msgid "# Enter the container"
msgstr ""

#: src\1-3-command-cheatsheet.md:85
msgid "Interfaces / IPs"
msgstr ""

#: src\1-3-command-cheatsheet.md:98
msgid "MAC / ARP / NDP"
msgstr ""

#: src\1-3-command-cheatsheet.md:101
msgid "# Show MAC (FDB) entries"
msgstr ""

#: src\1-3-command-cheatsheet.md:103
msgid "# Show IP ARP table"
msgstr ""

#: src\1-3-command-cheatsheet.md:106
msgid "# Show IPv6 NDP table"
msgstr ""

#: src\1-3-command-cheatsheet.md:111
msgid "BGP / Routes"
msgstr ""

#: src\1-3-command-cheatsheet.md:128
msgid "LLDP"
msgstr ""

#: src\1-3-command-cheatsheet.md:131
msgid "# Show LLDP neighbors in table format"
msgstr ""

#: src\1-3-command-cheatsheet.md:133
msgid "# Show LLDP neighbors details"
msgstr ""

#: src\1-3-command-cheatsheet.md:138
msgid "VLAN"
msgstr ""

#: src\1-3-command-cheatsheet.md:144
msgid "QoS Related"
msgstr ""

#: src\1-3-command-cheatsheet.md:147
msgid "# Show PFC watchdog stats"
msgstr ""

#: src\1-3-command-cheatsheet.md:152
msgid "ACL"
msgstr ""

#: src\1-3-command-cheatsheet.md:159
msgid "MUXcable / Dual ToR"
msgstr ""

#: src\1-3-command-cheatsheet.md:161
msgid "Muxcable mode"
msgstr ""

#: src\1-3-command-cheatsheet.md:168
msgid "Muxcable config"
msgstr ""

#: src\1-3-command-cheatsheet.md:174
msgid "Muxcable status"
msgstr ""

#: src\1-3-command-cheatsheet.md:180
msgid "Muxcable firmware"
msgstr ""

#: src\1-3-command-cheatsheet.md:183
msgid "# Firmware version:"
msgstr ""

#: src\1-3-command-cheatsheet.md:185
msgid "# Firmware download"
msgstr ""

#: src\1-3-command-cheatsheet.md:186
msgid "# config muxcable firmware download <firmware_file> <port_name> "
msgstr ""

#: src\1-3-command-cheatsheet.md:189
msgid "# Rollback:"
msgstr ""

#: src\1-3-command-cheatsheet.md:190
msgid "# config muxcable firmware rollback <port_name>"
msgstr ""

#: src\1-3-command-cheatsheet.md:197
msgid ""
"[SONiC Command Line Interface Guide](https://github.com/sonic-net/sonic-"
"utilities/blob/master/doc/Command-Reference.md)"
msgstr ""

#: src\2-core-components-intro.md:1
msgid "Core components"
msgstr ""

#: src\2-core-components-intro.md:3
msgid ""
"We might feel that a switch is a simple network device, but in fact, there "
"could be many components running on the switch."
msgstr ""

#: src\2-core-components-intro.md:5
msgid ""
"Since SONiC decoupled all its services using Redis, it can be difficult to "
"understand the relationships between services by simpling tracking the code. "
"To get started on SONiC quickly, it is better to first establish a high-"
"level model, and then delve into the details of each component. Therefore, "
"before diving into other parts, we will first give a brief introduction to "
"each component to help everyone build a rough overall model."
msgstr ""

#: src\2-core-components-intro.md:13
msgid ""
"In addition, to help us get started, we placed the SONiC architecture "
"diagram here again as a reference:"
msgstr ""

#: src\2-core-components-intro.md:15
msgid "![](assets/chapter-2/sonic-arch.png)"
msgstr ""

#: src\2-core-components-intro.md:21 src\2-1-database.md:78
#: src\2-2-services-intro.md:76 src\2-3-key-containers.md:183
#: src\2-4-sai-intro.md:166 src\3-1-code-repos.md:135
#: src\4-communications.md:21 src\4-2-1-redis-wrappers.md:34
#: src\4-2-2-subscribe-state-table.md:73
#: src\4-2-3-notification-producer-consumer.md:54
#: src\4-2-4-producer-consumer-table.md:130
#: src\4-2-5-producer-consumer-state-table.md:125 src\4-4-orch-layer.md:36
#: src\4-5-event-polling-and-error-handling.md:123
#: src\5-1-syncd-and-sai.md:824 src\5-2-bgp.md:34 src\5-2-1-bgp-cli.md:91
#: src\5-2-2-route-update-in-frr.md:737 src\5-2-3-route-update-in-sonic.md:736
msgid ""
"[SONiC Architecture](https://github.com/sonic-net/SONiC/wiki/Architecture)"
msgstr ""

#: src\2-core-components-intro.md:22 src\2-4-sai-intro.md:167
#: src\3-1-code-repos.md:138
msgid "[SAI API](https://github.com/opencomputeproject/SAI/wiki/SAI-APIs)"
msgstr ""

#: src\2-core-components-intro.md:23 src\2-4-sai-intro.md:168
msgid ""
"[Forwarding Metamorphosis: Fast Programmable Match-Action Processing in "
"Hardware for SDN](http://yuba.stanford.edu/~grg/docs/sdn-chip-sigcomm-2013."
"pdf)"
msgstr ""

#: src\2-1-database.md:1
msgid "Redis database"
msgstr ""

#: src\2-1-database.md:3
msgid ""
"First and foremost, the core service in SONiC is undoubtedly the central "
"database - Redis! It has two major purposes: storing the configuration and "
"state of all services, and providing a communication channel for these "
"services."
msgstr ""

#: src\2-1-database.md:5
msgid ""
"To provide these functionalities, SONiC creates a database instance in Redis "
"named `sonic-db`. The configuration and database partitioning information "
"can be found in `/var/run/redis/sonic-db/database_config.json`:"
msgstr ""

#: src\2-1-database.md:10
msgid "\"INSTANCES\""
msgstr ""

#: src\2-1-database.md:11 src\2-1-database.md:19 src\2-1-database.md:20
#: src\2-1-database.md:21 src\2-1-database.md:22 src\2-1-database.md:23
#: src\2-1-database.md:24 src\2-1-database.md:25 src\2-1-database.md:26
#: src\2-1-database.md:27 src\2-1-database.md:28 src\2-1-database.md:29
#: src\2-1-database.md:30 src\2-1-database.md:31 src\2-1-database.md:32
msgid "\"redis\""
msgstr ""

#: src\2-1-database.md:12
msgid "\"hostname\""
msgstr ""

#: src\2-1-database.md:12
msgid "\"127.0.0.1\""
msgstr ""

#: src\2-1-database.md:13
msgid "\"port\""
msgstr ""

#: src\2-1-database.md:14
msgid "\"unix_socket_path\""
msgstr ""

#: src\2-1-database.md:14
msgid "\"/var/run/redis/redis.sock\""
msgstr ""

#: src\2-1-database.md:15
msgid "\"persistence_for_warm_boot\""
msgstr ""

#: src\2-1-database.md:15
msgid "\"yes\""
msgstr ""

#: src\2-1-database.md:18
msgid "\"DATABASES\""
msgstr ""

#: src\2-1-database.md:19 src\5-2-3-route-update-in-sonic.md:50
msgid "\"APPL_DB\""
msgstr ""

#: src\2-1-database.md:19 src\2-1-database.md:20 src\2-1-database.md:21
#: src\2-1-database.md:22 src\2-1-database.md:23 src\2-1-database.md:24
#: src\2-1-database.md:25 src\2-1-database.md:26 src\2-1-database.md:27
#: src\2-1-database.md:28 src\2-1-database.md:29 src\2-1-database.md:30
#: src\2-1-database.md:31 src\2-1-database.md:32
msgid "\"id\""
msgstr ""

#: src\2-1-database.md:19 src\2-1-database.md:20 src\2-1-database.md:21
#: src\2-1-database.md:22 src\2-1-database.md:23 src\2-1-database.md:24
#: src\2-1-database.md:25 src\2-1-database.md:26 src\2-1-database.md:27
#: src\2-1-database.md:28 src\2-1-database.md:29 src\2-1-database.md:30
#: src\2-1-database.md:31 src\2-1-database.md:32
msgid "\"separator\""
msgstr ""

#: src\2-1-database.md:19 src\2-1-database.md:20 src\2-1-database.md:21
#: src\2-1-database.md:22 src\2-1-database.md:24 src\2-1-database.md:25
#: src\2-1-database.md:29 src\2-1-database.md:30 src\2-1-database.md:31
#: src\2-1-database.md:32 src\5-1-syncd-and-sai.md:498
#: src\5-2-3-route-update-in-sonic.md:682
msgid "\":\""
msgstr ""

#: src\2-1-database.md:19 src\2-1-database.md:20 src\2-1-database.md:21
#: src\2-1-database.md:22 src\2-1-database.md:23 src\2-1-database.md:24
#: src\2-1-database.md:25 src\2-1-database.md:26 src\2-1-database.md:27
#: src\2-1-database.md:28 src\2-1-database.md:29 src\2-1-database.md:30
#: src\2-1-database.md:31 src\2-1-database.md:32
msgid "\"instance\""
msgstr ""

#: src\2-1-database.md:20
msgid "\"ASIC_DB\""
msgstr ""

#: src\2-1-database.md:21
msgid "\"COUNTERS_DB\""
msgstr ""

#: src\2-1-database.md:22
msgid "\"LOGLEVEL_DB\""
msgstr ""

#: src\2-1-database.md:23
msgid "\"CONFIG_DB\""
msgstr ""

#: src\2-1-database.md:23 src\2-1-database.md:26 src\2-1-database.md:27
#: src\2-1-database.md:28
msgid "\"|\""
msgstr ""

#: src\2-1-database.md:24
msgid "\"PFC_WD_DB\""
msgstr ""

#: src\2-1-database.md:25
msgid "\"FLEX_COUNTER_DB\""
msgstr ""

#: src\2-1-database.md:26
msgid "\"STATE_DB\""
msgstr ""

#: src\2-1-database.md:27
msgid "\"SNMP_OVERLAY_DB\""
msgstr ""

#: src\2-1-database.md:28
msgid "\"RESTAPI_DB\""
msgstr ""

#: src\2-1-database.md:29
msgid "\"GB_ASIC_DB\""
msgstr ""

#: src\2-1-database.md:30
msgid "\"GB_COUNTERS_DB\""
msgstr ""

#: src\2-1-database.md:31
msgid "\"GB_FLEX_COUNTER_DB\""
msgstr ""

#: src\2-1-database.md:32
msgid "\"APPL_STATE_DB\""
msgstr ""

#: src\2-1-database.md:34
msgid "\"VERSION\""
msgstr ""

#: src\2-1-database.md:34
msgid "\"1.0\""
msgstr ""

#: src\2-1-database.md:38
msgid ""
"Although we can see that there are about a dozen databases in SONiC, most of "
"the time we only need to focus on the following most important ones:"
msgstr ""

#: src\2-1-database.md:40
msgid ""
"**CONFIG_DB (ID = 4)**: Stores the **configuration** of all services, such "
"as port configuration, VLAN configuration, etc. It represents the data model "
"of the **desired state of the switch** as intended by the user. This is also "
"the main object of operation when all CLI and external applications modify "
"the configuration."
msgstr ""

#: src\2-1-database.md:41
msgid ""
"**APPL_DB (Application DB, ID = 0)**: Stores **internal state information of "
"all services**. It contains two types of information:"
msgstr ""

#: src\2-1-database.md:42
msgid ""
"One is calculated by each service after reading the configuration "
"information from CONFIG_DB, which can be understood as the **desired state "
"of the switch** (Goal State) but from the perspective of each service."
msgstr ""

#: src\2-1-database.md:43
msgid ""
"The other is when the ASIC state changes and is written back, some services "
"write directly to APPL_DB instead of the STATE_DB we will introduce next. "
"This information can be understood as the **current state of the switch** as "
"perceived by each service."
msgstr ""

#: src\2-1-database.md:44
msgid ""
"**STATE_DB (ID = 6)**: Stores the **current state** of various components of "
"the switch. When a service in SONiC receives a state change from STATE_DB "
"and finds it inconsistent with the Goal State, SONiC will reapply the "
"configuration until the two states are consistent. (Of course, for those "
"states written back to APPL_DB, the service will monitor changes in APPL_DB "
"instead of STATE_DB.)"
msgstr ""

#: src\2-1-database.md:45
msgid ""
"**ASIC_DB (ID = 1)**: Stores the **desired state information** of the switch "
"ASIC in SONiC, such as ACL, routing, etc. Unlike APPL_DB, the data model in "
"this database is designed for ASIC rather than service abstraction. This "
"design facilitates the development of SAI and ASIC drivers by various "
"vendors."
msgstr ""

#: src\2-1-database.md:47
msgid ""
"Now, we have an intuitive question: with so many services in the switch, are "
"all configurations and states stored in a single database without isolation? "
"What if two services use the same Redis Key? This is a very good question, "
"and SONiC's solution is straightforward: continue to partition each database "
"into tables!"
msgstr ""

#: src\2-1-database.md:49
msgid ""
"We know that Redis does not have the concept of tables within each database "
"but uses key-value pairs to store data. Therefore, to further partition "
"tables, SONiC's solution is to include the table name in the key and "
"separate the table and key with a delimiter. The `separator` field in the "
"configuration file above serves this purpose. For example, the state of the "
"`Ethernet4` port in the `PORT_TABLE` table in `APPL_DB` can be accessed "
"using `PORT_TABLE:Ethernet4` as follows:"
msgstr ""

#: src\2-1-database.md:56
msgid "\"admin_status\""
msgstr ""

#: src\2-1-database.md:57 src\2-1-database.md:71 src\4-1-2-netlink.md:68
msgid "\"up\""
msgstr ""

#: src\2-1-database.md:58
msgid "\"alias\""
msgstr ""

#: src\2-1-database.md:59
msgid "\"Ethernet6/1\""
msgstr ""

#: src\2-1-database.md:60
msgid "\"index\""
msgstr ""

#: src\2-1-database.md:61
msgid "\"6\""
msgstr ""

#: src\2-1-database.md:62
msgid "\"lanes\""
msgstr ""

#: src\2-1-database.md:63
msgid "\"13,14,15,16\""
msgstr ""

#: src\2-1-database.md:64
msgid "\"mtu\""
msgstr ""

#: src\2-1-database.md:65
msgid "\"9100\""
msgstr ""

#: src\2-1-database.md:66
msgid "\"speed\""
msgstr ""

#: src\2-1-database.md:67
msgid "\"40000\""
msgstr ""

#: src\2-1-database.md:68
msgid "\"description\""
msgstr ""

#: src\2-1-database.md:69 src\5-2-3-route-update-in-sonic.md:307
msgid "\"\""
msgstr ""

#: src\2-1-database.md:70 src\4-1-2-netlink.md:68
msgid "\"oper_status\""
msgstr ""

#: src\2-1-database.md:74
msgid ""
"Of course, in SONiC, not only the data model but also the communication "
"mechanism uses a similar method to achieve \"table\" level isolation."
msgstr ""

#: src\2-2-services-intro.md:2
msgid "Introduction to Services and Workflows"
msgstr ""

#: src\2-2-services-intro.md:4
msgid ""
"There are many services (daemon processes) in SONiC, around twenty to "
"thirty. They start with the switch and keep running until the switch is shut "
"down. If we want to quickly understand how SONiC works, diving into each "
"service one by one is obviously not a good option. Therefore, it is better "
"to categorize these services and control flows on high level to help us "
"build a big picture."
msgstr ""

#: src\2-2-services-intro.md:10
msgid "Service Categories"
msgstr ""

#: src\2-2-services-intro.md:12
msgid ""
"Generally speaking, the services in SONiC can be divided into the following "
"categories: `*syncd`, `*mgrd`, feature implementations, `orchagent`, and "
"`syncd`."
msgstr ""

#: src\2-2-services-intro.md:14
msgid "`*syncd` Services"
msgstr ""

#: src\2-2-services-intro.md:16
msgid ""
"These services have names ending with `syncd`. They perform similar tasks: "
"synchronizing hardware states to Redis, usually into APPL_DB or STATE_DB."
msgstr ""

#: src\2-2-services-intro.md:18
msgid ""
"For example, `portsyncd` listens to netlink events and synchronizes the "
"status of all ports in the switch to STATE_DB, while `natsyncd` listens to "
"netlink events and synchronizes all NAT statuses in the switch to APPL_DB."
msgstr ""

#: src\2-2-services-intro.md:20
msgid "`*mgrd` Services"
msgstr ""

#: src\2-2-services-intro.md:22
msgid ""
"These services have names ending with `mgrd`. As the name suggests, these "
"are \"Manager\" services responsible for configuring various hardware, "
"opposite to `*syncd`. Their logic mainly consists of two parts:"
msgstr ""

#: src\2-2-services-intro.md:24
msgid ""
"**Configuration Deployment**: Responsible for reading configuration files "
"and listening to configuration and state changes in Redis (mainly CONFIG_DB, "
"APPL_DB, and STATE_DB), then pushing these changes to the switch hardware. "
"The method of pushing varies depending on the target, either by updating "
"APPL_DB and publishing update messages or directly calling Linux command "
"lines to modify the system. For example, `nbrmgr` listens to changes in "
"CONFIG_DB, APPL_DB, and STATE_DB for neighbors and modifies neighbors and "
"routes using netlink and command lines, while `intfmgr` not only calls "
"command lines but also updates some states to APPL_DB."
msgstr ""

#: src\2-2-services-intro.md:25
msgid ""
"**State Synchronization**: For services that need reconciliation, `*mgrd` "
"also listens to state changes in STATE_DB. If it finds that the hardware "
"state is inconsistent with the expected state, it will re-initiate the "
"configuration process to set the hardware state to the expected state. These "
"state changes in STATE_DB are usually pushed by `*syncd` services. For "
"example, `intfmgr` listens to port up/down status and MTU changes pushed by "
"`portsyncd` in STATE_DB. If it finds inconsistencies with the expected state "
"stored in its memory, it will re-deploy the configuration."
msgstr ""

#: src\2-2-services-intro.md:27
msgid "`orchagent` Service"
msgstr ""

#: src\2-2-services-intro.md:29
msgid ""
"This is the most important service in SONiC. Unlike other services that are "
"responsible for one or two specific functions, `orchagent`, as the "
"orchestrator of the switch ASIC state, checks all states from `*syncd` "
"services in the database, integrates them, and deploys them to ASIC_DB, "
"which is used to store the switch ASIC configuration. These states are "
"eventually received by `syncd`, which calls the SAI API through the SAI "
"implementation and ASIC SDK provided by various vendors to interact with the "
"ASIC, ultimately deploying the configuration to the switch hardware."
msgstr ""

#: src\2-2-services-intro.md:31
msgid "Feature Implementation Services"
msgstr ""

#: src\2-2-services-intro.md:33
msgid ""
"Some features are not implemented by the OS itself but by specific "
"processes, such as BGP or some external-facing interfaces. These services "
"often have names ending with `d`, indicating daemon, such as `bgpd`, "
"`lldpd`, `snmpd`, `teamd`, etc., or simply the name of the feature, such as "
"`fancontrol`."
msgstr ""

#: src\2-2-services-intro.md:35
msgid "`syncd` Service"
msgstr ""

#: src\2-2-services-intro.md:37
msgid ""
"The `syncd` service is downstream of `orchagent`. Although its name is "
"`syncd`, it shoulders the work of both `*mgrd` and `*syncd` for the ASIC."
msgstr ""

#: src\2-2-services-intro.md:39
msgid ""
"First, as `*mgrd`, it listens to state changes in ASIC_DB. Once detected, it "
"retrieves the new state and calls the SAI API to deploy the configuration to "
"the switch hardware."
msgstr ""

#: src\2-2-services-intro.md:40
msgid ""
"Then, as `*syncd`, if the ASIC sends any notifications to SONiC, it will "
"send these notifications to Redis as messages, allowing `orchagent` and "
"`*mgrd` services to obtain these changes and process them. The types of "
"these notifications can be found in [SwitchNotifications.h](https://github."
"com/sonic-net/sonic-sairedis/blob/master/syncd/SwitchNotifications.h)."
msgstr ""

#: src\2-2-services-intro.md:42
msgid "Control Flow Between Services"
msgstr ""

#: src\2-2-services-intro.md:44
msgid ""
"With service categories, we can now better understand the services in SONiC. "
"To get started, it is crucial to understand the control flow between "
"services. Based on the above categories, we can divide the main control "
"flows into two categories: configuration deployment and state "
"synchronization."
msgstr ""

#: src\2-2-services-intro.md:46
msgid "Configuration Deployment"
msgstr ""

#: src\2-2-services-intro.md:48
msgid "The configuration deployment process generally follows these steps:"
msgstr ""

#: src\2-2-services-intro.md:50
msgid ""
"**Modify Configuration**: Users can modify configurations through CLI or "
"REST API. These configurations are written to CONFIG_DB and send update "
"notifications through Redis. Alternatively, external programs can modify "
"configurations through specific interfaces, such as the BGP API. These "
"configurations are sent to `*mgrd` services through internal TCP sockets."
msgstr ""

#: src\2-2-services-intro.md:51
msgid ""
"**`*mgrd` Deploys Configuration**: Services listen to configuration changes "
"in CONFIG_DB and then push these configurations to the switch hardware. "
"There are two main scenarios (which can coexist):"
msgstr ""

#: src\2-2-services-intro.md:52
msgid "**Direct Deployment**:"
msgstr ""

#: src\2-2-services-intro.md:53
msgid ""
"`*mgrd` services directly call Linux command lines or modify system "
"configurations through netlink."
msgstr ""

#: src\2-2-services-intro.md:54
msgid ""
"`*syncd` services listen to system configuration changes through netlink or "
"other methods and push these changes to STATE_DB or APPL_DB."
msgstr ""

#: src\2-2-services-intro.md:55
msgid ""
"`*mgrd` services listen to configuration changes in STATE_DB or APPL_DB, "
"compare these configurations with those stored in their memory, and if "
"inconsistencies are found, they re-call command lines or netlink to modify "
"system configurations until they are consistent."
msgstr ""

#: src\2-2-services-intro.md:56
msgid "**Indirect Deployment**:"
msgstr ""

#: src\2-2-services-intro.md:57
msgid ""
"`*mgrd` pushes states to APPL_DB and sends update notifications through "
"Redis."
msgstr ""

#: src\2-2-services-intro.md:58
msgid ""
"`orchagent` listens to configuration changes, calculates the state the ASIC "
"should achieve based on all related states, and deploys it to ASIC_DB."
msgstr ""

#: src\2-2-services-intro.md:59
msgid ""
"`syncd` listens to changes in ASIC_DB and updates the switch ASIC "
"configuration through the unified SAI API interface by calling the ASIC "
"Driver."
msgstr ""

#: src\2-2-services-intro.md:61
msgid ""
"Configuration initialization is similar to configuration deployment but "
"involves reading configuration files when services start, which will not be "
"expanded here."
msgstr ""

#: src\2-2-services-intro.md:63
msgid "State Synchronization"
msgstr ""

#: src\2-2-services-intro.md:65
msgid ""
"If situations arise, such as a port failure or changes in the ASIC state, "
"state updates and synchronization are needed. The process generally follows "
"these steps:"
msgstr ""

#: src\2-2-services-intro.md:67
msgid ""
"**Detect State Changes**: These state changes mainly come from `*syncd` "
"services (netlink, etc.) and `syncd` services ([SAI Switch Notification]"
"(https://github.com/sonic-net/sonic-sairedis/blob/master/syncd/"
"SwitchNotifications.h)). After detecting changes, these services send them "
"to STATE_DB or APPL_DB."
msgstr ""

#: src\2-2-services-intro.md:68
msgid ""
"**Process State Changes**: `orchagent` and `*mgrd` services listen to these "
"changes, process them, and re-deploy new configurations to the system "
"through command lines and netlink or to ASIC_DB for `syncd` services to "
"update the ASIC again."
msgstr ""

#: src\2-2-services-intro.md:70
msgid "Specific Examples"
msgstr ""

#: src\2-2-services-intro.md:72
msgid ""
"The official SONiC documentation provides several typical examples of "
"control flow. Interested readers can refer to [SONiC Subsystem Interactions]"
"(https://github.com/sonic-net/SONiC/wiki/Architecture#sonic-subsystems-"
"interactions). In the workflow chapter, we will also expand on some very "
"common workflows."
msgstr ""

#: src\2-3-key-containers.md:1
msgid "Key containers"
msgstr ""

#: src\2-3-key-containers.md:3
msgid ""
"One of the most distinctive features of SONiC's design is containerization."
msgstr ""

#: src\2-3-key-containers.md:5
msgid ""
"From the design diagram of SONiC, we can see that all services in SONiC run "
"in the form of containers. After logging into the switch, we can use the "
"`docker ps` command to see all containers that are currently running:"
msgstr ""

#: src\2-3-key-containers.md:10 src\2-3-key-containers.md:11
#: src\2-3-key-containers.md:16 src\2-3-key-containers.md:17
#: src\2-3-key-containers.md:19
msgid "\"/usr/local/bin/supe\""
msgstr ""

#: src\2-3-key-containers.md:12
msgid "\"/usr/bin/docker-lld\""
msgstr ""

#: src\2-3-key-containers.md:13 src\2-3-key-containers.md:15
msgid "\"/usr/bin/docker_ini\""
msgstr ""

#: src\2-3-key-containers.md:14 src\2-3-key-containers.md:18
msgid "\"/usr/bin/docker-ini\""
msgstr ""

#: src\2-3-key-containers.md:20
msgid "\"/usr/local/bin/dock\""
msgstr ""

#: src\2-3-key-containers.md:23
msgid "Here we will briefly introduce these containers."
msgstr ""

#: src\2-3-key-containers.md:25
msgid "Database Container: `database`"
msgstr ""

#: src\2-3-key-containers.md:27
msgid ""
"This container contains the central database - Redis, which we have "
"mentioned multiple times. It stores all the configuration and status of the "
"switch, and SONiC also uses it to provide the underlying communication "
"mechanism to various services."
msgstr ""

#: src\2-3-key-containers.md:29
msgid ""
"By entering this container via Docker, we can see the running Redis process:"
msgstr ""

#: src\2-3-key-containers.md:44
msgid "How does other container access this Redis database?"
msgstr ""

#: src\2-3-key-containers.md:46
msgid ""
"The answer is through Unix Socket. We can see this Unix Socket in the "
"database container, which is mapped from the `/var/run/redis` directory on "
"the switch."
msgstr ""

#: src\2-3-key-containers.md:49
msgid "# In database container"
msgstr ""

#: src\2-3-key-containers.md:52
msgid "# On host"
msgstr ""

#: src\2-3-key-containers.md:58
msgid ""
"Then SONiC maps `/var/run/redis` folder into all relavent containers, "
"allowing other services to access the central database. For example, the "
"swss container:"
msgstr ""

#: src\2-3-key-containers.md:63
msgid "\"HostConfig\""
msgstr ""

#: src\2-3-key-containers.md:64
msgid "\"Binds\""
msgstr ""

#: src\2-3-key-containers.md:66
msgid "\"/var/run/redis:/var/run/redis:rw\""
msgstr ""

#: src\2-3-key-containers.md:72
msgid "SWitch State Service Container: `swss`"
msgstr ""

#: src\2-3-key-containers.md:74
msgid ""
"This container can be considered the most critical container in SONiC. **It "
"is the brain of SONiC**, running numerous `*syncd` and `*mgrd` services to "
"manage various configurations of the switch, such as Port, neighbor, ARP, "
"VLAN, Tunnel, etc. Additionally, it runs the `orchagent`, which handles many "
"configurations and state changes related to the ASIC."
msgstr ""

#: src\2-3-key-containers.md:76
msgid ""
"We have already discussed the general functions and processes of these "
"services, so we won't repeat them here. We can use the `ps` command to see "
"the services running in this container:"
msgstr ""

#: src\2-3-key-containers.md:101
msgid "ASIC Management Container: `syncd`"
msgstr ""

#: src\2-3-key-containers.md:103
msgid ""
"This container is mainly used for managing the ASIC on the switch, running "
"the `syncd` service. The SAI (Switch Abstraction Interface) implementation "
"and ASIC Driver provided by various vendors are placed in this container. It "
"allows SONiC to support multiple different ASICs without modifying the upper-"
"layer services. In other words, without this container, SONiC would be a "
"brain in a jar, capable of only thinking but nothing else."
msgstr ""

#: src\2-3-key-containers.md:105
msgid ""
"We don't have too many services running in the syncd container, mainly "
"syncd. We can check them using the `ps` command, and in the `/usr/lib` "
"directory, we can find the enormous SAI file compiled to support the ASIC:"
msgstr ""

#: src\2-3-key-containers.md:125
msgid "Feature Containers"
msgstr ""

#: src\2-3-key-containers.md:127
msgid ""
"There are many containers in SONiC designed to implement specific features. "
"These containers usually have special external interfaces (non-SONiC CLI and "
"REST API) and implementations (non-OS or ASIC), such as:"
msgstr ""

#: src\2-3-key-containers.md:129
msgid ""
"`bgp`: Container for implementing the BGP and other routing protocol (Border "
"Gateway Protocol)"
msgstr ""

#: src\2-3-key-containers.md:130
msgid ""
"`lldp`: Container for implementing the LLDP protocol (Link Layer Discovery "
"Protocol)"
msgstr ""

#: src\2-3-key-containers.md:131
msgid "`teamd`: Container for implementing Link Aggregation"
msgstr ""

#: src\2-3-key-containers.md:132
msgid ""
"`snmp`: Container for implementing the SNMP protocol (Simple Network "
"Management Protocol)"
msgstr ""

#: src\2-3-key-containers.md:134
msgid ""
"Similar to SWSS, these containers also run the services we mentioned earlier "
"to adapt to SONiC's architecture:"
msgstr ""

#: src\2-3-key-containers.md:136
msgid ""
"Configuration management and deployment (similar to `*mgrd`): `lldpmgrd`, "
"`zebra` (bgp)"
msgstr ""

#: src\2-3-key-containers.md:137
msgid ""
"State synchronization (similar to `*syncd`): `lldpsyncd`, `fpmsyncd` (bgp), "
"`teamsyncd`"
msgstr ""

#: src\2-3-key-containers.md:138
msgid ""
"Service implementation or external interface (`*d`): `lldpd`, `bgpd`, "
"`teamd`, `snmpd`"
msgstr ""

#: src\2-3-key-containers.md:140
msgid "Management Service Container: `mgmt-framework`"
msgstr ""

#: src\2-3-key-containers.md:142
msgid ""
"In previous chapters, we have seen how to use SONiC's CLI to configure some "
"aspects of the switch. However, in a production environment, manually "
"logging into the switch and using the CLI to configure all switches is "
"unrealistic. Therefore, SONiC provides a REST API to solve this problem. "
"This REST API is implemented in the `mgmt-framework` container. We can check "
"it using the `ps` command:"
msgstr ""

#: src\2-3-key-containers.md:153
msgid ""
"In addition to the REST API, SONiC can also be managed through other methods "
"such as gNMI, all of which run in this container. The overall architecture "
"is shown in the figure below [\\[2\\]](https://github.com/sonic-net/SONiC/"
"blob/master/doc/mgmt/Management%20Framework.md):"
msgstr ""

#: src\2-3-key-containers.md:155
msgid "![](assets/chapter-2/sonic-mgmt-framework.jpg)"
msgstr ""

#: src\2-3-key-containers.md:157
msgid ""
"Here we can also see that the CLI we use can be implemented by calling this "
"REST API at the bottom layer."
msgstr ""

#: src\2-3-key-containers.md:159
msgid "Platform Monitor Container: `pmon`"
msgstr ""

#: src\2-3-key-containers.md:161
msgid ""
"The services in this container are mainly used to monitor the basic hardware "
"status of the switch, such as temperature, power supply, fans, SFP events, "
"etc. Similarly, we can use the `ps` command to check the services running in "
"this container:"
msgstr ""

#: src\2-3-key-containers.md:179
msgid ""
"The purpose of most of these services can be told from their names. The only "
"one that is not so obvious is `xcvrd`, where xcv stands for transceiver. It "
"is used to monitor the optical modules of the switch, such as SFP, QSFP, etc."
msgstr ""

#: src\2-3-key-containers.md:184 src\3-1-code-repos.md:137
msgid ""
"[SONiC Management Framework](https://github.com/sonic-net/SONiC/blob/master/"
"doc/mgmt/Management%20Framework.md)"
msgstr ""

#: src\2-4-sai-intro.md:3
msgid ""
"SAI (Switch Abstraction Interface) is the cornerstone of SONiC, while "
"enables it to support multiple hardware platforms. In [this SAI API document]"
"(https://github.com/opencomputeproject/SAI/wiki/SAI-APIs), we can see all "
"the interfaces it defines."
msgstr ""

#: src\2-4-sai-intro.md:5
msgid ""
"[In the core container section, we mentioned that SAI runs in the `syncd` "
"container](./2-3-key-containers.html). However, unlike other components, it "
"is not a service but a set of common header files and dynamic link libraries "
"(.so). All abstract interfaces are defined as C language header files in the "
"[OCP SAI repository](https://github.com/opencomputeproject/SAI), and the "
"hardware vendors provides the .so files that implement the SAI interfaces."
msgstr ""

#: src\2-4-sai-intro.md:7
msgid "SAI Interface"
msgstr ""

#: src\2-4-sai-intro.md:9
msgid ""
"To make things more intuitive, let's take a small portion of the code to "
"show how SAI interfaces look like and how it works, as follows:"
msgstr ""

#: src\2-4-sai-intro.md:12
msgid "// File: meta/saimetadata.h"
msgstr ""

#: src\2-4-sai-intro.md:18
msgid "// File: inc/saiswitch.h"
msgstr ""

#: src\2-4-sai-intro.md:28
msgid "// File: inc/saiport.h"
msgstr ""

#: src\2-4-sai-intro.md:40
msgid ""
"The `sai_apis_t` structure is a collection of interfaces for all SAI "
"modules, with each member being a pointer to a specific module's interface "
"list. For example, `sai_switch_api_t` defines all the interfaces for the SAI "
"Switch module, and its definition can be found in `inc/saiswitch.h`. "
"Similarly, the interface definitions for the SAI Port module can be found in "
"`inc/saiport.h`."
msgstr ""

#: src\2-4-sai-intro.md:42
msgid "SAI Initialization"
msgstr ""

#: src\2-4-sai-intro.md:44
msgid ""
"SAI initialization is essentially about obtaining these function pointers so "
"that we can operate the ASIC through the SAI interfaces."
msgstr ""

#: src\2-4-sai-intro.md:46
msgid ""
"The main functions involved in SAI initialization are defined in `inc/sai.h`:"
msgstr ""

#: src\2-4-sai-intro.md:48
msgid "`sai_api_initialize`: Initialize SAI"
msgstr ""

#: src\2-4-sai-intro.md:49
msgid ""
"`sai_api_query`: Pass in the type of SAI API to get the corresponding "
"interface list"
msgstr ""

#: src\2-4-sai-intro.md:51
msgid ""
"Although most vendors' SAI implementations are closed-source, Mellanox has "
"open-sourced its SAI implementation, allowing us to gain a deeper "
"understanding of how SAI works."
msgstr ""

#: src\2-4-sai-intro.md:53
msgid ""
"For example, the `sai_api_initialize` function simply sets two global "
"variables and returns `SAI_STATUS_SUCCESS`:"
msgstr ""

#: src\2-4-sai-intro.md:56 src\2-4-sai-intro.md:73
msgid ""
"// File: https://github.com/Mellanox/SAI-Implementation/blob/master/mlnx_sai/"
"src/mlnx_sai_interfacequery.c"
msgstr ""

#: src\2-4-sai-intro.md:62
msgid "// Validate parameters here (code omitted)"
msgstr ""

#: src\2-4-sai-intro.md:70
msgid ""
"After initialization, we can use the `sai_api_query` function to query the "
"corresponding interface list by passing in the type of API, where each "
"interface list is actually a global variable:"
msgstr ""

#: src\2-4-sai-intro.md:83
msgid ""
"// File: https://github.com/Mellanox/SAI-Implementation/blob/master/mlnx_sai/"
"src/mlnx_sai_interfacequery_eth.c"
msgstr ""

#: src\2-4-sai-intro.md:103
msgid ""
"// File: https://github.com/Mellanox/SAI-Implementation/blob/master/mlnx_sai/"
"src/mlnx_sai_bridge.c"
msgstr ""

#: src\2-4-sai-intro.md:113 src\5-1-syncd-and-sai.md:395
#: src\5-1-syncd-and-sai.md:592
msgid ""
"// File: https://github.com/Mellanox/SAI-Implementation/blob/master/mlnx_sai/"
"src/mlnx_sai_switch.c"
msgstr ""

#: src\2-4-sai-intro.md:124
msgid "Using SAI"
msgstr ""

#: src\2-4-sai-intro.md:126
msgid ""
"In the `syncd` container, SONiC starts the `syncd` service at startup, which "
"loads the SAI component present in the system. This component is provided by "
"various vendors, who implement the SAI interfaces based on their hardware "
"platforms, allowing SONiC to use a unified upper-layer logic to control "
"various hardware platforms."
msgstr ""

#: src\2-4-sai-intro.md:128
msgid "We can verify this using the `ps`, `ls`, and `nm` commands:"
msgstr ""

#: src\2-4-sai-intro.md:131
msgid "# Enter into syncd container"
msgstr ""

#: src\2-4-sai-intro.md:133
msgid "# List all processes. We will only see syncd process here."
msgstr ""

#: src\2-4-sai-intro.md:141
msgid "# Find all libsai*.so.* files."
msgstr ""

#: src\2-4-sai-intro.md:152
msgid ""
"# Copy the file out of switch and check libsai.so on your own dev machine."
msgstr ""

#: src\2-4-sai-intro.md:153
msgid "# We will see the most important SAI export functions here."
msgstr ""

#: src\2-4-sai-intro.md:169
msgid ""
"[Github: sonic-net/sonic-sairedis](https://github.com/sonic-net/sonic-"
"sairedis/)"
msgstr ""

#: src\2-4-sai-intro.md:170
msgid ""
"[Github: opencomputeproject/SAI](https://github.com/opencomputeproject/SAI)"
msgstr ""

#: src\2-4-sai-intro.md:171
msgid ""
"[Arista 7050QX Series 10/40G Data Center Switches Data Sheet](https://www."
"arista.com/assets/data/pdf/Datasheets/7050QX-32_32S_Datasheet_S.pdf)"
msgstr ""

#: src\2-4-sai-intro.md:172 src\5-1-syncd-and-sai.md:826
msgid ""
"[Github repo: Nvidia (Mellanox) SAI implementation](https://github.com/"
"Mellanox/SAI-Implementation/tree/master)"
msgstr ""

#: src\3-1-code-repos.md:3
msgid ""
"The code of SONiC is hosted on the [sonic-net account on GitHub](https://"
"github.com/sonic-net), with over 30 repositories. It can be a bit "
"overwhelming at first, but don't worry, we'll go through them together here."
msgstr ""

#: src\3-1-code-repos.md:5
msgid "Core Repositories"
msgstr ""

#: src\3-1-code-repos.md:7
msgid ""
"First, let's look at the two most important core repositories in SONiC: "
"SONiC and sonic-buildimage."
msgstr ""

#: src\3-1-code-repos.md:9
msgid "Landing Repository: `SONiC`"
msgstr ""

#: src\3-1-code-repos.md:11
msgid "<https://github.com/sonic-net/SONiC>"
msgstr ""

#: src\3-1-code-repos.md:13
msgid ""
"This repository contains the SONiC Landing Page and a large number of "
"documents, Wiki, tutorials, slides from past talks, and so on. This "
"repository is the most commonly used by newcomers, but note that there is "
"**no code** in this repository, only documentation."
msgstr ""

#: src\3-1-code-repos.md:15
msgid "Image Build Repository: `sonic-buildimage`"
msgstr ""

#: src\3-1-code-repos.md:17
msgid "<https://github.com/sonic-net/sonic-buildimage>"
msgstr ""

#: src\3-1-code-repos.md:19
msgid ""
"Why is this build repository so important to us? Unlike other projects, "
"**the build repository of SONiC is actually its main repository**! This "
"repository contains:"
msgstr ""

#: src\3-1-code-repos.md:21
msgid ""
"All the feature implementation repositories, in the form of git submodules "
"(under the `src` directory)."
msgstr ""

#: src\3-1-code-repos.md:22
msgid ""
"Support files for each device from switch manufactures (under the `device` "
"directory), such as device configuration files for each model of switch, "
"scripts, and so on. For example, my switch is an Arista 7050QX-32S, so I can "
"find its support files in the `device/arista/x86_64-arista_7050_qx32s` "
"directory."
msgstr ""

#: src\3-1-code-repos.md:23
msgid ""
"Support files provided by all ASIC chip manufacturers (in the `platform` "
"directory), such as drivers, BSP, and low-level support scripts for each "
"platform. Here we can see support files from almost all major chip "
"manufacturers, such as Broadcom, Mellanox, etc., as well as implementations "
"for simulated software switches, such as vs and p4. But for protecting IPs "
"from each vendor, most of the time, the repo only contains the Makefiles "
"that downloads these things for build purpose."
msgstr ""

#: src\3-1-code-repos.md:24
msgid ""
"Dockerfiles for building all container images used by SONiC (in the "
"`dockers` directory)."
msgstr ""

#: src\3-1-code-repos.md:25
msgid ""
"Various general configuration files and scripts (in the `files` directory)."
msgstr ""

#: src\3-1-code-repos.md:26
msgid ""
"Dockerfiles for the build containers used for building (in the `sonic-slave-"
"*` directories)."
msgstr ""

#: src\3-1-code-repos.md:27
msgid "And more..."
msgstr ""

#: src\3-1-code-repos.md:29
msgid ""
"Because this repository brings all related resources together, we basically "
"only need to checkout this single repository to get all SONiC's code. It "
"makes searching and navigating the code much more convenient than checking "
"out the repos one by one!"
msgstr ""

#: src\3-1-code-repos.md:31
msgid "Feature Repositories"
msgstr ""

#: src\3-1-code-repos.md:33
msgid ""
"In addition to the core repositories, SONiC also has many feature "
"repositories, which contain the implementations of various containers and "
"services. These repositories are imported as submodules in the `src` "
"directory of sonic-buildimage. If we would like to modify and contribute to "
"SONiC, we also need to understand them."
msgstr ""

#: src\3-1-code-repos.md:35
msgid "SWSS (Switch State Service) Related Repositories"
msgstr ""

#: src\3-1-code-repos.md:37
msgid ""
"As introduced in the previous section, the SWSS container is the brain of "
"SONiC. In SONiC, it consists of two repositories: [sonic-swss-common]"
"(https://github.com/sonic-net/sonic-swss-common) and [sonic-swss](https://"
"github.com/sonic-net/sonic-swss)."
msgstr ""

#: src\3-1-code-repos.md:39
msgid "SWSS Common Library: `sonic-swss-common`"
msgstr ""

#: src\3-1-code-repos.md:41
msgid ""
"The first one is the common library: `sonic-swss-common` (<https://github."
"com/sonic-net/sonic-swss-common>)."
msgstr ""

#: src\3-1-code-repos.md:43
msgid ""
"This repository contains all the common functionalities needed by `*mgrd` "
"and `*syncd` services, such as logger, JSON, netlink encapsulation, Redis "
"operations, and various inter-service communication mechanisms based on "
"Redis. Although it was initially intended for swss services, its extensive "
"functionalities have led to its use in many other repositories, such as "
"`swss-sairedis` and `swss-restapi`."
msgstr ""

#: src\3-1-code-repos.md:45
msgid "Main SWSS Repository: `sonic-swss`"
msgstr ""

#: src\3-1-code-repos.md:47
msgid ""
"Next is the main SWSS repository: `sonic-swss` (<https://github.com/sonic-"
"net/sonic-swss>)."
msgstr ""

#: src\3-1-code-repos.md:49
msgid "In this repository, we can find:"
msgstr ""

#: src\3-1-code-repos.md:51
msgid ""
"Most of the `*mgrd` and `*syncd` services: `orchagent`, `portsyncd/portmgrd/"
"intfmgrd`, `neighsyncd/nbrmgrd`, `natsyncd/natmgrd`, `buffermgrd`, "
"`coppmgrd`, `macsecmgrd`, `sflowmgrd`, `tunnelmgrd`, `vlanmgrd`, `vrfmgrd`, "
"`vxlanmgrd`, and more."
msgstr ""

#: src\3-1-code-repos.md:52
msgid ""
"`swssconfig`: Located in the `swssconfig` directory, used to restore FDB and "
"ARP tables during fast reboot."
msgstr ""

#: src\3-1-code-repos.md:53
msgid ""
"`swssplayer`: Also in the `swssconfig` directory, used to record all "
"configuration operations performed through SWSS, allowing us to replay them "
"for troubleshooting and debugging."
msgstr ""

#: src\3-1-code-repos.md:54
msgid ""
"Even some services not in the SWSS container, such as `fpmsyncd` (BGP "
"container) and `teamsyncd/teammgrd` (teamd container)."
msgstr ""

#: src\3-1-code-repos.md:56
msgid "SAI/Platform Related Repositories"
msgstr ""

#: src\3-1-code-repos.md:58
msgid ""
"Next is the Switch Abstraction Interface (SAI). [Although SAI was proposed "
"by Microsoft and released version 0.1 in March 2015](https://www.opencompute."
"org/documents/switch-abstraction-interface-ocp-specification-v0-2-pdf), [by "
"September 2015, before SONiC had even released its first version, it was "
"already accepted by OCP as a public standard](https://azure.microsoft.com/en-"
"us/blog/switch-abstraction-interface-sai-officially-accepted-by-the-open-"
"compute-project-ocp/). This shows how quickly SONiC and SAI was getting "
"supports from the community and vendors."
msgstr ""

#: src\3-1-code-repos.md:60
msgid "Overall, the SAI code is divided into two parts:"
msgstr ""

#: src\3-1-code-repos.md:62
msgid ""
"OpenComputeProject/SAI under OCP: <https://github.com/opencomputeproject/"
"SAI>. This repository contains all the code related to the SAI standard, "
"including SAI header files, behavior models, test cases, documentation, and "
"more."
msgstr ""

#: src\3-1-code-repos.md:63
msgid ""
"sonic-sairedis under SONiC: <https://github.com/sonic-net/sonic-sairedis>. "
"This repository contains all the code used by SONiC to interact with SAI, "
"such as the syncd service and various debugging tools like `saiplayer` for "
"replay and `saidump` for exporting ASIC states."
msgstr ""

#: src\3-1-code-repos.md:65
msgid ""
"In addition to these two repositories, there is another platform-related "
"repository, such as [sonic-platform-vpp](https://github.com/sonic-net/sonic-"
"platform-vpp), which uses SAI interfaces to implement data plane "
"functionalities through VPP, essentially acting as a high-performance soft "
"switch. I personally feel it might be merged into the buildimage repository "
"in the future as part of the platform directory."
msgstr ""

#: src\3-1-code-repos.md:67
msgid "Management Service (mgmt) Related Repositories"
msgstr ""

#: src\3-1-code-repos.md:69
msgid ""
"Next are all the repositories related to [management services](https://"
"github.com/sonic-net/SONiC/blob/master/doc/mgmt/Management%20Framework.md) "
"in SONiC:"
msgstr ""

#: src\3-1-code-repos.md:71 src\3-1-code-repos.md:87
msgid "Name"
msgstr ""

#: src\3-1-code-repos.md:71 src\3-1-code-repos.md:87 src\3-1-code-repos.md:96
msgid "Description"
msgstr ""

#: src\3-1-code-repos.md:73
msgid "[sonic-mgmt-common](https://github.com/sonic-net/sonic-mgmt-common)"
msgstr ""

#: src\3-1-code-repos.md:73
msgid ""
"Base library for management services, containing `translib`, YANG model-"
"related code"
msgstr ""

#: src\3-1-code-repos.md:74
msgid ""
"[sonic-mgmt-framework](https://github.com/sonic-net/sonic-mgmt-framework)"
msgstr ""

#: src\3-1-code-repos.md:74
msgid ""
"REST Server implemented in Go, acting as the REST Gateway in the "
"architecture diagram below (process name: `rest_server`)"
msgstr ""

#: src\3-1-code-repos.md:75
msgid "[sonic-gnmi](https://github.com/sonic-net/sonic-gnmi)"
msgstr ""

#: src\3-1-code-repos.md:75
msgid ""
"Similar to sonic-mgmt-framework, this is the gNMI (gRPC Network Management "
"Interface) Server based on gRPC in the architecture diagram below"
msgstr ""

#: src\3-1-code-repos.md:76
msgid "[sonic-restapi](https://github.com/sonic-net/sonic-restapi)"
msgstr ""

#: src\3-1-code-repos.md:76
msgid ""
"Another configuration management REST Server implemented in Go. Unlike mgmt-"
"framework, this server directly operates on CONFIG_DB upon receiving "
"messages, instead of using translib (not shown in the diagram, process name: "
"`go-server-server`)"
msgstr ""

#: src\3-1-code-repos.md:77
msgid "[sonic-mgmt](https://github.com/sonic-net/sonic-mgmt)"
msgstr ""

#: src\3-1-code-repos.md:77
msgid ""
"Various automation scripts (in the `ansible` directory), tests (in the "
"`tests` directory), test bed setup and test reporting (in the "
"`test_reporting` directory), and more"
msgstr ""

#: src\3-1-code-repos.md:79
msgid ""
"Here is the architecture diagram of SONiC management services for reference "
"[\\[4\\]](https://github.com/sonic-net/SONiC/blob/master/doc/mgmt/Management%"
"20Framework.md):"
msgstr ""

#: src\3-1-code-repos.md:81
msgid "![](assets/chapter-3/sonic-mgmt-framework.jpg)"
msgstr ""

#: src\3-1-code-repos.md:83
msgid ""
"Platform Monitoring Related Repositories: `sonic-platform-common` and `sonic-"
"platform-daemons`"
msgstr ""

#: src\3-1-code-repos.md:85
msgid ""
"The following two repositories are related to platform monitoring and "
"control, such as LEDs, fans, power supplies, thermal control, and more:"
msgstr ""

#: src\3-1-code-repos.md:89
msgid ""
"[sonic-platform-common](https://github.com/sonic-net/sonic-platform-common)"
msgstr ""

#: src\3-1-code-repos.md:89
msgid ""
"A base package provided to manufacturers, defining interfaces for accessing "
"fans, LEDs, power management, thermal control, and other modules, all "
"implemented in Python"
msgstr ""

#: src\3-1-code-repos.md:90
msgid ""
"[sonic-platform-daemons](https://github.com/sonic-net/sonic-platform-daemons)"
msgstr ""

#: src\3-1-code-repos.md:90
msgid ""
"Contains various monitoring services running in the pmon container in SONiC, "
"such as `chassisd`, `ledd`, `pcied`, `psud`, `syseepromd`, `thermalctld`, "
"`xcvrd`, `ycabled`. All these services are implemented in Python, and used "
"for monitoring and controlling the platform modules, by calling the "
"interface implementations provided by manufacturers."
msgstr ""

#: src\3-1-code-repos.md:92
msgid "Other Feature Repositories"
msgstr ""

#: src\3-1-code-repos.md:94
msgid ""
"In addition to the repositories above, SONiC has many repositories "
"implementing various functionalities. They can be services or libraries "
"described in the table below:"
msgstr ""

#: src\3-1-code-repos.md:96
msgid "Repository"
msgstr ""

#: src\3-1-code-repos.md:98
msgid "[sonic-frr](https://github.com/sonic-net/sonic-frr)"
msgstr ""

#: src\3-1-code-repos.md:98
msgid ""
"FRRouting, implementing various routing protocols, so in this repository, we "
"can find implementations of routing-related processes like `bgpd`, `zebra`, "
"etc."
msgstr ""

#: src\3-1-code-repos.md:99
msgid "[sonic-snmpagent](https://github.com/sonic-net/sonic-snmpagent)"
msgstr ""

#: src\3-1-code-repos.md:99
msgid ""
"Implementation of [AgentX](https://www.ietf.org/rfc/rfc2741.txt) SNMP "
"subagent (`sonic_ax_impl`), used to connect to the Redis database and "
"provide various information needed by snmpd. It can be understood as the "
"control plane of snmpd, while snmpd is the data plane, responding to "
"external SNMP requests"
msgstr ""

#: src\3-1-code-repos.md:100
msgid "[sonic-linkmgrd](https://github.com/sonic-net/sonic-linkmgrd)"
msgstr ""

#: src\3-1-code-repos.md:100
msgid ""
"Dual ToR support, checking the status of links and controlling ToR "
"connections"
msgstr ""

#: src\3-1-code-repos.md:101
msgid "[sonic-dhcp-relay](https://github.com/sonic-net/sonic-dhcp-relay)"
msgstr ""

#: src\3-1-code-repos.md:101
msgid "DHCP relay agent"
msgstr ""

#: src\3-1-code-repos.md:102
msgid "[sonic-dhcpmon](https://github.com/sonic-net/sonic-dhcpmon)"
msgstr ""

#: src\3-1-code-repos.md:102
msgid "Monitors the status of DHCP and reports to the central Redis database"
msgstr ""

#: src\3-1-code-repos.md:103
msgid "[sonic-dbsyncd](https://github.com/sonic-net/sonic-dbsyncd)"
msgstr ""

#: src\3-1-code-repos.md:103
msgid ""
"`lldp_syncd` service, but the repository name is not well-chosen, called "
"dbsyncd"
msgstr ""

#: src\3-1-code-repos.md:104
msgid "[sonic-pins](https://github.com/sonic-net/sonic-pins)"
msgstr ""

#: src\3-1-code-repos.md:104
msgid ""
"Google's P4-based network stack support (P4 Integrated Network Stack, PINS). "
"More information can be found on the [PINS website](https://opennetworking."
"org/pins/)"
msgstr ""

#: src\3-1-code-repos.md:105
msgid "[sonic-stp](https://github.com/sonic-net/sonic-stp)"
msgstr ""

#: src\3-1-code-repos.md:105
msgid "STP (Spanning Tree Protocol) support"
msgstr ""

#: src\3-1-code-repos.md:106
msgid "[sonic-ztp](https://github.com/sonic-net/sonic-ztp)"
msgstr ""

#: src\3-1-code-repos.md:106
msgid ""
"[Zero Touch Provisioning](https://github.com/sonic-net/SONiC/blob/master/doc/"
"ztp/ztp.md)"
msgstr ""

#: src\3-1-code-repos.md:107
msgid "[DASH](https://github.com/sonic-net/DASH)"
msgstr ""

#: src\3-1-code-repos.md:107
msgid ""
"[Disaggregated API for SONiC Hosts](https://github.com/sonic-net/DASH/blob/"
"main/documentation/general/dash-high-level-design.md)"
msgstr ""

#: src\3-1-code-repos.md:108
msgid "[sonic-host-services](https://github.com/sonic-net/sonic-host-services)"
msgstr ""

#: src\3-1-code-repos.md:108
msgid ""
"Services running on the host, providing support to services in containers "
"via dbus, such as saving and reloading configurations, saving dumps, etc., "
"similar to a host broker"
msgstr ""

#: src\3-1-code-repos.md:109
msgid "[sonic-fips](https://github.com/sonic-net/sonic-fips)"
msgstr ""

#: src\3-1-code-repos.md:109
msgid ""
"FIPS (Federal Information Processing Standards) support, containing various "
"patch files added to support FIPS standards"
msgstr ""

#: src\3-1-code-repos.md:110
msgid ""
"[sonic-wpa-supplicant](https://github.com/sonic-net/sonic-wpa-supplicant)"
msgstr ""

#: src\3-1-code-repos.md:110
msgid "Support for various wireless network protocols"
msgstr ""

#: src\3-1-code-repos.md:112
msgid "Tooling Repository: `sonic-utilities`"
msgstr ""

#: src\3-1-code-repos.md:114
msgid "<https://github.com/sonic-net/sonic-utilities>"
msgstr ""

#: src\3-1-code-repos.md:116
msgid "This repository contains all the command-line tools for SONiC:"
msgstr ""

#: src\3-1-code-repos.md:118
msgid ""
"`config`, `show`, `clear` directories: These are the implementations of the "
"three main SONiC CLI commands. Note that the specific command "
"implementations may not necessarily be in these directories; many commands "
"are implemented by calling other commands, with these directories providing "
"an entry point."
msgstr ""

#: src\3-1-code-repos.md:119
msgid ""
"`scripts`, `sfputil`, `psuutil`, `pcieutil`, `fwutil`, `ssdutil`, "
"`acl_loader` directories: These directories provide many tool commands, but "
"most are not directly used by users; instead, they are called by commands in "
"the `config`, `show`, and `clear` directories. For example, the `show "
"platform fan` command is implemented by calling the `fanshow` command in the "
"`scripts` directory."
msgstr ""

#: src\3-1-code-repos.md:120
msgid ""
"`utilities_common`, `flow_counter_util`, `syslog_util` directories: Similar "
"to the above, but they provide base classes that can be directly imported "
"and called in Python."
msgstr ""

#: src\3-1-code-repos.md:121
msgid ""
"There are also many other commands: `fdbutil`, `pddf_fanutil`, "
"`pddf_ledutil`, `pddf_psuutil`, `pddf_thermalutil`, etc., used to view and "
"control the status of various modules."
msgstr ""

#: src\3-1-code-repos.md:122
msgid ""
"`connect` and `consutil` directories: Commands in these directories are used "
"to connect to and manage other SONiC devices."
msgstr ""

#: src\3-1-code-repos.md:123
msgid ""
"`crm` directory: Used to configure and view [CRM (Critical Resource "
"Monitoring)](https://github.com/sonic-net/SONiC/wiki/Critical-Resource-"
"Monitoring-High-Level-Design) in SONiC. This command is not included in the "
"`config` and `show` commands, so users can use it directly."
msgstr ""

#: src\3-1-code-repos.md:124
msgid ""
"`pfc` directory: Used to configure and view PFC (Priority-based Flow "
"Control) in SONiC."
msgstr ""

#: src\3-1-code-repos.md:125
msgid ""
"`pfcwd` directory: Used to configure and view [PFC Watch Dog](https://github."
"com/sonic-net/SONiC/wiki/PFC-Watchdog) in SONiC, such as starting, stopping, "
"modifying polling intervals, and more."
msgstr ""

#: src\3-1-code-repos.md:127
msgid "Kernel Patches: sonic-linux-kernel"
msgstr ""

#: src\3-1-code-repos.md:129
msgid "<https://github.com/sonic-net/sonic-linux-kernel>"
msgstr ""

#: src\3-1-code-repos.md:131
msgid ""
"Although SONiC is based on Debian, the default Debian kernel may not "
"necessarily run SONiC, such as certain modules not being enabled by default "
"or issues with older drivers. Therefore, SONiC requires some modifications "
"to the Linux kernel. This repository is used to store all the kernel patches."
msgstr ""

#: src\3-1-code-repos.md:136
msgid ""
"[SONiC Source Repositories](https://github.com/sonic-net/SONiC/blob/master/"
"sourcecode.md)"
msgstr ""

#: src\3-1-code-repos.md:139 src\3-1-code-repos.md:141
msgid ""
"[SONiC Critical Resource Monitoring](https://github.com/sonic-net/SONiC/wiki/"
"Critical-Resource-Monitoring-High-Level-Design)"
msgstr ""

#: src\3-1-code-repos.md:140
msgid ""
"[SONiC Zero Touch Provisioning](https://github.com/sonic-net/SONiC/blob/"
"master/doc/ztp/ztp.md)"
msgstr ""

#: src\3-1-code-repos.md:142
msgid "[SONiC P4 Integrated Network Stack](https://opennetworking.org/pins/)"
msgstr ""

#: src\3-1-code-repos.md:143
msgid ""
"[SONiC Disaggregated API for Switch Hosts](https://github.com/sonic-net/DASH/"
"blob/main/documentation/general/dash-high-level-design.md)"
msgstr ""

#: src\3-1-code-repos.md:144
msgid ""
"[SAI spec for OCP](https://www.opencompute.org/documents/switch-abstraction-"
"interface-ocp-specification-v0-2-pdf)"
msgstr ""

#: src\3-1-code-repos.md:145
msgid "[PFC Watchdog](https://github.com/sonic-net/SONiC/wiki/PFC-Watchdog)"
msgstr ""

#: src\3-2-build.md:3
msgid ""
"To ensure that we can successfully build SONiC on any platform as well, "
"SONiC leverages docker to build its build environment. It installs all tools "
"and dependencies in a docker container of the corresponding Debian version, "
"mounts its code into the container, and then start the build process inside "
"the container. This way, we can easily build SONiC on any platform without "
"worrying about dependency mismatches. For example, some packages in Debian "
"have higher versions than in Ubuntu, which might cause unexpected errors "
"during build time or runtime."
msgstr ""

#: src\3-2-build.md:5
msgid "Setup the Build Environment"
msgstr ""

#: src\3-2-build.md:7
msgid "Install Docker"
msgstr ""

#: src\3-2-build.md:9
msgid ""
"To support the containerized build environment, the first step is to ensure "
"that Docker is installed on our machine."
msgstr ""

#: src\3-2-build.md:11
msgid ""
"You can refer to the [official documentation](https://docs.docker.com/engine/"
"install/) for Docker installation methods. Here, we briefly introduce the "
"installation method for Ubuntu."
msgstr ""

#: src\3-2-build.md:13
msgid ""
"First, we need to add docker's source and certificate to the apt source list:"
msgstr ""

#: src\3-2-build.md:24
msgid "\"deb [arch=\""
msgstr ""

#: src\3-2-build.md:24
msgid ""
"\" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/"
"ubuntu \\"
msgstr ""

#: src\3-2-build.md:25
msgid "\"$VERSION_CODENAME\""
msgstr ""

#: src\3-2-build.md:25
msgid "\" stable\""
msgstr ""

#: src\3-2-build.md:29
msgid "Then, we can quickly install docker via apt:"
msgstr ""

#: src\3-2-build.md:36
msgid ""
"After installing docker, we need to add the current user to the docker user "
"group and **log out and log back in**. This way, we can run any docker "
"commands without sudo! **This is very important** because subsequent SONiC "
"builds do not allow the use of sudo."
msgstr ""

#: src\3-2-build.md:42
msgid ""
"After installation, don't forget to verify the installation with the "
"following command (note, no sudo is needed here!):"
msgstr ""

#: src\3-2-build.md:48
msgid "Install Other Dependencies"
msgstr ""

#: src\3-2-build.md:55
msgid "Pull the Code"
msgstr ""

#: src\3-2-build.md:57
msgid ""
"In [Chapter 3.1 Code Repositories](./3-1-code-repos), we mentioned that the "
"main repository of SONiC is [sonic-buildimage](https://github.com/sonic-net/"
"sonic-buildimage). It is also the only repo we need to focus on for now."
msgstr ""

#: src\3-2-build.md:59
msgid ""
"Since this repository includes all other build-related repositories as "
"submodules, we need to use the `--recurse-submodules` option when pulling "
"the code with git:"
msgstr ""

#: src\3-2-build.md:65
msgid ""
"If you forget to pull the submodules when pulling the code, you can make up "
"for it with the following command:"
msgstr ""

#: src\3-2-build.md:71
msgid ""
"After the code is downloaded, or for an existing repo, we can initialize the "
"compilation environment with the following command. This command updates all "
"current submodules to the required versions to help us successfully compile:"
msgstr ""

#: src\3-2-build.md:78
msgid "Set Your Target Platform"
msgstr ""

#: src\3-2-build.md:80
msgid ""
"[Although SONiC supports many different types of switches](https://sonic-net."
"github.io/SONiC/Supported-Devices-and-Platforms.html), different models of "
"switches use different ASICs, which means different drivers and SDKs. "
"Although SONiC uses SAI to hide these differences and provide a unified "
"interface for the upper layers. However, we need to set target platform "
"correctly to ensure that the right SAI will be used, so the SONiC we build "
"can run on our target devices."
msgstr ""

#: src\3-2-build.md:82
msgid "Currently, SONiC mainly supports the following platforms:"
msgstr ""

#: src\3-2-build.md:84
msgid "broadcom"
msgstr ""

#: src\3-2-build.md:85
msgid "mellanox"
msgstr ""

#: src\3-2-build.md:86
msgid "marvell"
msgstr ""

#: src\3-2-build.md:87
msgid "barefoot"
msgstr ""

#: src\3-2-build.md:88
msgid "cavium"
msgstr ""

#: src\3-2-build.md:89
msgid "centec"
msgstr ""

#: src\3-2-build.md:90
msgid "nephos"
msgstr ""

#: src\3-2-build.md:91
msgid "innovium"
msgstr ""

#: src\3-2-build.md:92
msgid "vs"
msgstr ""

#: src\3-2-build.md:94
msgid ""
"After confirming the target platform, we can configure our build environment "
"with the following command:"
msgstr ""

#: src\3-2-build.md:97
msgid "# e.g.: make PLATFORM=mellanox configure"
msgstr ""

#: src\3-2-build.md:114
msgid "Build the Code"
msgstr ""

#: src\3-2-build.md:116
msgid "Build All Code"
msgstr ""

#: src\3-2-build.md:118
msgid "After setting the platform, we can start compiling the code:"
msgstr ""

#: src\3-2-build.md:121
msgid "# The number of jobs can be the number of cores on your machine."
msgstr ""

#: src\3-2-build.md:121
msgid ""
"# Say, if you have 16 cores, then feel free to set it to 16 to speed up the "
"build."
msgstr ""

#: src\3-2-build.md:132
msgid "Build Debug Image"
msgstr ""

#: src\3-2-build.md:134
msgid ""
"To improve the debug experience, SONiC also supports building debug image. "
"During build, SONiC will make sure the symbols are kept and debug tools are "
"installed inside all the containers, such as gdb. This will help us debug "
"the code more easily."
msgstr ""

#: src\3-2-build.md:136
msgid ""
"To build the debug image, we can use `INSTALL_DEBUG_TOOLS` build option:"
msgstr ""

#: src\3-2-build.md:139
msgid "y"
msgstr ""

#: src\3-2-build.md:142
msgid "Build Specific Package"
msgstr ""

#: src\3-2-build.md:144
msgid ""
"From SONiC's Build Pipeline, we can see that compiling the entire project is "
"very time-consuming. Most of the time, our code changes only affect a small "
"part of the code. So, is there a way to reduce our compilation workload? "
"Gladly, yes! We can specify the make target to build only the target or "
"package we need."
msgstr ""

#: src\3-2-build.md:146
msgid ""
"In SONiC, the files generated by each subproject can be found in the "
"`target` directory. For example:"
msgstr ""

#: src\3-2-build.md:148
msgid ""
"Docker containers: target/<docker-image>.gz, e.g., `target/docker-orchagent."
"gz`"
msgstr ""

#: src\3-2-build.md:149
msgid ""
"Deb packages: target/debs/<debian-version>/<package>.deb, e.g., `target/debs/"
"bullseye/libswsscommon_1.0.0_amd64.deb`"
msgstr ""

#: src\3-2-build.md:150
msgid ""
"Python wheels: target/python-wheels/<debian-version>/<package>.whl, e.g., "
"`target/python-wheels/bullseye/sonic_utilities-1.2-py3-none-any.whl`"
msgstr ""

#: src\3-2-build.md:152
msgid ""
"After figuring out the package we need to build, we can delete its generated "
"files and then call the make command again. Here we use `libswsscommon` as "
"an example:"
msgstr ""

#: src\3-2-build.md:155
msgid "# Remove the deb package for bullseye"
msgstr ""

#: src\3-2-build.md:157
msgid "# Build the deb package for bullseye"
msgstr ""

#: src\3-2-build.md:162
msgid "Check and Handle Build Errors"
msgstr ""

#: src\3-2-build.md:164
msgid ""
"If an error occurs during the build process, we can check the log file of "
"the failed project to find the specific reason. In SONiC, each subproject "
"generates its related log file, which can be easily found in the `target` "
"directory, such as:"
msgstr ""

#: src\3-2-build.md:175
msgid ""
"If we don't want to check the log files every time, then fix errors and "
"recompile in the root directory, SONiC provides another more convenient way "
"that allows us to stay in the docker builder after build. This way, we can "
"directly go to the corresponding directory to run the `make` command to "
"recompile the things you need:"
msgstr ""

#: src\3-2-build.md:178
msgid "# KEEP_SLAVE_ON=yes make <target>"
msgstr ""

#: src\3-2-build.md:179 src\3-2-build.md:180
msgid "yes"
msgstr ""

#: src\3-2-build.md:183
msgid ""
"```admonish note\n"
"Some parts of the code in some repositories will not be build during full "
"build. For example, gtest in `sonic-swss-common`. So, when using this way to "
"recompile, please make sure to check the original repository's build "
"guidance to avoid errors, such as: <https://github.com/sonic-net/sonic-swss-"
"common#build-from-source>.\n"
"```"
msgstr ""

#: src\3-2-build.md:187
msgid "Get the Correct Image File"
msgstr ""

#: src\3-2-build.md:189
msgid ""
"After compilation, we can find the image files we need in the `target` "
"directory. However, there will be many different types of SONiC images, so "
"which one should we use? This mainly depends on what kind of BootLoader or "
"Installer the switch uses. The mapping is as below:"
msgstr ""

#: src\3-2-build.md:191
msgid "Bootloader"
msgstr ""

#: src\3-2-build.md:191
msgid "Suffix"
msgstr ""

#: src\3-2-build.md:193
msgid "Aboot"
msgstr ""

#: src\3-2-build.md:193
msgid ".swi"
msgstr ""

#: src\3-2-build.md:194
msgid "ONIE"
msgstr ""

#: src\3-2-build.md:194
msgid ".bin"
msgstr ""

#: src\3-2-build.md:195
msgid "Grub"
msgstr ""

#: src\3-2-build.md:195
msgid ".img.gz"
msgstr ""

#: src\3-2-build.md:197
msgid "Partial Upgrade"
msgstr ""

#: src\3-2-build.md:199
msgid ""
"Obviously, during development, build the image and then performing a full "
"installation each time is very inefficient. So, we could choose not to "
"install the image but directly upgrading certain deb packages as partial "
"upgrade, which could improving our development efficiency."
msgstr ""

#: src\3-2-build.md:201
msgid ""
"First, we can upload the deb package to the `/etc/sonic` directory of the "
"switch. The files in this directory will be mapped to the `/etc/sonic` "
"directory of all containers. Then, we can enter the container and use the "
"`dpkg` command to install the deb package, as follows:"
msgstr ""

#: src\3-2-build.md:204
msgid "# Enter the docker container"
msgstr ""

#: src\3-2-build.md:206
msgid "# Install deb package"
msgstr ""

#: src\3-2-build.md:213
msgid ""
"[SONiC Build Guide](https://github.com/sonic-net/sonic-buildimage/blob/"
"master/README.md)"
msgstr ""

#: src\3-2-build.md:214
msgid "[Install Docker Engine](https://docs.docker.com/engine/install/)"
msgstr ""

#: src\3-2-build.md:215
msgid ""
"[Github repo: sonic-buildimage](https://github.com/sonic-net/sonic-"
"buildimage)"
msgstr ""

#: src\3-2-build.md:217
msgid ""
"[Wrapper for starting make inside sonic-slave container](https://github.com/"
"sonic-net/sonic-buildimage/blob/master/Makefile.work)"
msgstr ""

#: src\3-3-testing.md:1
msgid "Testing"
msgstr ""

#: src\3-4-debugging.md:1
msgid "Debugging"
msgstr ""

#: src\3-4-1-sai-debugging.md:1
msgid "Debugging SAI"
msgstr ""

#: src\4-communications.md:1
msgid "Communication"
msgstr ""

#: src\4-communications.md:3
msgid ""
"There are three main communication mechanisms in SONiC: communication using "
"kernel, Redis-based inter-service communication, and ZMQ-based inter-service "
"communication."
msgstr ""

#: src\4-communications.md:5
msgid ""
"There are two main methods for communication using kernel: command line "
"calls and Netlink messages."
msgstr ""

#: src\4-communications.md:6
msgid ""
"Redis-based inter-service communication: There are 4 different communication "
"channel based on Redis - SubscriberStateTable, NotificationProducer/"
"Consumer, Producer/ConsumerTable, and Producer/ConsumerStateTable. Although "
"they are all based on Redis, their use case can be very different."
msgstr ""

#: src\4-communications.md:7
msgid ""
"ZMQ-based inter-service communication: This communication mechanism is "
"currently only used in the communication between `orchagent` and `syncd`."
msgstr ""

#: src\4-communications.md:15
msgid ""
"The implementation of all these basic communication mechanisms is in the "
"`common` directory of the [sonic-swss-common](https://github.com/sonic-net/"
"sonic-swss-common) repo. Additionally, to facilitate the use of various "
"services, SONiC has build a wrapper layer called Orch in [sonic-swss]"
"(https://github.com/sonic-net/sonic-swss), which helps simplify the upper-"
"layer services."
msgstr ""

#: src\4-communications.md:17
msgid ""
"In this chapter, we will dive into the implementation of these communication "
"mechanisms!"
msgstr ""

#: src\4-communications.md:22 src\4-2-1-redis-wrappers.md:35
#: src\4-2-2-subscribe-state-table.md:74
#: src\4-2-3-notification-producer-consumer.md:55
#: src\4-2-4-producer-consumer-table.md:131
#: src\4-2-5-producer-consumer-state-table.md:126 src\4-4-orch-layer.md:37
#: src\4-5-event-polling-and-error-handling.md:124 src\5-2-bgp.md:35
#: src\5-2-2-route-update-in-frr.md:738 src\5-2-3-route-update-in-sonic.md:737
msgid "[Github repo: sonic-swss](https://github.com/sonic-net/sonic-swss)"
msgstr ""

#: src\4-communications.md:23 src\4-1-1-exec.md:38 src\4-1-2-netlink.md:78
#: src\4-2-1-redis-wrappers.md:36 src\4-2-2-subscribe-state-table.md:75
#: src\4-2-3-notification-producer-consumer.md:56
#: src\4-2-4-producer-consumer-table.md:132
#: src\4-2-5-producer-consumer-state-table.md:127 src\4-4-orch-layer.md:38
#: src\4-5-event-polling-and-error-handling.md:125
#: src\5-2-2-route-update-in-frr.md:739 src\5-2-3-route-update-in-sonic.md:738
msgid ""
"[Github repo: sonic-swss-common](https://github.com/sonic-net/sonic-swss-"
"common)"
msgstr ""

#: src\4-1-1-exec.md:3
msgid ""
"The simplest way SONiC communicates with the kernel is through command-line "
"calls, which are implemented in [common/exec.h](https://github.com/sonic-net/"
"sonic-swss-common/blob/master/common/exec.h). The interface is straight-"
"forward:"
msgstr ""

#: src\4-1-1-exec.md:6
msgid "// File: common/exec.h"
msgstr ""

#: src\4-1-1-exec.md:6
msgid "// Namespace: swss"
msgstr ""

#: src\4-1-1-exec.md:11
msgid ""
"Here, `cmd` is the command to execute, and `stdout` captures the command "
"output. The `exec` function is a synchronous call that blocks until the "
"command finishes. Internally, it creates a child process via `popen` and "
"retrieves output via `fgets`. However, **although this function returns "
"output, it is rarely used in practice**. Most code only checks the return "
"value for success, and sometimes even error logs won't be logged in the "
"output."
msgstr ""

#: src\4-1-1-exec.md:13
msgid ""
"Despite its simplicity, this function is widely used, especially in various "
"`*mgrd` services. For instance, `portmgrd` calls it to set each port's "
"status:"
msgstr ""

#: src\4-1-1-exec.md:16
msgid "// File: sonic-swss - cfgmgr/portmgr.cpp"
msgstr ""

#: src\4-1-1-exec.md:22
msgid "// ip link set dev <port_name> [up|down]"
msgstr ""

#: src\4-1-1-exec.md:23
msgid "\" link set dev \""
msgstr ""

#: src\4-1-1-exec.md:23
msgid "\" up\""
msgstr ""

#: src\4-1-1-exec.md:23
msgid "\" down\""
msgstr ""

#: src\4-1-1-exec.md:27 src\4-1-2-netlink.md:27 src\4-1-2-netlink.md:36
#: src\4-1-2-netlink.md:43 src\4-1-2-netlink.md:59 src\4-1-2-netlink.md:65
#: src\4-1-2-netlink.md:72 src\4-2-2-subscribe-state-table.md:28
#: src\4-2-2-subscribe-state-table.md:42 src\4-2-2-subscribe-state-table.md:51
#: src\4-2-2-subscribe-state-table.md:58
#: src\4-2-3-notification-producer-consumer.md:28
#: src\4-2-3-notification-producer-consumer.md:40
#: src\4-2-3-notification-producer-consumer.md:44
#: src\4-2-4-producer-consumer-table.md:42
#: src\4-2-4-producer-consumer-table.md:90
#: src\4-2-4-producer-consumer-table.md:108
#: src\4-2-5-producer-consumer-state-table.md:32
#: src\4-2-5-producer-consumer-state-table.md:60
#: src\4-2-5-producer-consumer-state-table.md:63
#: src\4-5-event-polling-and-error-handling.md:27
#: src\4-5-event-polling-and-error-handling.md:29
#: src\4-5-event-polling-and-error-handling.md:62
#: src\4-5-event-polling-and-error-handling.md:83
msgid "// ..."
msgstr ""

#: src\4-1-2-netlink.md:3
msgid ""
"Netlinkis the message-based communication mechanism provided by Linux kernel "
"and used between the kernel and user-space processes. It is implemented via "
"socket and custom protocol families. It can be used to deliver various types "
"of kernel messages, including network device status, routing table updates, "
"firewall rule changes, and system resource usage. SONiC's `*sync` services "
"heavily utilize Netlink to monitor changes of network devices in the system, "
"synchronize the latest status to Redis, and notify other services to make "
"corresponding updates."
msgstr ""

#: src\4-1-2-netlink.md:5
msgid ""
"The main implementation of netlink communication channel is done by these "
"files:"
msgstr ""

#: src\4-1-2-netlink.md:7
msgid ""
"[common/netmsg.\\*](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/netmsg.h)"
msgstr ""

#: src\4-1-2-netlink.md:8
msgid ""
"[common/netlink.\\*](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/netlink.h)"
msgstr ""

#: src\4-1-2-netlink.md:9
msgid ""
"[common/netdispatcher.\\*](https://github.com/sonic-net/sonic-swss-common/"
"blob/master/common/netdispatcher.h)."
msgstr ""

#: src\4-1-2-netlink.md:11
msgid "The class diagram is as follows:"
msgstr ""

#: src\4-1-2-netlink.md:13
msgid "![](assets/chapter-4/netlink.png)"
msgstr ""

#: src\4-1-2-netlink.md:15
msgid "In this diagram:"
msgstr ""

#: src\4-1-2-netlink.md:17
msgid ""
"**Netlink**: Wraps the netlink socket interface and provides an interface "
"for sending netlink messages and a callback for receiving messages."
msgstr ""

#: src\4-1-2-netlink.md:18
msgid ""
"**NetDispatcher**: A singleton that provides an interface for registering "
"handlers. When a raw netlink message is received, it calls NetDispatcher to "
"parse them into `nl_object` objects and then dispatches them to the "
"corresponding handler based on the message type."
msgstr ""

#: src\4-1-2-netlink.md:19
msgid ""
"**NetMsg**: The base class for netlink message handlers, which only provides "
"the `onMsg` interface without a default implementation."
msgstr ""

#: src\4-1-2-netlink.md:21
msgid ""
"For example, when `portsyncd` starts, it creates a `Netlink` object to "
"listen for link-related status changes and implements the `NetMsg` interface "
"to handle the link messages. The specific implementation is as follows:"
msgstr ""

#: src\4-1-2-netlink.md:24
msgid "// File: sonic-swss - portsyncd/portsyncd.cpp"
msgstr ""

#: src\4-1-2-netlink.md:29
msgid "// Create Netlink object to listen to link messages"
msgstr ""

#: src\4-1-2-netlink.md:33
msgid ""
"// Here SONiC requests a full dump of the current state to get the status of "
"all links"
msgstr ""

#: src\4-1-2-netlink.md:35
msgid "\"Listen to link messages...\""
msgstr ""

#: src\4-1-2-netlink.md:38
msgid "// Register handler for link messages"
msgstr ""

#: src\4-1-2-netlink.md:47
msgid ""
"The `LinkSync` class above is an implementation of `NetMsg`, providing the "
"`onMsg` interface for handling link messages:"
msgstr ""

#: src\4-1-2-netlink.md:50
msgid "// File: sonic-swss - portsyncd/linksync.h"
msgstr ""

#: src\4-1-2-netlink.md:56
msgid "// NetMsg interface"
msgstr ""

#: src\4-1-2-netlink.md:61
msgid "// File: sonic-swss - portsyncd/linksync.cpp"
msgstr ""

#: src\4-1-2-netlink.md:67
msgid "// Write link state to Redis DB"
msgstr ""

#: src\4-1-2-netlink.md:68
msgid "\"down\""
msgstr ""

#: src\4-2-redis-based-channels.md:3
msgid ""
"To facilitate communication between services, SONiC provides a messaging "
"layer that is built on top of the Redis. On high-level, it contains 2 layers:"
msgstr ""

#: src\4-2-redis-based-channels.md:5
msgid ""
"First layer wraps frequenctly used redis operations and provide table "
"abstraction on top of it."
msgstr ""

#: src\4-2-redis-based-channels.md:6
msgid ""
"Second layer provides different channels for inter-service communication to "
"satisfy various communication channel requirements."
msgstr ""

#: src\4-2-redis-based-channels.md:8
msgid "Now, let's dive into them one by one."
msgstr ""

#: src\4-2-1-redis-wrappers.md:3
msgid "Redis Database Operation Layer"
msgstr ""

#: src\4-2-1-redis-wrappers.md:5
msgid ""
"The first layer, which is also the lowest layer, is the Redis database "
"operation layer. It wraps various basic commands, such as DB connection, "
"command execution, event notification callback interfaces, etc. The specific "
"class diagram is as follows:"
msgstr ""

#: src\4-2-1-redis-wrappers.md:7
msgid "![](assets/chapter-4/redis-ops.png)"
msgstr ""

#: src\4-2-1-redis-wrappers.md:9
msgid "Among them:"
msgstr ""

#: src\4-2-1-redis-wrappers.md:11
msgid ""
"**[RedisContext](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/dbconnector.h)**: Wraps and maintains the connection to Redis, and "
"closes the connection when it is destroyed."
msgstr ""

#: src\4-2-1-redis-wrappers.md:12
msgid ""
"**[DBConnector](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/dbconnector.h)**: Wraps all the underlying Redis commands used, such "
"as `SET`, `GET`, `DEL`, etc."
msgstr ""

#: src\4-2-1-redis-wrappers.md:13
msgid ""
"**[RedisTransactioner](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/redistran.h)**: Wraps Redis transaction operations, used to "
"execute multiple commands in a transaction, such as `MULTI`, `EXEC`, etc."
msgstr ""

#: src\4-2-1-redis-wrappers.md:14
msgid ""
"**[RedisPipeline](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/redispipeline.h)**: Wraps the hiredis redisAppendFormattedCommand "
"API, providing an asynchronous interface for executing Redis commands "
"similar to a queue (although most usage methods are still synchronous). It "
"is also one of the few classes that wraps the `SCRIPT LOAD` command, used to "
"load Lua scripts in Redis to implement stored procedures. Most classes in "
"SONiC that need to execute Lua scripts will use this class for loading and "
"calling."
msgstr ""

#: src\4-2-1-redis-wrappers.md:15
msgid ""
"**[RedisSelect](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/redisselect.h)**: Implements the Selectable interface to support the "
"epoll-based event notification mechanism (Event Polling). Mainly used to "
"trigger epoll callbacks when we receive a reply from Redis (we will "
"introduce this in more detail later)."
msgstr ""

#: src\4-2-1-redis-wrappers.md:16
msgid ""
"**[SonicDBConfig](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/dbconnector.h)**: This class is a \"static class\" that mainly "
"implements the reading and parsing of the SONiC DB configuration file. Other "
"database operation classes will use this class to obtain any configuration "
"information if needed."
msgstr ""

#: src\4-2-1-redis-wrappers.md:18
msgid "Table Abstraction Layer"
msgstr ""

#: src\4-2-1-redis-wrappers.md:20
msgid ""
"Above the Redis database operation layer is the table abstraction layer "
"established by SONiC using the keys in Redis. Since the format of each Redis "
"key is `<table-name><separator><key-name>`, SONiC needs to craft or parse "
"it, when accessing the database. For more details on how the database is "
"designed, please refer to [the database section for more information](/posts/"
"sonic-2-key-components/#database)."
msgstr ""

#: src\4-2-1-redis-wrappers.md:22
msgid "The main class diagram of related classes is as follows:"
msgstr ""

#: src\4-2-1-redis-wrappers.md:24
msgid "![](assets/chapter-4/table-abstraction.png)"
msgstr ""

#: src\4-2-1-redis-wrappers.md:26
msgid "In this diagram, we have three key classes:"
msgstr ""

#: src\4-2-1-redis-wrappers.md:28
msgid ""
"**[TableBase](https://github.com/sonic-net/sonic-swss-common/blob/master/"
"common/table.h)**: This class is the base class for all tables. It mainly "
"wraps the basic information of the table, such as the table name, Redis key "
"packaging, the name of the channel used for communication when each table is "
"modified, etc."
msgstr ""

#: src\4-2-1-redis-wrappers.md:29
msgid ""
"**[Table](https://github.com/sonic-net/sonic-swss-common/blob/master/common/"
"table.h)**: This class wraps the CRUD operations for each table. It contains "
"the table name and separator, so the final key can be constructed when "
"called."
msgstr ""

#: src\4-2-1-redis-wrappers.md:30
msgid ""
"**[ConsumerTableBase](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/consumertablebase.h)**: This class is the base class for "
"various SubscriptionTables. It mainly wraps a simple queue and its pop "
"operation (yes, only pop, no push, because it is for consumers only), for "
"upper layer calls."
msgstr ""

#: src\4-2-2-subscribe-state-table.md:3
msgid ""
"The most straight-forward redis-based communication channel is "
"[SubscriberStateTable](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/subscriberstatetable.h)."
msgstr ""

#: src\4-2-2-subscribe-state-table.md:5
msgid ""
"The idea is to use the built-in keyspace notification mechanism of the Redis "
"database [\\[4\\]](https://redis.io/docs/manual/keyspace-notifications/). "
"When any value in the Redis database changes, Redis sends two keyspace event "
"notifications: one is `<op>` on `__keyspace@<db-id>__:<key>` and the other "
"is `<key>` on `__keyevent@<db-id>__:<op>`. For example, deleting a key in "
"database `0` triggers:"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:12
msgid ""
"`SubscriberStateTable` listens for the first event notification and then "
"calls the corresponding callback function. The main classes related to it "
"are shown in this diagram, where we can see it inherits from "
"ConsumerTableBase because it is a consumer of Redis messages:"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:14
msgid "![](assets/chapter-4/subscriber-state-table.png)"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:16
msgid "Initialization"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:18
msgid ""
"From the initialization code, we can see how it subscribes to Redis event "
"notifications:"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:21 src\4-2-2-subscribe-state-table.md:39
msgid "// File: sonic-swss-common - common/subscriberstatetable.cpp"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:25
msgid "\"__keyspace@\""
msgstr ""

#: src\4-2-2-subscribe-state-table.md:26
msgid "\"__:\""
msgstr ""

#: src\4-2-2-subscribe-state-table.md:26
msgid "\"*\""
msgstr ""

#: src\4-2-2-subscribe-state-table.md:31
msgid "Event handling"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:33
msgid ""
"`SubscriberStateTable` handles the event reception and distribution in two "
"main functions:"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:35
msgid ""
"`readData()`: Reads pending events from Redis and puts them into the "
"ConsumerTableBase queue"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:36
msgid ""
"`pops()`: Retrieves the raw events from the queue, parses and passes them to "
"the caller via function parameters"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:55
msgid "/*prefix*/"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:60
msgid "// Pop from m_keyspace_event_buffer, which is filled by readData()"
msgstr ""

#: src\4-2-2-subscribe-state-table.md:63
msgid "// Parsing here ..."
msgstr ""

#: src\4-2-2-subscribe-state-table.md:76
#: src\4-2-3-notification-producer-consumer.md:57
#: src\4-2-4-producer-consumer-table.md:133
#: src\4-2-5-producer-consumer-state-table.md:128
msgid ""
"[Redis keyspace notifications](https://redis.io/docs/manual/keyspace-"
"notifications/)"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:1
msgid "NotificationProducer / NotificationConsumer"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:3
msgid ""
"When it comes to message communication, there is no way we can bypass "
"message queues. And this is the second communication channel in SONiC - "
"[NotificationProducer](https://github.com/sonic-net/sonic-swss-common/blob/"
"master/common/notificationproducer.h) and [NotificationConsumer](https://"
"github.com/sonic-net/sonic-swss-common/blob/master/common/"
"notificationconsumer.h)."
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:5
msgid ""
"This communication channel is implemented using Redis's built-in PubSub "
"mechanism, wrapping the `PUBLISH` and `SUBSCRIBE` commands. However, because "
"`PUBLISH` needs everything being send to be serialized in the command, due "
"to API limitations [\\[5\\]](https://redis.io/docs/reference/clients/), "
"these commands are not suitable for passing large data. Hence, in SONiC, it "
"is only used in limited places, such as simple notification scenarios (e.g., "
"timeout checks or restart checks in orchagent), which won't have large "
"payload, such as user configurations or data:"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:7
msgid "![](assets/chapter-4/notification-producer-consumer.png)"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:9
msgid ""
"In this communication channel, the producer side performs two main tasks:"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:11
msgid "Package the message into JSON format."
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:12
msgid "Call Redis command `PUBLISH` to send it."
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:14
msgid ""
"Because `PUBLISH` can only carry a single message, the \"op\" and \"data\" "
"fields are placed at the front of \"values\", then the `buildJson` function "
"is called to package them into a JSON array:"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:19
msgid ""
"// Pack the op and data into values array, then pack everything into a JSON "
"string as the message"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:25
msgid "// Publish message to Redis channel"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:27
msgid "\"PUBLISH %s %s\""
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:35
msgid ""
"The consumer side uses the `SUBSCRIBE` command to receive all notifications:"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:46
msgid "// Subscribe to Redis channel"
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:47
msgid "\"SUBSCRIBE \""
msgstr ""

#: src\4-2-3-notification-producer-consumer.md:58
#: src\4-2-4-producer-consumer-table.md:137
#: src\4-2-5-producer-consumer-state-table.md:132
msgid "[Redis client handling](https://redis.io/docs/reference/clients/)"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:1
msgid "ProducerTable / ConsumerTable"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:3
msgid ""
"Although `NotificationProducer` and `NotificationConsumer` is straight-"
"forward, but they are not suitable for passing large data. Therefore, SONiC "
"provides another message-queue-based communication mechanism that works in "
"similar way - [ProducerTable](https://github.com/sonic-net/sonic-swss-common/"
"blob/master/common/producertable.h) and [ConsumerTable](https://github.com/"
"sonic-net/sonic-swss-common/blob/master/common/consumertable.h)."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:5
msgid ""
"This channel leverages the Redis list to pass the message. Unlike "
"Notification, which has limited message capacity, it stores all the message "
"data in a Redis list with a very slim custom messsage format. This solves "
"the message size limitation in Notification. In SONiC, it is mainly used in "
"FlexCounter, the `syncd` service, and `ASIC_DB`."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:7
msgid "Message format"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:9
msgid ""
"In this channel, a message is a triplet (`Key`, `FieldValuePairs`, `Op`) and "
"will be pushed into the Redis list (Key = `<table-name>_KEY_VALUE_OP_QUEUE`) "
"as 3 list items:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:11
msgid ""
"`Key` is table name and key (e.g., `SAI_OBJECT_TYPE_SWITCH:"
"oid:0x21000000000000`)."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:12
msgid ""
"`FieldValuePairs` are the field that needs to be updated in the database and "
"their values, which is serialized into a JSON string: `\"[\\\"Field1\\\", \\"
"\"Value1\\\", \\\"Field2\\\", \\\"Value2\\\", ...]\"`."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:13
msgid "`Op` is the operation to be performed (e.g., Set, Get, Del, etc.)"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:15
msgid ""
"Once the message is pushed into the Redis list, a notification will be "
"published to a specific channel (Key = `<table-name>_CHANNEL`) with only a "
"single character \"G\" as payload, indicating that there is a new message in "
"the list."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:17
msgid ""
"So, when using this channel, we can imaging the actual data stored in the "
"Redis:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:19
msgid "In the channel: `[\"G\", \"G\", ...]`"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:20
msgid ""
"In the list: `[\"Key1\", \"FieldValuePairs1\", \"Op1\", \"Key2\", "
"\"FieldValuePairs2\", \"Op2\", ...]`"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:22
msgid "Queue operations"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:24
msgid ""
"Using this message format, `ProducerTable` and `ConsumerTable` provides two "
"queue operations:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:26
msgid ""
"Enqueue: `ProducerTable` uses a Lua script to atomically write the message "
"triplet into the Redis list and then publishes an update notification to a "
"specific channel."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:27
msgid ""
"Pop: `ConsumerTable` also uses a Lua script to atomically read the message "
"triplet from the message queue and writes the requested changes to the "
"database during the read process."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:33
msgid ""
"Its main class diagram is shown below. In ProducerTable, `m_shaEnqueue` and "
"in ConsumerTable, `m_shaPop` are the two Lua scripts we mentioned. After "
"they are loaded, you can call them atomically via `EVALSHA`:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:35
msgid "![](assets/chapter-4/producer-consumer-table.png)"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:37
msgid ""
"The core logic of ProducerTable is as follows, showing how values are packed "
"into JSON and how `EVALSHA` is used to call Lua scripts:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:40
msgid "// File: sonic-swss-common - common/producertable.cpp"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:45
msgid "\"redis.call('LPUSH', KEYS[1], ARGV[1], ARGV[2], ARGV[3]);\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:46
msgid "\"redis.call('PUBLISH', KEYS[2], ARGV[4]);\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:53
msgid "\"S\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:58
msgid "\"{}\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:58
msgid "\"D\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:61
msgid "/* prefix */"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:66
msgid "\"EVALSHA %s 2 %s %s %s %s %s %s\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:73
msgid "\"G\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:79
msgid ""
"On the other side, ConsumerTable is slightly more complicated because it "
"supports many types of ops. The logic is written in a separate file (`common/"
"consumer_table_pops.lua`). Interested readers can explore it further:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:82
msgid "// File: sonic-swss-common - common/consumertable.cpp"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:88
msgid "\"consumer_table_pops.lua\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:95
msgid ""
"// Note that here we are processing the messages in bulk with POP_BATCH_SIZE!"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:98
msgid "\"EVALSHA %s 2 %s %s %d %d\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:107
msgid "// Parse and pack the messages in bulk"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:112
msgid "Monitor"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:114
msgid ""
"To monitor how the `ProducerTable` and `ConsumerTable` work, we can use the "
"`redis-cli monitor` command to see the actual Redis commands that being "
"executed."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:117
msgid "# Filter to `LPUSH` and `PUBLISH` commands to help us reduce the noise."
msgstr ""

#: src\4-2-4-producer-consumer-table.md:118
msgid "\"LPUSH|PUBLISH\""
msgstr ""

#: src\4-2-4-producer-consumer-table.md:121
msgid ""
"And here is an example of the output showing a `ProducerTable` enqueue "
"operation:"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:123
msgid ""
"```text\n"
"1735966216.139741 [1 lua] \"LPUSH\" \"ASIC_STATE_KEY_VALUE_OP_QUEUE\" "
"\"SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000\" \"[\\"
"\"SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY\\\",\\\"1\\\"]\" \"Sget"
"\"               \n"
"1735966216.139774 [1 lua] \"PUBLISH\" \"ASIC_STATE_CHANNEL@1\" \"G\" \n"
"```"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:134
#: src\4-2-5-producer-consumer-state-table.md:129
msgid "[Redis Transactions](https://redis.io/docs/manual/transactions/)"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:135
#: src\4-2-5-producer-consumer-state-table.md:130
msgid ""
"[Redis Atomicity with Lua](https://developer.redis.com/develop/java/spring/"
"rate-limiting/fixed-window/reactive-lua/)"
msgstr ""

#: src\4-2-4-producer-consumer-table.md:136
#: src\4-2-5-producer-consumer-state-table.md:131
msgid "[Redis hashes](https://redis.io/docs/data-types/hashes/)"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:1
msgid "ProducerStateTable / ConsumerStateTable"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:3
msgid ""
"Although `Producer/ConsumerTable` is straightforward and maintains the order "
"of the messages, each message can only update one table key and requires "
"JSON serialization. However, in many cases, we don't need strict ordering "
"but need higher throughput. To optimize performance, SONiC introduces the "
"fourth, and most frequently used, communication channel: [ProducerStateTable]"
"(https://github.com/sonic-net/sonic-swss-common/blob/master/common/"
"producerstatetable.h) and [ConsumerStateTable](https://github.com/sonic-net/"
"sonic-swss-common/blob/master/common/consumerstatetable.h)."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:5
msgid "Overview"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:7
msgid ""
"Unlike `ProducerTable`, `ProducerStateTable` uses a Hash to store messages "
"instead of a List. This means the order of messages will not be guranteed, "
"but it can significantly boosts performance:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:9
msgid "First, no more JSON serialization, hence its overhead is gone."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:10
msgid "Second, batch processing:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:11
msgid ""
"Multiple table updates can be merged into one (single pending update key set "
"per table)."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:12
msgid ""
"If the same Field under the same Key is changed multiple times, only the "
"latest change is preserved, merging all changes related to that Key into a "
"single message and reducing unnecessary handling."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:14
msgid ""
"`Producer/ConsumerStateTable` is more complex under the hood than `Producer/"
"ConsumerTable`. The related classes are shown in the diagram below, where "
"`m_shaSet` and `m_shaDel` store the Lua scripts for modifying and sending "
"messages, while `m_shaPop` is used to retrieve messages:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:16
msgid "![](assets/chapter-4/producer-consumer-state-table.png)"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:18
msgid "Sending messages"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:20
msgid "When sending messages:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:22
msgid "Each message is stored in two parts:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:23
msgid ""
"KEY_SET: keeps track of which Keys have been modified (stored as a Set at "
"`<table-name_KEY_SET>`)"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:24
msgid ""
"A series of Hash: One Hash for each modified Key (stored at `_<redis-key-"
"name>`)."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:25
msgid ""
"After storing a message, if the Producer finds out it's a new Key, it calls "
"`PUBLISH` to notify `<table-name>_CHANNEL@<db-id>` that a new Key has "
"appeared."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:28
msgid "// File: sonic-swss-common - common/producerstatetable.cpp"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:35
msgid "\"local added = redis.call('SADD', KEYS[2], ARGV[2])\\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:36
msgid "\"for i = 0, #KEYS - 3 do\\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:37
msgid ""
"\"    redis.call('HSET', KEYS[3 + i], ARGV[3 + i * 2], ARGV[4 + i * 2])\\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:38
#: src\4-2-5-producer-consumer-state-table.md:41
msgid "\"end\\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:39
msgid "\" if added > 0 then \\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:40
msgid "\"    redis.call('PUBLISH', KEYS[1], ARGV[1])\\n\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:47
msgid "Receiving messages"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:49
msgid "When receiving messages:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:51
msgid ""
"The consumer uses `SUBSCRIBE` to listen on `<table-name>_CHANNEL@<db-id>`. "
"Once a new message arrives, it calls a Lua script to run `HGETALL`, fetch "
"all Keys, and write them into the database."
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:58
msgid "\"consumer_state_table_pops.lua\""
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:67
msgid "Example"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:69
msgid "To illustrate, here is an example of enabling Port Ethernet0:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:71
msgid ""
"First, we call `config interface startup Ethernet0` from the command line to "
"enable Ethernet0. This causes `portmgrd` to send a status update to APP_DB "
"via ProducerStateTable, as shown below:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:73
msgid ""
"```redis\n"
"EVALSHA \"<hash-of-set-lua>\" \"6\" \"PORT_TABLE_CHANNEL@0\" "
"\"PORT_TABLE_KEY_SET\" \n"
"    \"_PORT_TABLE:Ethernet0\" \"_PORT_TABLE:Ethernet0\" \"_PORT_TABLE:"
"Ethernet0\" \"_PORT_TABLE:Ethernet0\" \"G\"\n"
"    \"Ethernet0\" \"alias\" \"Ethernet5/1\" \"index\" \"5\" \"lanes\" "
"\"9,10,11,12\" \"speed\" \"40000\"\n"
"```"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:79
msgid "This command triggers the following creation and broadcast:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:81
msgid ""
"```redis\n"
"SADD \"PORT_TABLE_KEY_SET\" \"_PORT_TABLE:Ethernet0\"\n"
"HSET \"_PORT_TABLE:Ethernet0\" \"alias\" \"Ethernet5/1\"\n"
"HSET \"_PORT_TABLE:Ethernet0\" \"index\" \"5\"\n"
"HSET \"_PORT_TABLE:Ethernet0\" \"lanes\" \"9,10,11,12\"\n"
"HSET \"_PORT_TABLE:Ethernet0\" \"speed\" \"40000\"\n"
"PUBLISH \"PORT_TABLE_CHANNEL@0\" \"_PORT_TABLE:Ethernet0\"\n"
"```"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:90
msgid "Thus, the message is ultimately stored in APPL_DB as follows:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:103
msgid ""
"When ConsumerStateTable receives the message, it also calls `EVALSHA` to "
"execute a Lua script, such as:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:105
msgid ""
"```redis\n"
"EVALSHA \"<hash-of-pop-lua>\" \"3\" \"PORT_TABLE_KEY_SET\" \"PORT_TABLE:\" "
"\"PORT_TABLE_DEL_SET\" \"8192\" \"_\"\n"
"```"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:109
msgid "Similar to the Producer side, this script runs:"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:111
msgid ""
"```redis\n"
"SPOP \"PORT_TABLE_KEY_SET\" \"_PORT_TABLE:Ethernet0\"\n"
"HGETALL \"_PORT_TABLE:Ethernet0\"\n"
"HSET \"PORT_TABLE:Ethernet0\" \"alias\" \"Ethernet5/1\"\n"
"HSET \"PORT_TABLE:Ethernet0\" \"index\" \"5\"\n"
"HSET \"PORT_TABLE:Ethernet0\" \"lanes\" \"9,10,11,12\"\n"
"HSET \"PORT_TABLE:Ethernet0\" \"speed\" \"40000\"\n"
"DEL \"_PORT_TABLE:Ethernet0\"\n"
"```"
msgstr ""

#: src\4-2-5-producer-consumer-state-table.md:121
msgid "At this point, the data update is complete."
msgstr ""

#: src\4-3-zmq-based-channels.md:1
msgid "ZMQ-based Channels"
msgstr ""

#: src\4-4-orch-layer.md:1
msgid "Service Layer - Orch"
msgstr ""

#: src\4-4-orch-layer.md:3
msgid ""
"Finally, to make it more convenient for building services, SONiC provides "
"another layer of abstraction on top of the communication layer, offering a "
"base class for services: [Orch](https://github.com/sonic-net/sonic-swss/blob/"
"master/src/orchagent/orch.h)."
msgstr ""

#: src\4-4-orch-layer.md:5
msgid ""
"With all the lower layers, adding message communication support in Orch is "
"relatively straightforward. The main class diagram is shown below:"
msgstr ""

#: src\4-4-orch-layer.md:7
msgid "![](assets/chapter-4/orch.png)"
msgstr ""

#: src\4-4-orch-layer.md:13
msgid ""
"We can see that Orch mainly wraps `SubscriberStateTable` and "
"`ConsumerStateTable` to simplify and unify the message subscription. The "
"core code is very simple and creates different Consumers based on the "
"database type:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:1
msgid "Event Dispatching and Error Handling"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:3
msgid "Epoll-based Event Dispatching"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:5
msgid ""
"Just like many other Linux services, SONiC uses epoll at its core for event "
"dispatching:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:7
msgid ""
"Any class that supports event dispatching should inherit from `Selectable` "
"and implement two key functions:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:8
msgid ""
"`int getFd();`: Returns the fd for epoll to listen on. For most services, "
"this fd is the one used for Redis communication, so the call to `getFd()` "
"ultimately delegates to the Redis library."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:9
msgid "`uint64_t readData()`: Reads data when an event arrives."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:10
msgid ""
"Any objects that need to participate in event dispatching must register with "
"the `Select` class. This class registers all `Selectable` objects' fds with "
"epoll and calls `Selectable`'s `readData()` when an event arrives."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:12
msgid "Here's the class diagram:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:14
msgid "![](assets/chapter-4/event-polling.png)"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:16
msgid ""
"The core logic lives in the `Select` class, which can be simplified as "
"follows:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:37
msgid "// error handling here ..."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:47
msgid "// After update callback ..."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:55
msgid ""
"However, here comes the question... where is the callback? As mentioned, "
"`readData()` only reads the message and stores it in a pending queue for "
"processing. The real processing needs to call `pops()`. So at which point "
"does every upper-level message handler get called?"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:57
msgid ""
"Here, let's look back again at `portmgrd`'s `main` function. From the "
"simplified code below, we can see - unlike a typical event loop, SONiC does "
"not handle events with callbacks; the outermost event loop directly calls "
"the actual handlers:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:64
msgid "// Create PortMgr, which implements Orch interface."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:68
msgid "// Create Select object for event loop and add PortMgr to it."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:74
msgid "// Event loop"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:80
msgid "// When anyone of the selectables gets signaled, select() will call"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:81
msgid "// into readData() and fetch all events, then return."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:85
msgid "// Then, we call into execute() explicitly to process all events."
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:93
msgid "Error Handling"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:95
msgid ""
"Another thing about event loops is error handling. For example, if a Redis "
"command fails, or the connection is broken, or any kind of failure happens, "
"what will happen to our services?"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:97
msgid ""
"SONiC's error handling is very simple: it just throws exceptions (for "
"example, in the code that fetches command results). Then the event loop "
"catches the exceptions, logs them, and continues:"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:105
msgid "// The only reason of error is REDIS_ERR_OOM (Out of memory)"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:106
msgid "// ref: https://github.com/redis/hiredis/blob/master/hiredis.c"
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:113
msgid "\"Failed to redisGetReply with \""
msgstr ""

#: src\4-5-event-polling-and-error-handling.md:119
msgid ""
"There is no specific code here for statistics or telemetry, so monitoring is "
"somewhat weak. We also need to consider data errors (for example, partial "
"writes leading to corrupted data), though simply restarting `*syncd` or "
"`*mgrd` services might fix such issues because many stored data in database "
"will be wiped out, such as APPL_DB, and the services will do a full sync on "
"startup."
msgstr ""

#: src\5-core-components.md:1
msgid "Core Components"
msgstr ""

#: src\5-core-components.md:3
msgid ""
"In this chapter, we take a deeper look at some of the representative core "
"components in SONiC and their workflows from a code perspective."
msgstr ""

#: src\5-core-components.md:5
msgid ""
"```admonish note\n"
"For helping us to read and understand, all the code shown here will be "
"simplified to its core part to illustrate the process. If you would like to "
"read the full code, please refer to [the original code in the repository]"
"(./3-1-code-repos.html).\n"
"\n"
"Additionally, the relevant file path of the code will be shared in the "
"beginning of each code block, which is based on the SONiC's main repository: "
"[sonic-buildimage](https://github.com/sonic-net/sonic-buildimage). If the "
"code is not imported by buildimage repo, the full URL will be provided.\n"
"```"
msgstr ""

#: src\5-1-syncd-and-sai.md:3
msgid ""
"[Syncd Container](./2-3-key-containers.html#asic-management-container-syncd) "
"is the container in SONiC dedicated to managing the ASIC. The key process "
"`syncd` is responsible for communicating with the Redis database, loading "
"SAI implementation, and interacting with it to handle ASIC initialization, "
"configuration, status reporting, and so on."
msgstr ""

#: src\5-1-syncd-and-sai.md:5
msgid ""
"Since many SONiC workflows ultimately need to interact with the ASIC through "
"Syncd and SAI, this part becomes common to all those workflows. Therefore, "
"before diving into other workflows, let's take a look at how Syncd and SAI "
"work first."
msgstr ""

#: src\5-1-syncd-and-sai.md:7
msgid "Syncd Startup Flow"
msgstr ""

#: src\5-1-syncd-and-sai.md:9
msgid ""
"The entry point of the `syncd` process is the `syncd_main` function in "
"`syncd_main.cpp`. The startup flow can be roughly divided into two parts."
msgstr ""

#: src\5-1-syncd-and-sai.md:11
msgid "The first part creates and initializes various objects:"
msgstr ""

#: src\5-1-syncd-and-sai.md:29
msgid "The second part starts the main loop and handles initialization events:"
msgstr ""

#: src\5-1-syncd-and-sai.md:64
msgid "Now, let's dive into the code to see how Syncd and SAI are implemented."
msgstr ""

#: src\5-1-syncd-and-sai.md:66
msgid "The syncd_main Function"
msgstr ""

#: src\5-1-syncd-and-sai.md:68
msgid ""
"The `syncd_main` function itself is straightforward: it creates a `Syncd` "
"object and then calls its `run` method:"
msgstr ""

#: src\5-1-syncd-and-sai.md:71
msgid "// File: src/sonic-sairedis/syncd/syncd_main.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:81
msgid ""
"The Syncd constructor initializes each feature in Syncd, while the run "
"method starts the Syncd main loop."
msgstr ""

#: src\5-1-syncd-and-sai.md:83
msgid "The Syncd Constructor"
msgstr ""

#: src\5-1-syncd-and-sai.md:85
msgid ""
"The `Syncd` constructor creates or initializes the key components in "
"`Syncd`, such as database connection objects, statistics management, and "
"ASIC notification handler. The key code looks like below:"
msgstr ""

#: src\5-1-syncd-and-sai.md:88 src\5-1-syncd-and-sai.md:229
#: src\5-1-syncd-and-sai.md:319 src\5-1-syncd-and-sai.md:370
#: src\5-1-syncd-and-sai.md:466 src\5-1-syncd-and-sai.md:730
msgid "// File: src/sonic-sairedis/syncd/Syncd.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:98
msgid "// Load context config"
msgstr ""

#: src\5-1-syncd-and-sai.md:103
msgid "// Create FlexCounter manager"
msgstr ""

#: src\5-1-syncd-and-sai.md:106
msgid "// Create DB related objects"
msgstr ""

#: src\5-1-syncd-and-sai.md:111
msgid "// Create notification processor and handler"
msgstr ""

#: src\5-1-syncd-and-sai.md:119
msgid "// Init many other event handlers here"
msgstr ""

#: src\5-1-syncd-and-sai.md:123 src\5-1-syncd-and-sai.md:143
msgid "// Initialize SAI"
msgstr ""

#: src\5-1-syncd-and-sai.md:129
msgid "SAI Initialization and VendorSai"
msgstr ""

#: src\5-1-syncd-and-sai.md:131
msgid ""
"The last and most important step in `Syncd` initialization is to initialize "
"SAI. [In the core component introduction to SAI](./2-4-sai-intro.html), we "
"briefly described how SAI is initialized and implemented, and how it "
"provides support for different platforms in SONiC. And here, we will focus "
"more on how Syncd wraps SAI and uses it."
msgstr ""

#: src\5-1-syncd-and-sai.md:133
msgid ""
"`Syncd` uses `VendorSai` to wrap all SAI APIs to simplify upper-level calls. "
"The initialization looks like below, essentially just calling the sai "
"initialize and api query functions, and handling errors:"
msgstr ""

#: src\5-1-syncd-and-sai.md:136 src\5-1-syncd-and-sai.md:168
msgid "// File: src/sonic-sairedis/syncd/VendorSai.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:147
msgid "// If SAI is initialized successfully, query all SAI API methods."
msgstr ""

#: src\5-1-syncd-and-sai.md:148
msgid ""
"// sai_metadata_api_query will also update all extern global sai_*_api "
"variables, so we can also use"
msgstr ""

#: src\5-1-syncd-and-sai.md:149
msgid ""
"// sai_metadata_get_object_type_info to get methods for a specific SAI "
"object type."
msgstr ""

#: src\5-1-syncd-and-sai.md:161
msgid ""
"Once all the SAI APIs have been acquired, we can call into the SAI "
"implementation using the `VendorSai` object."
msgstr ""

#: src\5-1-syncd-and-sai.md:163
msgid ""
"Currently, `VendorSai` internally has two different ways to call the SAI "
"APIs:"
msgstr ""

#: src\5-1-syncd-and-sai.md:165
msgid ""
"Using `sai_object_type_info_t` from SAI metadata, which essentially acts "
"like a virtual table for all SAI Objects:"
msgstr ""

#: src\5-1-syncd-and-sai.md:182
msgid ""
"Using `m_apis` stored in the `VendorSai` object. This approach needs us to "
"check the object type and then call the corresponding APIs, so the code "
"becomes more verbose:"
msgstr ""

#: src\5-1-syncd-and-sai.md:214
msgid "\"not implemented, FIXME\""
msgstr ""

#: src\5-1-syncd-and-sai.md:222
msgid "The first approach is more succinct."
msgstr ""

#: src\5-1-syncd-and-sai.md:224
msgid "Main Event Loop"
msgstr ""

#: src\5-1-syncd-and-sai.md:226
msgid ""
"`Syncd`'s main event loop follows SONiC's standard [event dispatching](./4-5-"
"event-polling-and-error-handling.html) pattern. On startup, Syncd registers "
"all Selectable objects handling events with a Select object that waits for "
"events. The main loop calls \"select\" to wait for events:"
msgstr ""

#: src\5-1-syncd-and-sai.md:236
msgid "// Start notification processing thread"
msgstr ""

#: src\5-1-syncd-and-sai.md:239
msgid "// Start MDIO threads"
msgstr ""

#: src\5-1-syncd-and-sai.md:243
msgid "// Registering selectable for event polling"
msgstr ""

#: src\5-1-syncd-and-sai.md:249
msgid "// Main event loop"
msgstr ""

#: src\5-1-syncd-and-sai.md:257
msgid "// Handling switch restart event and restart switch here."
msgstr ""

#: src\5-1-syncd-and-sai.md:263
msgid "// Handle redis updates here."
msgstr ""

#: src\5-1-syncd-and-sai.md:266
msgid "\"select failed: %d\""
msgstr ""

#: src\5-1-syncd-and-sai.md:274
msgid ""
"Here, `m_selectableChannel` handles Redis database events. It interacts with "
"Redis [ProducerTable / ConsumerTable](./4-2-4-producer-consumer-table.html). "
"Hence, all operations from `orchagent` will be stored in Redis lists, "
"waiting for `Syncd` to consume."
msgstr ""

#: src\5-1-syncd-and-sai.md:277
msgid "// File: src/sonic-sairedis/meta/RedisSelectableChannel.h"
msgstr ""

#: src\5-1-syncd-and-sai.md:288
msgid "// SelectableChannel overrides"
msgstr ""

#: src\5-1-syncd-and-sai.md:292
msgid "// Selectable overrides"
msgstr ""

#: src\5-1-syncd-and-sai.md:305
msgid "During the main loop startup, `Syncd` also launches two threads:"
msgstr ""

#: src\5-1-syncd-and-sai.md:307
msgid ""
"A notification processing thread for receiving ASIC-reported notifications: "
"`m_processor->startNotificationsProcessingThread()`"
msgstr ""

#: src\5-1-syncd-and-sai.md:308
msgid ""
"A thread for handling MDIO communication: `m_mdioIpcServer->startMdioThread()"
"`"
msgstr ""

#: src\5-1-syncd-and-sai.md:310
msgid ""
"We'll discuss their details more thoroughly when introducing related "
"workflows."
msgstr ""

#: src\5-1-syncd-and-sai.md:312
msgid "Initialize SAI Switch and Notifications"
msgstr ""

#: src\5-1-syncd-and-sai.md:314
msgid ""
"Once the main event loop is started, `Syncd` will call into SAI to create "
"the Switch object. There are two main entry points: either a create switch "
"request from ASIC_DB (called by swss) or `Syncd` directlly calls it for the "
"Warm Boot process. Either way, the internal flow is similar."
msgstr ""

#: src\5-1-syncd-and-sai.md:316
msgid ""
"A crucial step here is initializing the notification callbacks in the SAI "
"implementation, such as FDB events. These callback functions are passed to "
"SAI as Switch attributes in `create_switch`. The SAI implementation stores "
"them so it can call back into `Syncd` whenever these events occur:"
msgstr ""

#: src\5-1-syncd-and-sai.md:324
msgid "// Parse event into SAI object"
msgstr ""

#: src\5-1-syncd-and-sai.md:332
msgid "// Update notifications pointers in attribute list"
msgstr ""

#: src\5-1-syncd-and-sai.md:340
msgid ""
"// ProcessQuadEventInInitViewMode will eventually call into VendorSai, which "
"calls create_swtich function in SAI."
msgstr ""

#: src\5-1-syncd-and-sai.md:347 src\5-1-syncd-and-sai.md:702
msgid "// File: src/sonic-sairedis/syncd/NotificationHandler.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:371
msgid "// Call stack: processQuadEvent"
msgstr ""

#: src\5-1-syncd-and-sai.md:372
msgid "//          -> processQuadEventInInitViewMode"
msgstr ""

#: src\5-1-syncd-and-sai.md:373
msgid "//          -> processQuadInInitViewModeCreate"
msgstr ""

#: src\5-1-syncd-and-sai.md:374
msgid "//          -> onSwitchCreateInInitViewMode"
msgstr ""

#: src\5-1-syncd-and-sai.md:392
msgid ""
"From the open-sourced Mellanox's implementation, we can see how the SAI "
"switch is created and the notification callbacks are set:"
msgstr ""

#: src\5-1-syncd-and-sai.md:431
msgid "ASIC Programming Workflow"
msgstr ""

#: src\5-1-syncd-and-sai.md:433
msgid ""
"ASIC programming workflow is the most important workflow in `Syncd`. When "
"`orchagent` discovers any configuration changes, it sends ASIC programming "
"request via `ASIC_DB`, which triggers this workflow and uses SAI to update "
"the ASIC. After understanding Syncd's main event loop and the communication "
"channels, the workflow will become easier to follow."
msgstr ""

#: src\5-1-syncd-and-sai.md:435
msgid "All steps happen sequentially on the main thread:"
msgstr ""

#: src\5-1-syncd-and-sai.md:461
msgid ""
"First, `orchagent` sends operations through Redis, which will be received by "
"the `RedisSelectableChannel.` When the main event loop processes "
"`m_selectableChannel`, it calls `processEvent` to process it, just like what "
"we have discussed in the main event loop section."
msgstr ""

#: src\5-1-syncd-and-sai.md:463
msgid ""
"Then, `processEvent` calls the relevant SAI API to update the ASIC. The "
"logic is a giant switch-case statement that dispatches the operations:"
msgstr ""

#: src\5-1-syncd-and-sai.md:469
msgid "// Loop all operations in the queue"
msgstr ""

#: src\5-1-syncd-and-sai.md:496
msgid "// Parse operation"
msgstr ""

#: src\5-1-syncd-and-sai.md:511
msgid "// Process the operation"
msgstr ""

#: src\5-1-syncd-and-sai.md:519
msgid "// Send response"
msgstr ""

#: src\5-1-syncd-and-sai.md:547
msgid "\"api %s not supported\""
msgstr ""

#: src\5-1-syncd-and-sai.md:552
msgid "ASIC State Change Notification Workflow"
msgstr ""

#: src\5-1-syncd-and-sai.md:554
msgid ""
"On the other hand, when the ASIC state is changed or needs to report certain "
"status, it notifies us through SAI. `Syncd` listens for these notifications, "
"then reports them back to `orchagent` through our communication channel on "
"top of `ASIC_DB`."
msgstr ""

#: src\5-1-syncd-and-sai.md:556
msgid "The workflow shows as below:"
msgstr ""

#: src\5-1-syncd-and-sai.md:587
msgid ""
"Here, let's look into a real implementation. For better understanding, we "
"still use Mellanox's open-sourced SAI implementation as an example."
msgstr ""

#: src\5-1-syncd-and-sai.md:589
msgid ""
"First of all, SAI implementation needs to be able to receive notification "
"from ASIC. This is done by calling into the ASIC SDK. In Mellanox's SAI, it "
"sets up an event thread to hook into ASIC, then use `select` to handle the "
"events from ASIC SDK:"
msgstr ""

#: src\5-1-syncd-and-sai.md:608
msgid "// Init SDK API"
msgstr ""

#: src\5-1-syncd-and-sai.md:621
msgid "// Register for port and channel notifications"
msgstr ""

#: src\5-1-syncd-and-sai.md:639
msgid "// Port state change event"
msgstr ""

#: src\5-1-syncd-and-sai.md:641
msgid "// Parse port state event here ..."
msgstr ""

#: src\5-1-syncd-and-sai.md:648
msgid "// Receive notification event."
msgstr ""

#: src\5-1-syncd-and-sai.md:654
msgid "// BFD packet event"
msgstr ""

#: src\5-1-syncd-and-sai.md:657
msgid "// Parse and check event valid here ..."
msgstr ""

#: src\5-1-syncd-and-sai.md:662
msgid ""
"// Same way to handle BFD timeout event, Bulk counter ready event. Emiited."
msgstr ""

#: src\5-1-syncd-and-sai.md:664
msgid "// FDB event and packet event handling"
msgstr ""

#: src\5-1-syncd-and-sai.md:666
msgid "\"FDB event\""
msgstr ""

#: src\5-1-syncd-and-sai.md:672
msgid "// Parse FDB events here ..."
msgstr ""

#: src\5-1-syncd-and-sai.md:681
msgid "// Packet event handling"
msgstr ""

#: src\5-1-syncd-and-sai.md:695
msgid "Using FDB event as an example:"
msgstr ""

#: src\5-1-syncd-and-sai.md:697
msgid ""
"When ASIC sends the FDB events, it will be received by the event loop above."
msgstr ""

#: src\5-1-syncd-and-sai.md:698
msgid ""
"The callback `g_notification_callbacks.on_fdb_event` stored in SAI "
"implementation will be called to handle this event."
msgstr ""

#: src\5-1-syncd-and-sai.md:699
msgid ""
"It then calls `NotificationHandler::onFdbEvent` in Syncd to serialize the "
"event and put it into the notification queue:"
msgstr ""

#: src\5-1-syncd-and-sai.md:710
msgid ""
"Then the notification thread is signaled to pick up this event from the "
"queue, then process it under the syncd lock:"
msgstr ""

#: src\5-1-syncd-and-sai.md:713 src\5-1-syncd-and-sai.md:743
#: src\5-1-syncd-and-sai.md:763 src\5-1-syncd-and-sai.md:797
msgid "// File: src/sonic-sairedis/syncd/NotificationProcessor.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:720
msgid "// When notification arrives, it will signal this condition variable."
msgstr ""

#: src\5-1-syncd-and-sai.md:723
msgid "// Process notifications in the queue."
msgstr ""

#: src\5-1-syncd-and-sai.md:731
msgid "// Call from NotificationProcessor::processNotification"
msgstr ""

#: src\5-1-syncd-and-sai.md:740
msgid ""
"Now, it goes into the event dispatching and handling logic. "
"`syncProcessNotification` function is essentially a series of `if-else` "
"statements, which calls the corresponding handling function based on the "
"event type:"
msgstr ""

#: src\5-1-syncd-and-sai.md:755
msgid "\"unknown notification: %s\""
msgstr ""

#: src\5-1-syncd-and-sai.md:760
msgid ""
"For each event, the handling function deserializes the event and processes "
"it, such as `handle_fdb_event` and `process_on_fdb_event`:"
msgstr ""

#: src\5-1-syncd-and-sai.md:779
msgid "// Check FDB event notification data here"
msgstr ""

#: src\5-1-syncd-and-sai.md:788
msgid "// Send notification"
msgstr ""

#: src\5-1-syncd-and-sai.md:794
msgid ""
"Finally, it's written to ASIC_DB via [NotificationProducer](./4-2-3-"
"notification-producer-consumer.md) to notify `orchagent`:"
msgstr ""

#: src\5-1-syncd-and-sai.md:808
msgid "// File: src/sonic-sairedis/syncd/RedisNotificationProducer.cpp"
msgstr ""

#: src\5-1-syncd-and-sai.md:814
msgid ""
"// The m_notificationProducer is created in the ctor of "
"RedisNotificationProducer as below:"
msgstr ""

#: src\5-1-syncd-and-sai.md:815
msgid ""
"// m_notificationProducer = std::make_shared<swss::NotificationProducer>"
"(m_db.get(), REDIS_TABLE_NOTIFICATIONS_PER_DB(dbName));"
msgstr ""

#: src\5-1-syncd-and-sai.md:820
msgid "That's it! This is basically how things work in high level in `Syncd`!"
msgstr ""

#: src\5-1-syncd-and-sai.md:825 src\5-2-2-route-update-in-frr.md:742
#: src\5-2-3-route-update-in-sonic.md:741
msgid ""
"[Github repo: sonic-sairedis](https://github.com/sonic-net/sonic-sairedis/)"
msgstr ""

#: src\5-2-bgp.md:3
msgid ""
"[BGP](https://datatracker.ietf.org/doc/html/rfc4271) might be the most "
"commonly used and important feature in switches. In this section, we take a "
"deeper look at BGP-related workflows."
msgstr ""

#: src\5-2-bgp.md:5
msgid "BGP Processes"
msgstr ""

#: src\5-2-bgp.md:7
msgid ""
"SONiC uses [FRRouting](https://frrouting.org/) as its BGP implementation, "
"responsible for handling the BGP protocol. FRRouting is an open-source "
"routing software that supports multiple routing protocols, including BGP, "
"OSPF, IS-IS, RIP, PIM, LDP, etc. When a new version of FRR is released, "
"SONiC synchronizes it to the [SONiC FRR repository: sonic-frr](https://"
"github.com/sonic-net/sonic-frr), with each version corresponding to a branch "
"such as `frr/8.2`."
msgstr ""

#: src\5-2-bgp.md:9
msgid ""
"FRR mainly consists of two major parts. The first part includes the "
"implementations of each protocol, where processes are named `*d.` When they "
"receive routing update notifications, they inform the second part, the "
"\"zebra\" process. The `zebra` process performs route selection and "
"synchronizes the best routing information to the kernel. Its main structure "
"is shown below:"
msgstr ""

#: src\5-2-bgp.md:30
msgid ""
"In SONiC, these FRR processes all run inside the `bgp` container. In "
"addition, to integrate FRR with Redis, SONiC runs a process called "
"`fpmsyncd` (Forwarding Plane Manager syncd) within the `bgp` container. Its "
"main function is to listen to kernel routing updates and synchronize them to "
"the `APPL_DB`. Because it is not part of FRR, its implementation is located "
"in the [sonic-swss](https://github.com/sonic-net/sonic-swss) repository."
msgstr ""

#: src\5-2-bgp.md:36 src\5-2-1-bgp-cli.md:92
#: src\5-2-2-route-update-in-frr.md:740 src\5-2-3-route-update-in-sonic.md:739
msgid "[Github repo: sonic-frr](https://github.com/sonic-net/sonic-frr)"
msgstr ""

#: src\5-2-bgp.md:37 src\5-2-1-bgp-cli.md:94
#: src\5-2-2-route-update-in-frr.md:743 src\5-2-3-route-update-in-sonic.md:742
msgid ""
"[RFC 4271: A Border Gateway Protocol 4 (BGP-4)](https://datatracker.ietf.org/"
"doc/html/rfc4271)"
msgstr ""

#: src\5-2-bgp.md:38 src\5-2-1-bgp-cli.md:95
#: src\5-2-2-route-update-in-frr.md:744 src\5-2-3-route-update-in-sonic.md:743
msgid "[FRRouting](https://frrouting.org/)"
msgstr ""

#: src\5-2-1-bgp-cli.md:3
msgid "`show` Command"
msgstr ""

#: src\5-2-1-bgp-cli.md:5
msgid ""
"Since BGP is implemented using FRR, naturally, the `show` command will "
"forward the direct request to FRR's `vtysh`. The key code is as follows:"
msgstr ""

#: src\5-2-1-bgp-cli.md:8
msgid "# file: src/sonic-utilities/show/bgp_frr_v4.py"
msgstr ""

#: src\5-2-1-bgp-cli.md:8
msgid "# 'summary' subcommand (\"show ip bgp summary\")"
msgstr ""

#: src\5-2-1-bgp-cli.md:16
msgid "# file: src/sonic-utilities/utilities_common/bgp_util.py"
msgstr ""

#: src\5-2-1-bgp-cli.md:19
msgid "# The IPv6 case is omitted here for simplicity"
msgstr ""

#: src\5-2-1-bgp-cli.md:20
msgid "\"show ip bgp summary json\""
msgstr ""

#: src\5-2-1-bgp-cli.md:26
msgid "'sudo'"
msgstr ""

#: src\5-2-1-bgp-cli.md:26
msgid "'-c'"
msgstr ""

#: src\5-2-1-bgp-cli.md:30
msgid "We can also verify by running `vtysh` directly:"
msgstr ""

#: src\5-2-1-bgp-cli.md:59
msgid "`config` Command"
msgstr ""

#: src\5-2-1-bgp-cli.md:61
msgid ""
"Meanwhile, the `config` command directly operates on `CONFIG_DB` to achieve "
"configuration changes."
msgstr ""

#: src\5-2-1-bgp-cli.md:63
msgid "Take remove neighbor as an example. The key code is shown as follows:"
msgstr ""

#: src\5-2-1-bgp-cli.md:66
msgid "# file: src/sonic-utilities/config/main.py"
msgstr ""

#: src\5-2-1-bgp-cli.md:70
msgid "\"Remove BGP neighbor configuration from the device\""
msgstr ""

#: src\5-2-1-bgp-cli.md:73
msgid "'neighbor'"
msgstr ""

#: src\5-2-1-bgp-cli.md:74
msgid "'neighbor_ip_or_hostname'"
msgstr ""

#: src\5-2-1-bgp-cli.md:74
msgid "'<neighbor_ip_or_hostname>'"
msgstr ""

#: src\5-2-1-bgp-cli.md:76
msgid ""
"\"\"\"Removes BGP neighbor configuration (internal or external) from the "
"device\"\"\""
msgstr ""

#: src\5-2-1-bgp-cli.md:93 src\5-2-2-route-update-in-frr.md:741
#: src\5-2-3-route-update-in-sonic.md:740
msgid ""
"[Github repo: sonic-utilities](https://github.com/sonic-net/sonic-utilities)"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:3
msgid ""
"Route update is almost the most important workflow in SONiC. The entire "
"process starts from the `bgpd` process and eventually reaches the ASIC chip "
"through SAI. Many processes are involved in between, and the workflow is "
"quite complex. However, once we understand it, we can understand the design "
"of SONiC and many other configuration workflows much better. Therefore, in "
"this section, we will deeply dive into its overall process."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:5
msgid ""
"To help us understand the workflow on the code level, we divide this "
"workflow into two major parts: how FRR handles route changes in this "
"chapter, and how the SONiC updates the routes and integrates with FRR in the "
"next chapter."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:7
msgid "FRR Handling Route Changes"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:38
msgid ""
"```admonish note\n"
"Regarding the implementation of FRR, this section focuses more on explaining "
"its workflow from the code perspective rather than the details of its BGP "
"implementation. If you want to learn about the details of FRR's BGP "
"implementation, you can refer to the [official documentation](https://docs."
"frrouting.org/en/latest/bgp.html).\n"
"```"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:42
msgid "`bgpd` Handling Route Changes"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:44
msgid ""
"`bgpd` is the process in FRR specifically used to handle BGP sessions. It "
"opens TCP port 179 to establish BGP connections with neighbors and handles "
"routing table update requests. When a route changes, FRR also uses this "
"session to notify other neighbors."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:46
msgid ""
"When a request arrives at `bgpd`, it will land on the io thread first: "
"`bgp_io`. As the name suggests, this thread is responsible for network read "
"and write operations in `bgpd`:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:49
msgid "// File: src/sonic-frr/frr/bgpd/bgp_io.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:55
msgid "// Read packets here"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:58
msgid ""
"// If we have more than 1 complete packet, mark it and process it later."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:73
msgid ""
"After the packet is read, `bgpd` sends it to the main thread for processing. "
"Here, `bgpd` dispatches the packet based on its type. And the route update "
"requests will be handed over to `bpg_update_receive` for processing:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:76
msgid "// File: src/sonic-frr/frr/bgpd/bgp_packet.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:86
msgid "/* read in the packet length and type */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:102
msgid "// Process BGP UPDATE message for peer."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:111
msgid "// Parse attributes and NLRI"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:122
msgid "// More parsing here"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:128
msgid "/* End-of-RIB received */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:133
msgid "/* Best path selection */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:147
msgid ""
"Then, `bgpd` starts checking for better paths and updates its local routing "
"table (RIB, Routing Information Base):"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:150
msgid "// File: src/sonic-frr/frr/bgpd/bgp_route.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:150
msgid "/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:159
msgid "/* Process the route list */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:183
msgid "/* Best path selection. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:189
msgid "/* FIB update. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:204
msgid "/* Withdraw the route from the kernel. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:209
msgid "/* EVPN route injection and clean up */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:217
msgid ""
"Finally, `bgp_zebra_announce` notifies `zebra` to update the kernel routing "
"table through `zclient`."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:220 src\5-2-2-route-update-in-frr.md:231
msgid "// File: src/sonic-frr/frr/bgpd/bgp_zebra.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:228
msgid ""
"`zclient` communicates with `zebra` using a local socket and provides a "
"series of callback functions to receive notifications from `zebra`. The key "
"code is shown as follows:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:236
msgid "/* Set default values. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:255
msgid "/* Connect to zebra. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:264
msgid ""
"In the `bgpd` container, we can find the socket file used for `zebra` "
"communication in the `/run/frr` directory for simple verification:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:273
msgid "`zebra` Updating Routing Table"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:275
msgid ""
"Since FRR supports many routing protocols, if each routing protocol updates "
"kernel independently, conflicts will inevitably arise, because it is "
"difficult to coordinate. Therefore, FRR uses a separate process to "
"communicate with all routing protocol handling processes, merges the "
"information, and then update the kernel routing table. This process is "
"`zebra`."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:277
msgid ""
"In `zebra`, kernel updates occur in a separate data plane handling thread: "
"`dplane_thread`. All requests are sent to `zebra` through `zclient`, then "
"get processed, and finally get forwarded to `dplane_thread` for handling. In "
"whis way, the route update will always be in order, which avoids any "
"conflicts to happen."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:279
msgid ""
"When `zebra` starts, it registers all request handlers. When a request "
"arrives, the corresponding handler will be called based on the request type. "
"And here is the key code:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:282 src\5-2-2-route-update-in-frr.md:298
msgid "// File: src/sonic-frr/frr/zebra/zapi_msg.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:295
msgid ""
"Take adding a route (`zread_route_add`) as an example to explain the later "
"workflow. From the following code, we can see that when a new route arrives, "
"`zebra` will start checking and updating its internal routing table:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:307
msgid "// Decode zclient request"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:314
msgid "// Allocate new route entry."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:320
msgid "// Init nexthop entry, if we have an id, then add route."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:328
msgid "// Update stats. IPv6 is omitted here for simplicity."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:332
msgid "// File: src/sonic-frr/frr/zebra/zebra_rib.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:344
msgid "/* Find table and nexthop entry */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:349
msgid "/* Attach the re to the nhe's nexthop group. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:352
msgid "/* Make it sure prefixlen is applied to the prefix. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:353
msgid "/* Set default distance by route type. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:356
msgid "/* Lookup route node.*/"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:360
msgid ""
"/* If this route is kernel/connected route, notify the dataplane to update "
"kernel route table. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:365
msgid "/* Link new re to node. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:369
msgid "/* Clean up */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:375
msgid ""
"Here, `rib_addnode` will forward this route add request to the rib "
"processing thread, where the requests are being processed sequentially:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:395
msgid ""
"Then, the request arrives at the RIB processing thread: `rib_process`, which "
"further selects the best route and adds it to `zebra`'s internal routing "
"table (RIB):"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:398
msgid "/* Core function for processing routing information base. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:415
msgid "/* Check every route entry and select the best route. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:433
msgid "/* RNODE_FOREACH_RE */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:436
msgid "/* Update fib according to selection results */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:444
msgid "/* Remove all RE entries queued for removal */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:445
msgid "/* Check if the dest can be deleted now.  */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:450
msgid ""
"For new routes, `rib_process_add_fib` is called to add them to `zebra`'s "
"internal routing table and notify the dplane to update the kernel routing "
"table:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:455
msgid "\"new route selected\""
msgstr ""

#: src\5-2-2-route-update-in-frr.md:458
msgid "/* If labeled-unicast route, install transit LSP. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:474
msgid "/* Install the resolved nexthop object first. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:477
msgid ""
"/* If this is a replace to a new RE let the originator of the RE know that "
"they've lost */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:481
msgid "/* Update fib selection */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:484
msgid ""
"/* Make sure we update the FPM any time we send new information to the "
"kernel. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:485
msgid "\"installing in kernel\""
msgstr ""

#: src\5-2-2-route-update-in-frr.md:487
msgid "/* Send add or update */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:494
msgid ""
"There are two important operations here: one is to call the `dplane_route_*` "
"functions to update the kernel routing table, and the other is the "
"`hook_call` that appears twice here. The FPM hook function is hooked here to "
"receive and forward routing table update notifications."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:496
msgid "Here, let's look at them one by one:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:498
msgid "`dplane` Updating Kernel Routing Table"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:500
msgid ""
"Let's look at the dplane `dplane_route_*` functions first. They are "
"essentially do the same thing: simply pack the request and put it into the "
"`dplane_thread` message queue:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:503 src\5-2-2-route-update-in-frr.md:541
msgid "// File: src/sonic-frr/frr/zebra/zebra_dplane.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:522
msgid "/* Create and init context */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:525
msgid "/* Enqueue context for processing */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:528
msgid "/* Update counter */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:538
msgid ""
"Then, on the data plane handling thread `dplane_thread`, in its message "
"loop, it take messages from the queue one by one and call their handling "
"functions:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:549
msgid "/* Process work here */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:552
msgid "/* Check for zebra shutdown */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:553
msgid "/* Dequeue completed work from the provider */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:556
msgid "/* Locate next provider */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:564
msgid ""
"By default, `dplane_thread` uses `kernel_dplane_process_func` to process the "
"messages. Inside this function, different kernel operations will be invoked "
"based on the request type:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:578
msgid ""
"/* A previous provider plugin may have asked to skip the kernel update.  */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:584
msgid "/* Dispatch to appropriate kernel-facing apis */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:602
msgid "/* Call into the synchronous kernel-facing code here */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:608
msgid ""
"And `kernel_route_update` is the real kernel operation. It notifies the "
"kernel of route updates through netlink:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:611
msgid "// File: src/sonic-frr/frr/zebra/rt_netlink.c"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:611
msgid ""
"// Update or delete a prefix from the kernel, using info from a dataplane "
"context."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:633
msgid ""
"// Routing table change via netlink interface, using a dataplane context "
"object"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:637
msgid "// Build netlink request."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:648
msgid "/* Talk to netlink socket. */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:653
msgid "FPM Route Update Forwarding"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:655
msgid ""
"FPM (Forwarding Plane Manager) is the protocol in FRR used to notify other "
"processes of route changes. Its main logic code is in `src/sonic-frr/frr/"
"zebra/zebra_fpm.c`. It supports two protocols by default: `protobuf` and "
"`netlink`. The one used in SONiC is the `netlink` protocol."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:657
msgid ""
"As mentioned earlier, it is implemented through hook functions. By listening "
"for route changes in the RIB, the updates are forwarded to other processes "
"through a local socket. This hook is registered at startup. And the most "
"relevant one to us is the `rib_update` hook, as shown below:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:669
msgid "\"zebra_fpm\""
msgstr ""

#: src\5-2-2-route-update-in-frr.md:670
msgid "\"zebra FPM (Forwarding Plane Manager) module\""
msgstr ""

#: src\5-2-2-route-update-in-frr.md:675
msgid ""
"When the `rib_update` hook is called, the `zfpm_trigger_update` function "
"will be called, which puts the route update info into the fpm forwarding "
"queue and triggers a write operation:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:683
msgid "// Queue the update request"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:698
msgid ""
"The write callback takes the update from the queue, converts it into the FPM "
"message format, and forwards it to other processes through a local socket:"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:709
msgid "// Convert route info to buffer here."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:712
msgid ""
"// Write to socket until we don' have anything to write or cannot write "
"anymore (partial write)."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:726
msgid ""
"/* Stop processing the queues if zfpm_g->obuf is full or we do not have more "
"updates to process */"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:733
msgid "At this point, FRR's work is done."
msgstr ""

#: src\5-2-2-route-update-in-frr.md:745 src\5-2-3-route-update-in-sonic.md:744
msgid "[FRRouting - BGP](https://datatracker.ietf.org/doc/html/rfc4271)"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:746 src\5-2-3-route-update-in-sonic.md:745
msgid ""
"[FRRouting - FPM](https://docs.frrouting.org/projects/dev-guide/en/latest/"
"fpm.html)"
msgstr ""

#: src\5-2-2-route-update-in-frr.md:747 src\5-2-3-route-update-in-sonic.md:746
msgid ""
"[Understanding EVPN Pure Type 5 Routes](https://www.juniper.net/"
"documentation/us/en/software/junos/evpn-vxlan/topics/concept/evpn-route-"
"type5-understanding.html)"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:3
msgid ""
"After the work of FRR is done, the route update information is forwarded to "
"SONiC, either via Netlink or FPM. This causes a series of operations in "
"SONiC, and eventually updates the route table in the ASIC."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:5
msgid "The main workflow is shown as below:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:40
msgid "`fpmsyncd` Updating Route Configuration in Redis"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:42
msgid ""
"First, let's start from the source. When `fpmsyncd` launches, it starts "
"listening for FPM and Netlink events to receive route change messages and "
"forward to `RouteSync` for processing:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:45
msgid "// File: src/sonic-swss/fpmsyncd/fpmsyncd.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:54
msgid "// Register netlink message handler"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:68
msgid "// Launching FPM server and wait for zebra to connect."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:75
msgid ""
"// If connection is closed, keep retrying until it succeeds, before handling "
"any other events."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:76
msgid "\"Connection lost, reconnecting...\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:83
msgid ""
"In `FpmLink`, the FPM events will be converted into Netlink messages. This "
"unifies the message that being sent to `RouteSync` to Netlink. And "
"`RouteSync::onMsg` will be called for processing them (for how Netlink "
"receives and processes messages, please refer to [4.1.2 Netlink](./4-1-2-"
"netlink.html)):"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:85
msgid ""
"One small thing to notice is that - EVPN Type 5 messages must be processed "
"in raw message form, so `RouteSync::onMsgRaw` will be called."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:88
msgid "// File: src/sonic-swss/fpmsyncd/fpmlink.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:88
msgid "// Called from: FpmLink::readData()"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:96
msgid "/* Read all netlink messages inside FPM message */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:99
#: src\5-2-3-route-update-in-sonic.md:341
msgid "/*"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:112
msgid "/* EVPN Type5 Add route processing */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:113
msgid "/* This will call into onRawMsg() */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:116
msgid "/* This will call into onMsg() */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:130
msgid ""
"Next, when `RouteSync` receives a route change message, it makes judgments "
"and dispatches in `onMsg` and `onMsgRaw`:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:133
#: src\5-2-3-route-update-in-sonic.md:188
msgid "// File: src/sonic-swss/fpmsyncd/routesync.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:144
msgid "// Refill Netlink cache here"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:158
msgid ""
"/* If the master device name starts with VNET_PREFIX, it is a VNET route."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:165
msgid "/* Otherwise, it is a regular route (include VRF route). */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:175
msgid ""
"From the code above, we can see that there are four different route "
"processing entry points. These different routes will be finally written to "
"different tables in `APPL_DB` through their respective [ProducerStateTable]"
"(./4-2-5-producer-consumer-state-table.md):"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:177
msgid "Route Type"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:177
msgid "Entry Point"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:177
msgid "Table"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:179
msgid "MPLS"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:179
msgid "`onLabelRouteMsg`"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:179
msgid "LABLE_ROUTE_TABLE"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:180
msgid "Vnet VxLan Tunnel Route"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:180
#: src\5-2-3-route-update-in-sonic.md:181
msgid "`onVnetRouteMsg`"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:180
msgid "VNET_ROUTE_TUNNEL_TABLE"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:181
msgid "Other Vnet Routes"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:181
msgid "VNET_ROUTE_TABLE"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:182
msgid "EVPN Type 5"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:182
msgid "`onEvpnRouteMsg`"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:182
#: src\5-2-3-route-update-in-sonic.md:183
msgid "ROUTE_TABLE"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:183
msgid "Regular Routes"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:183
msgid "`onRouteMsg`"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:185
msgid ""
"Here we take regular routes as an example. The implementation of other "
"functions is different, but the basic idea is the same:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:191
msgid "// Parse route info from nl_object here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:194
msgid "// Get nexthop lists"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:201
msgid ""
"// Build route info here, including protocol, interface, next hops, MPLS, "
"weights etc."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:203
msgid "\"protocol\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:204
msgid "\"nexthop\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:211
msgid "// Push to ROUTE_TABLE via ProducerStateTable."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:213
msgid "\"RouteTable set msg: %s %s %s %s\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:218
msgid "`orchagent` Processing Route Configuration Changes"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:220
msgid ""
"Next, these route information will come to `orchagent`. When `orchagent` "
"starts, it creates `VNetRouteOrch` and `RouteOrch` objects, which are used "
"to listen and process Vnet-related routes and EVPN/regular routes "
"respectively:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:223
#: src\5-2-3-route-update-in-sonic.md:439
msgid "// File: src/sonic-swss/orchagent/orchdaemon.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:242
msgid ""
"The entry function that process the incoming messages for all Orch objects "
"is `doTask`. `RouteOrch` and `VNetRouteOrch` are the same. Here we take "
"`RouteOrch` as an example to see how it handles route changes."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:248
msgid ""
"Before we dive into the code, we have a few things to note for `RouteOrch`:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:250
msgid ""
"From the above `init` function, we can see that `RouteOrch` not only manages "
"regular routes but also manages MPLS routes. The logic for handling these "
"two types of routes is different. Therefore, in the following code, to "
"simplify, we only show the logic for handling the regular routes."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:251
msgid ""
"Since `ProducerStateTable` transmits and receives messages in batches, "
"`RouteOrch` also processes the route updates in batches. To support batch "
"processing, `RouteOrch` uses `EntityBulker<sai_route_api_t> gRouteBulker` to "
"cache the SAI route objects that need to be changed, and then applies these "
"route object changes to SAI at the end of the `doTask()` function."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:252
msgid ""
"Route operations require a lot of other information, such as the status of "
"each port, the status of each neighbor, the status of each VRF, etc. To "
"obtain this information, `RouteOrch` interacts with other Orch objects, such "
"as `PortOrch`, `NeighOrch`, `VRFOrch`, etc."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:254
msgid ""
"Let's start with the `RouteOrch::doTask` function. It parses the incoming "
"route operation messages, then calls the `addRoute` or `removeRoute` "
"function to create or delete routes."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:257
#: src\5-2-3-route-update-in-sonic.md:381
msgid "// File: src/sonic-swss/orchagent/routeorch.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:260
msgid ""
"// Calling PortOrch to make sure all ports are ready before processing route "
"messages."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:263
msgid ""
"// Call doLabelTask() instead, if the incoming messages are from MPLS "
"messages. Otherwise, move on as regular routes."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:266
msgid "/* Default handling is for ROUTE_TABLE (regular routes) */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:269
msgid "// Add or remove routes with a route bulker"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:274
msgid "// Parse route operation from the incoming message here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:279
msgid "// resync application:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:280
msgid ""
"// - When routeorch receives 'resync' message (key = \"resync\", op = \"SET"
"\"), it marks all current routes as dirty"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:281
msgid ""
"//   and waits for 'resync complete' message. For all newly received routes, "
"if they match current dirty routes,"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:282
msgid "//   it unmarks them dirty."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:283
msgid ""
"// - After receiving 'resync complete' (key = \"resync\", op != \"SET\") "
"message, it creates all newly added routes"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:284
msgid "//   and removes all dirty routes."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:287
msgid "// Parsing VRF and IP prefix from the incoming message here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:290
msgid "// Process regular route operations."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:293
msgid "// Parse and validate route attributes from the incoming message here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:298
msgid ""
"// If the nexthop_group is empty, create the next hop group key based on the "
"IPs and aliases."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:299
msgid ""
"// Otherwise, get the key from the NhgOrch. The result will be stored in the "
"\"nhg\" variable below."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:304
msgid ""
"// Here the nexthop_group is empty, so we create the next hop group key "
"based on the IPs and aliases."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:323
msgid "// Here we have a nexthop_group, so we get the key from the NhgOrch."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:330
msgid "// Now we start to create the SAI route entry."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:333
msgid ""
"// Skip certain routes, such as not valid, directly routes to tun0, "
"linklocal or multicast routes, etc."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:336
msgid "// Create SAI route entry in addRoute function."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:357
msgid "// Handle other ops, like DEL_COMMAND for route deletion, etc."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:361
msgid "// Flush the route bulker, so routes will be written to syncd and ASIC"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:364
msgid "// Go through the bulker results."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:365
msgid ""
"// Handle SAI failures, update neighbors, counters, send notifications in "
"add/removeRoutePost functions."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:368
msgid "/* Remove next hop group if the reference count decreases to zero */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:374
msgid ""
"Here we take `addRoute` as an example. It mainly does a few things below:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:376
msgid ""
"Get next hop information from `NeighOrch` and check if the next hop is "
"really available."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:377
msgid ""
"If the route is a new or re-added back while waiting to be deleted, a new "
"SAI route object will be created."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:378
msgid "If it is an existing route, the existing SAI route object is updated."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:384
msgid "// Get nexthop information from NeighOrch."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:385
msgid ""
"// We also need to check PortOrch for inband port, IntfsOrch to ensure the "
"related interface is created and etc."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:388
msgid "// Start to sync the SAI route entry."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:397
msgid "// Create a new route entry in this case."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:398
msgid "//"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:399
msgid ""
"// In case the entry is already pending removal in the bulk, it would be "
"removed from m_syncdRoutes during the bulk call."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:400
msgid ""
"// Therefore, such entries need to be re-created rather than set attribute."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:410
msgid "/* Default SAI_ROUTE_ATTR_PACKET_ACTION is SAI_PACKET_ACTION_FORWARD */"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:418
msgid "// Update existing route entry in this case."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:420
msgid ""
"// Set the packet action to forward when there was no next hop (dropped) and "
"not pointing to blackhole."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:429
msgid ""
"// Only 1 case is listed here as an example. Other cases are handled with "
"similar logic by calling set_entry_attributes as well."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:436
msgid ""
"After creating and setting up all the routes, `RouteOrch` calls "
"`gRouteBulker.flush()` to write all the routes to `ASIC_DB`. The `flush()` "
"function is straightforward: it processes all requests in batches, with each "
"batch being 1000 by default, defined in `OrchDaemon` and passed through the "
"constructor:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:442
msgid "// File: src/sonic-swss/orchagent/bulker.h"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:454
msgid "// Bulk remove entries"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:456
#: src\5-2-3-route-update-in-sonic.md:492
msgid ""
"// Split into batches of max_bulk_size, then call flush. Similar to "
"creating_entries, so details are omitted."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:463
msgid "// Bulk create entries"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:465
msgid ""
"// Split into batches of max_bulk_size, then call flush_creating_entries to "
"call SAI batch create API to create"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:466
msgid "// the objects in batch."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:479
msgid "// Batch create here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:490
msgid "// Bulk update existing entries"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:509
msgid "// Call SAI bulk create API"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:515
msgid "// Set results back to input entries and clean up the batch below."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:528
msgid ""
"// flush_removing_entries and flush_setting_entries are similar to "
"flush_creating_entries, so we omit them here."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:533
msgid "SAI Object Forwarding in `orchagent`"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:535
msgid ""
"At this point, you might have noticed something strange - The `EntityBulker` "
"seems to be directly calling the SAI API. Shouldn't they be called in "
"`syncd`? If we follow the SAI API objects passed to `EntityBulker`, we will "
"even find that `sai_route_api_t` is indeed the SAI interface, and there is "
"SAI initialization code in `orchagent`, as follows:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:538
msgid ""
"// File: src/sonic-sairedis/debian/libsaivs-dev/usr/include/sai/sairoute.h"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:538
#: src\5-2-3-route-update-in-sonic.md:700
msgid "/**"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:554
msgid "// File: src/sonic-swss/orchagent/saihelper.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:562
msgid "\"Context config file %s exists\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:585
msgid ""
"I believe whoever saw this code for the first time will definitely feel "
"confused. But don't worry, this is actually the SAI object forwarding "
"mechanism in `orchagent`."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:587
msgid ""
"If you are familiar with RPC, the `proxy-stub` pattern might sounds very "
"familar to you - using a unified way to define the interfaces called by both "
"parties in communication, implementing message serialization and sending on "
"the client side, and implementing message receiving, deserialization, and "
"dispatching on the server side. Here, SONiC does something similar: using "
"the SAI API itself as a unified interface, implementing message "
"serialization and sending for `orchagent` to call, and implementing message "
"receiving, deserialization, and dispatch functions in `syncd`."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:589
msgid ""
"Here, the sending end is called `ClientSai`, implemented in `src/sonic-"
"sairedis/lib/ClientSai.*`. Serialization and deserialization are implemented "
"in SAI metadata: `src/sonic-sairedis/meta/sai_serialize.h`:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:592
msgid "// File: src/sonic-sairedis/lib/ClientSai.h"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:601
msgid "// File: src/sonic-sairedis/meta/sai_serialize.h"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:602
msgid "// Serialize"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:606
msgid "// Deserialize"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:612
msgid ""
"When `orchagent` is compiled, it links to `libsairedis`, which implements "
"the SAI client and handles the serialization and message sending:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:615
msgid "# File: src/sonic-swss/orchagent/Makefile.am"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:616
msgid ""
"$(LDFLAGS_ASAN) -lnl-3 -lnl-route-3 -lpthread -lsairedis -lsaimeta -"
"lsaimetadata -lswsscommon -lzmq"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:619
msgid ""
"Here, we use Bulk Create as an example to see how `ClientSai` serializes and "
"sends the SAI API call:"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:622
#: src\5-2-3-route-update-in-sonic.md:709
msgid "// File: src/sonic-sairedis/lib/ClientSai.cpp"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:638
msgid ""
"// Server is responsible for generate new OID but for that we need switch ID"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:639
msgid ""
"// to be sent to server as well, so instead of sending empty oids we will"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:640
msgid "// send switch IDs"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:646
msgid ""
"// Since user requested create, OID value was created remotely and it was "
"returned in m_lastCreateOids"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:668
msgid "// Calling SAI serialize APIs to serialize all objects"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:674
msgid "\"NULL\""
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:684
msgid "// Send to syncd via the communication channel."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:687
msgid "// Wait for response from syncd."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:692
msgid ""
"Finally, `ClientSai` calls `m_communicationChannel->set()` to send the "
"serialized SAI objects to `syncd`. This channel, before the 202106 version, "
"was the [ProducerTable based on Redis](https://github.com/sonic-net/sonic-"
"sairedis/blob/202106/lib/inc/RedisChannel.h). Possibly for efficiency "
"reasons, starting from the 202111 version, this channel has been changed to "
"[ZMQ](https://github.com/sonic-net/sonic-sairedis/blob/202111/lib/"
"ZeroMQChannel.h)."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:695
msgid ""
"// File: https://github.com/sonic-net/sonic-sairedis/blob/202106/lib/inc/"
"RedisChannel.h"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:728
msgid ""
"For the inter-process communication, we are going to skip the details here. "
"Please feel free to refer to the [Redis-based channels](./4-2-redis-based-"
"channels.md) described in Chapter 4."
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:730
msgid "`syncd` Updating ASIC"
msgstr ""

#: src\5-2-3-route-update-in-sonic.md:732
msgid ""
"Finally, when the SAI objects are generated and sent to `syncd`, `syncd` "
"will receive, processa and updates `ASIC_DB`, then finally updates the ASIC. "
"We have already described this workflow in detail in the [Syncd-SAI Workflow]"
"(./5-1-syncd-and-sai.md), so we will skip them here. For more details, "
"please refer to the [Syncd-SAI Workflow chapter](./5-1-syncd-and-sai.md)."
msgstr ""

#: src\6-boot.md:1
msgid "Boot"
msgstr ""

#: src\6-1-cold-boot.md:1
msgid "Cold Boot"
msgstr ""

#: src\6-2-fast-boot.md:1
msgid "Fast Boot"
msgstr ""

#: src\6-3-warm-boot.md:1
msgid "Warm Boot"
msgstr ""
