cnitool: Add or remove network interfaces from a network namespace

  cnitool  add  <net>  <netns>
  cnitool  del  <net>  <netns>

cnitool的使用方式如下:其中<net>是配置文件所在目录,一般为/etc/cni/net.d/*.conf文件,<netns>为network namespace的目录文件,一般为/var/run/netns/NS-ID

1、cni/libcni/api.go

// AddNetwork executes the plugin with ADD command

func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)

(1)、首先调用pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path),该函数用于在c.Path中寻找对应插件的可执行文件,然后返回路径

(2)、调用 return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt)),net.Bytes是配置文件的序列化二进制码,其中c.args函数主要的作用是填充并返回一个*invoke.Args类型:

return &invoke.Args {
  Command:       action,
  ContainerID:    rt.ContainerID,
  NetNS:         rt.NetNS,
  PluginArgs:     rt.Args,
  IfName:        rt.IfName,
  Path:         strings.Join(c.Path, string(os.PathListSeparator)),
}

  

NetworkConfig的数据结构如下所示,用于表示容器要加入的网络:

// libcni/api.go
type NetworkConfig struct {
  Network   *types.NetConf
  Bytes    []byte // 在初始化CNI的时候,会将配置文件写入Bytes
} // pkg/types/types.go
// NetConf describes a network
type NetConf struct {
  CNIVersion   string
  Name       string
  IPAM  string {
    Type  string
  }
  DNS DNS
}

  

Runtime的数据结构如下所示,用于表示加入网络的容器的信息:

type RuntimeConf struct {
  ContainerID   string
  NetNS       string
  IfName      string
  Args       [][2]string
}

CNIConfig的数据结构如下所示:CNIconfig包含的是bridge,dhcp等插件的可执行文件的目录的路径集合

type CNIConfig struct {
  Path    []string
}

  

2、cni/pkg/invoke/exec.go

func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error)

该函数只是简单地返回 return defaultPluginExec.WithResult(pluginPath, netconf, args)

其中defaultPluginExec是一个*PluginExec的类型变量,赋值过程如下所示:

var defaultPluginExec = &PluginExec{
  RawExec:      &RawExec{Stderr: os.Stderr}, --->RawExec又是在raw_exec.go中定义的一个结构类型,其中只有一个Stderr的io.Writer类型
  VersionDecoder:   &version.PluginDecoder{},
} // 其中PluginExec的定义如下所示:
type PluginExec struct {
  RawExec interface {
    ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)
  }
  VersionDecoder interface {
    Decode(jsonBytes []byte) (version.PluginInfo, error)
  }
}

  

3、cni/pkg/invoke/exec.go

func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error)

(1)、调用stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv()),args.AsEnv()将args里的内容转变为环境变量返回,例如CNI_COMMAND=ADD等等

// Plugin must return result in same version as specified in netconf

(2)、调用versionDecoder := &version.ConfigDecoder{}和confVersion, err := versionDecoder.Decode(netconf)从netconf中解析处CNI的版本

(3)、最后调用return version.NewResult(confVersion, stdoutBytes)返回相应版本的Result

4、cni/pkg/invoke/args.go

func (args *Args) AsEnv() []string

1、调用env := os.Environ()获取已有的环境变量

2、若args.PluginArgsStr为"",则将args.PluginArgs拼接为“A=B;C=D”的形式

3、调用env = append(env,

  "CNI_COMMAND=" + args.Command,

  "CNI_CONTAINERID=" + args.ContainerID,

  "CNI_NETNS=" + args.NetNS,

  "CNI_ARGS=" + pluginArgsStr,

  "CNI_IFNAME=" + args.IfName,

  "CNI_PATH="+args.Path)

),将参数都作为环境变量传递给plugin

RawExec的结构如下所示:

type RawExec struct {
  Stderr  io.Writer
}

5、cni/pkg/invoke/raw_exec.go

func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)

(1)、首先获得stdout := bytes.Buffer{}作为输出缓冲器

(2)、创建执行命令并调用c.Run()运行

c := exec.Cmd {
  Env:      environ,
  Path:     pluginPath,
  Args:     []string{pluginPath},
  Stdin:     bytes.NewBuffer(stdinData),
  Stdout:    stdout,
  Stderr:    e.Stderr,
}

(3)、最后返回stdout.Bytes(),插件直接将结果输出到stdout

cni 添加网络 流程分析的更多相关文章

  1. android添加账户流程分析涉及漏洞修复

    android修复了添加账户代码中的2处bug,retme取了很酷炫的名字launchAnyWhere.broadAnywhere(参考资料1.2).本文顺着前辈的思路学习bug的原理和利用思路. 我 ...

  2. PPTP协议握手流程分析

    一  PPTP概述 PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网,可 ...

  3. Netty 拆包粘包和服务启动流程分析

    Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...

  4. 【转】Netty 拆包粘包和服务启动流程分析

    原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...

  5. PPTP协议握手流程分析--转载

    一  PPTP概述   PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网 ...

  6. CNI插件编写框架分析

    概述 在<CNI, From A Developer's Perspective>一文中,我们已经对CNI有了较为深入的了解.我们知道,容器网络功能的实现最终是通过CNI插件来完成的.每个 ...

  7. elasticsearch indices.recovery 流程分析(索引的_open操作也会触发recovery)——主分片recovery主要是从translog里恢复之前未写完的index,副分片recovery主要是从主分片copy segment和translog来进行恢复

    摘自:https://www.easyice.cn/archives/231 elasticsearch indices.recovery 流程分析与速度优化 目录 [隐藏] 主分片恢复流程 副本分片 ...

  8. VLC架构及流程分析

    0x00 前置信息 VLC是一个非常庞大的工程,我从它的架构及流程入手进行分析,涉及到一些很细的概念先搁置一边,日后详细分析. 0x01 源码结构(Android Java相关的暂未分析) # bui ...

  9. Okhttp源码分析--基本使用流程分析

    Okhttp源码分析--基本使用流程分析 一. 使用 同步请求 OkHttpClient okHttpClient=new OkHttpClient(); Request request=new Re ...

随机推荐

  1. csharp: Procedure with DAO(Data Access Object) and DAL(Data Access Layer)

    sql script code: CREATE TABLE DuCardType ( CardTypeId INT IDENTITY(1,1) PRIMARY KEY, CardTypeName NV ...

  2. 造完美的go开发环境

    http://www.cnblogs.com/qgymje/p/3912259.html   这篇原来是给公司里使用go开发的交流用的,主要是工具的安装,用markdown写的,发布了内部gitlab ...

  3. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  4. javascript 之正则匹配HTML

    正则表达式 <(\S*?) [^>]*>.*?</\1>|<.*? /> 匹配 <html>hello</html>|<a> ...

  5. redis 慢日志 slowlog

    1 slowlog是什么 redis的slowlog是redis用于记录记录慢查询执行时间的日志系统.由于slowlog只保存在内存中,因此slowlog的效率很高,完全不用担心会影响到redis的性 ...

  6. 六个创建模式之单例模式(Singleton Pattern)

    定义: 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.三个特点:一个类只有一个实例:必需自己创建这个实例:必需自行向整个系统提供这个实例. 结构图: Singleton:单例类,提 ...

  7. 解决客户 IE 浏览器"兼容性视图"设置带来的问题

    最近在给客户开发一个 ASP.NET web 报表时,发现客户的 IE8 浏览器上,看网页总是怪怪的. 调查后发现,客户的 IE8 浏览器,统一被设置成"对本地网络使用兼容性视图" ...

  8. Exchange 2013 、Lync 2013、SharePoint 2013 二

    上一篇简单介绍了安装过程,本篇主要集成 上一篇文章有关于头像的显示问题,engineer  给出了一个连接,介绍了Exchange和Lync的集成过程,根据介绍都配制了一遍. 一.Exchange 和 ...

  9. vh属性-- 一个永远垂直居中的弹出框

    下面的demo,无论浏览器大小如何改变,滚动条是否滚动,弹出框永远水平垂直居中 <html> <head> <title></title> </h ...

  10. Android子线程更新UI主线程方法之Handler

    背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. ...