以最简单的loopback插件作为实例,来分析CNI plugin的执行流程

// cni/plugins/loopback/loopback.go

1、func main()

main函数只是简单地调用skel.PluginMain(cmdAdd, cmdDel, version.All),注册插件中的插入和删除方法

// cni/pkg/skel/skel.go

// PluginMain is the core "main" for a plugin which includes automatic error handling.

// The caller must also specify what CNI spec versions the plugin supports.

// When an error occurs in either cmdAdd or cmdDel, PluginMain will print the error

// as JSON to stdout and call os.Exit(1).

// To have more control over error handling, use PluginMainWithErro() instead.

2、func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo)

该函数仅仅调用e := PluginMainWithError(cmdAdd, cmdDel, versionInfo)

若e不为nil,调用e.Print()并os.Exit()

// cni/pkg/skel/skel.go

3、func PluginMainWithError(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) *types.Error

该函数仅仅调用return (&dispatcher{

    Getenv:  os.Getenv,

    Stdin:   os.Stdin,

    Stdout:   os.Stdout,

    Stderr:   os.Stderr,

}).pluginMain(cmdAdd, cmdDel, versionInfo)

dispatcher 结构如下所示:

type dispatcher struct {
  Getenv   func(string) string
  Stdin:   io.Reader
  Stdout:   io.Write
  Stderr:   io.Write   ConfVersionDecoder  version.ConfigDecoder
  VersionReconciler    version.Reconciler
}

// cni/pkg/skel/skel.go

4、func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) *types.Error

1、先调用cmd, cmdArgs, err := t.getCmdArgsFromEnv()解析出,操作指令(ADD ,DEL或者VERSION),和操作参数

2、再根据不同的cmd,调用相关的函数。对于"ADD",调用t.checkVersionAndCall(cmdArgs, versionInfo, cmdAdd)

// cni/pkg/skel/skel.go

5、func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error)

该函数从环境变量和stdin中提取信息,填充数据结构CmdArgs,如下所示:

cmdArgs := &CmdArgs{
  ContainerID:    contID,
  Netns:        netns,
  IfName:       ifName,
  Args:        args,
  Path:        path,
  StdinData:     stdinData,    // StdinData中的数据其实是network配置
}

  

// cni/pkg/skel/skel.go

6、func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo version.PluginInfo, toCall func(*CmdArgs) error) error

1、调用confiVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)获取网络配置中的版本

2、调用verErr := t.VersionReconciler.Check(configVersion, pluginVersionInfo)

3、最后调用return toCall(cmdArgs)

// cni/plugins/loopback/loopback.go

7、func cmdAdd(args *skel.CmdArgs) error

1、因为loopback比较特殊,因此直接忽略args,设置args.IfName = "lo"

2、调用ns.WithNetNSPath(args.Netns, do func(_ ns.NetNS) error),在args指定的net ns中执行函数do

3、loopback比较简单,net ns中的执行函数只是调用link, err := netlink.LinkByName(args.IfName)找到lo设备,再调用netlink.LinkSetUp(link)启动而已

4、调用result := current.Result{}并return result.Print()

综上完成CNI插件的执行流程

最新文章

  1. Eclipse调试时附加匹配版本的JAR包源码:Edit Source Loopup
  2. C#使用DataSet Datatable更新数据库的三种实现方法
  3. mysql创建外键出错(注意数据库表字段排序)
  4. .net 调用C++类库
  5. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器
  6. CocoaPods 安装和使用
  7. [Elasticsearch] 部分匹配 (一) - 前缀查询
  8. 疯狂java讲义--笔记
  9. ftok函数的使用
  10. Java.MyEclipse Web项目导入Eclipse
  11. python3之序列化(pickle&json&shelve)
  12. [Swift]LeetCode804. 唯一摩尔斯密码词 | Unique Morse Code Words
  13. 20175320 2018-2019-2 《Java程序设计》第6周学习总结
  14. YUV420序列转成图片
  15. 如何取得select结果数据集的前10条记录。postgresql
  16. html文件中jquery与velocity变量中的$冲突的解决方法
  17. Flask源码解析:Flask上下文
  18. 13 python 常用的内置方法介绍
  19. 使用sos查看.NET对象内存布局
  20. Django(出版社功能)

热门文章

  1. PHP7:10件事情你需要知道的
  2. 浏览器在线打开pdf
  3. FormatUtil类型格式转换
  4. root权限NPM全局安装(-g)仍会权限不够,认识下参数 --unsafe-perm
  5. redission计数器实现,redisTemplate计数器
  6. head管理EC下载,配置启动
  7. 64位系统下,一个32位的程序究竟可以申请到多少内存,4GB还是更多?(一)
  8. 【BZOJ】3314: [Usaco2013 Nov]Crowded Cows(单调队列)
  9. 《C++程序设计》朝花夕拾
  10. (转)Unity笔记之编辑器(BeginFadeGroup、BeginHorizontal、BeginScrollView) ... ...