Command line call

The easiest way to communicate with the kernel in SONiC is to make a command line call, which is placed under the common/exec.h file and is very simple to implement The interface is as follows:

// File: common/exec.h
// Namespace: swss
int exec(const std::string &cmd, std::string &stdout);

Where cmd is the command to be executed and stdout is the output of the command execution. The exec function here is a synchronous call, and the caller blocks until the command is executed. Internally, it creates a child process by calling the popen function and gets the output by using the fgets function. However, although this function returns output, basically no one uses it, but only by the return value to determine whether it succeeded or not, and even the output is not written in the error log.

This function is crude but widely used, especially in the various *mgrd services, such as portmgrd where it is used to set the status of each port, etc.

// File: sonic-swss - cfgmgr/portmgr.cpp
bool PortMgr::setPortAdminStatus(const string &alias, const bool up)
{
    stringstream cmd;
    string res, cmd_str;

    // ip link set dev <port_name> [up|down]
    cmd << IP_CMD << " link set dev " << shellquote(alias) << (up ? " up" : " down");
    cmd_str = cmd.str();
    int ret = swss::exec(cmd_str, res);

    // ...

Note

为什么说命令行调用是一种通信机制呢

原因是当*mgrd服务调用exec函数对系统进行的修改,会触发下面马上会提到的netlink事件,从而通知其他服务进行相应的修改,比如*syncd,这样就间接的构成了一种通信。所以这里我们把命令行调用看作一种通信机制能帮助我们以后更好的理解SONiC的各种工作流。

参考资料

  1. Github repo: sonic-swss-common