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