Cnitool is used as follows: where <net> is the directory where the configuration file is located, generally/etc/cni/net.d/*.conf file,<netns> is the network namespace directory file, generally/var/ Run/netns/ns-id
Cnitool:add or remove network interfaces from a network namespace Cnitool Add <net> <netns> cnitool del <net> <netns>
1, Cni/cnitool/cni.go
Main function:
(1), first obtain the Netdir from the environment variable Netconfpath, if not exist then set the default value "/ETC/CNI/NET.D", then call netconf, err: = Libcni. Loadconf (Netdir, OS. ARGS[2]) to load the configuration variable, Netns is assigned to the OS. ARGS[3]
(2), call to get Cniconfig and runtimeconf
Cninet: = &libcni. cniconfig{path:strings. Split (OS. Getenv (Envcnipath), ":")}rt: = &libcni. runtimeconf{Containerid: "The MLM", Netns:netns, IfName: "eth0"}
(3), OS. ARGS[1] For Add, call _, Err: = Cninet. Addnetwork (netconf, RT) Add Network
The NETWORKCONFIG data structure is as follows:
Type networkconfig struct {Network *types.netconf Bytes []byte}
Type netconf struct {cniversion string Name string Type string IPAM struct {Type string} DNS DNS}
The data structure of the runtime is as follows:
Type runtimeconf struct {containerid string NetNS string IfName string Args [][2]string}
2, Cni/libcni/api.go
Addnetwork executes the plugin with ADD command
Func (c *cniconfig) addnetwork (NET *networkconfig, RT *runtimeconf) (*types. Result, error)
(1), first call Pluginpath, err: = Invoke. Findinpath (Net.Network.Type, C.path), this function is used in C. Search for Net.Network.Type in path and return to the full path
(2), call return Invoke. Execpluginwithresult (Pluginpath, net. Bytes, C.args ("ADD", RT)), net. Bytes is the serialized binary code of the configuration file, where the C.args function is the main function of filling and returning a *invoke. Args Type:
Return &invoke. Args {command:action, Containerid: Rt. Containerid, NetNS:rt.NetNS, Pluginargs: Rt. Args, Ifname:rt. IfName, Path:strings. Join (C.path, ":"),}
3, Cni/pkg/invoke/exec.go
Func Execpluginwithresult (Pluginpath string, netconf []byte, args Cniargs) (*types. Result, error)
The function simply returns return Defaultpluginexec.withresult (Pluginpath, netconf, args)
Where Defaultpluginexec is a *pluginexec type variable, the assignment process is as follows:
var defaultpluginexec = &pluginexec{rawexec: &rawexec{stderr:os. Stderr}, --->rawexec is also a struct type defined in Raw_exec.go, with only one Stderr io.writer type versiondecoder: &version. plugindecoder{},}//the definition of pluginexec is as follows: type pluginexec struct {rawexec interface {execplugin (Pluginpath string, s Tdindata []byte, Environ []string]} Versiondecoder Interface {Decode (jsonbytes []byte) (version. Plugininfo, Error)}}
4, Cni/pkg/invoke/exec.go
Func (e *pluginexec) Withresult (Pluginpath string, netconf []byte, args Cniargs) (*types. Result, error)
(1), call stdoutbytes, err: = E.rawexec.execplugin (Pluginpath, netconf, args. Asenv ()), args. Asenv () transforms the contents of args into an environment variable return, such as Cni_command=add, etc.
(2), res: = &types. result{}, and then call JSON. Unmarshal (stdoutbytes, res) resolves the result and returns
5, Cni/pkg/invoke/raw_exec.go
Func (e *rawexec) execplugin (Pluginpath string, stdindata []byte, Environ []string] ([]byte, error)
(1), first obtained stdout: = bytes. buffer{} as an output buffer
(2), create the Execute command and call C. Run ()
c: = Exec. CMD {env:environ, Path:pluginpath, Args: []string{pluginpath}, Stdin:bytes. Newbuffer (Stdindata), Stdout:stdout, Stderr:e.stderr,}
(3), and finally return to stdout. Bytes ()
-----------------------------------------------------------------------------------the implementation framework of plugin----------------- ------------------------------------------------------
Each plug-in's main function calls the Skel. Pluginmain (Cmdadd, Cmddel, version. Legacy), where the Skel package is a framework library, all newly added plug-ins are only called Skel. Pluginmain the Cmdadd and Cmddel method of the spread.
1, Cni/pkg/skel/skel.go
Pluginmain is the ' main ' for a plugin. It accepts callbacks functions for add and Del commands
Func Pluginmain (Cmdadd, Cmddel)
(1), first constructs a dispatcher type of caller:
Caller: = Dispatcher {Getenv:os. Getenv, Stdin:os. Stdin, Stdout: os. Stdout, Stderr: os. Stderrr,}
Then simply call err: = Caller.pluginmain (Cmdadd, Cmddel, Versioninfo)
2, Cni/pkg/skel/skel.go
Func (t *dispatcher) Pluginmain (Cmdadd, Cmddel func (_ *cmdargs) error, versioninfo version. Plugininfo) *types. Error
(1), first call cmd, Cmdargs, err: = T.getcmdargsfromenv (), the function from the environment variables passed to the process before parsing a lot of information such as Cni_command,cni_containerid, The fill gets Cmdargs as follows:
Cmdargs: = &cmdargs {containerid:contid, Netns:netns, Ifname:ifname, Args: A RGS, Path: path, Stdindata:stdindata,}
(2), according to CMD call the corresponding processing function for processing, for example, we parse the Add, call err = T.checkversionandcall (Cmdargs, Versioninfo, Cmdadd)
3, Cni/pkg/skel/skel.go
Func (t *dispatcher) Checkversionandcall (Cmdargs *cmdargs, pluginversioninfo version. Plugininfo, Tocall func (*cmdargs) error)
(1), first call configversion, err: = T.confversiondecoder.decode (Cmdargs.stdindata) and Vererr: = T.versionreconciler.check ( ConfigVersion, Pluginversioninfo) checks for version
(2), finally call the return Tocall (Cmdargs) function, enter the specific plug-in execution network add or delete operation
------------------------------------------------------------------------------------when type is Bridge-------------- ----------------------------------------------------------
1, Cni/plugins/main/bridge/bridge.go
Add Network process analysis to the MLM