runC 中 network 实现

runC 的网络实现开始于 libcontainer/process_linux.go 中func (p *initProcess) start() 调用createNetworkInterfaces()函数

该函数实现如下:

func (p *initProcess) createNetworkInterfaces() error {
	for _, config := range p.config.Config.Networks {//遍历所有网络配置
		strategy, err := getStrategy(config.Type)//获取网络类别,桥接或者loopback
		if err != nil {
			return err
		}
		n := &network{
			Network: *config,
		}
		if err := strategy.create(n, p.pid()); err != nil {//创建网络。参数为网络配置和进程号
			return err
		}
		p.config.Networks = append(p.config.Networks, n)
	}
	return nil
}

网络的具体实现在 libcontainer/network_linux.go中
var strategies = map[string]networkStrategy{ //两种网络策略
	"veth":     &veth{},
	"loopback": &loopback{},
}

// networkStrategy represents a specific network configuration for
// a container's networking stack
type networkStrategy interface {                 //网络策略接口
	create(*network, int) error
	initialize(*network) error
	detach(*configs.Network) error
	attach(*configs.Network) error
}

........省略loopback实现

// veth is a network strategy that uses a bridge and creates
// a veth pair, one that is attached to the bridge on the host and the other
// is placed inside the container's namespace
type veth struct {
}

func (v *veth) detach(n *configs.Network) (err error) {
	return netlink.LinkSetMaster(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: n.HostInterfaceName}}, nil)
}

// attach a container network interface to an external network
func (v *veth) attach(n *configs.Network) (err error) {
	brl, err := netlink.LinkByName(n.Bridge)
	if err != nil {
		return err
	}
	br, ok := brl.(*netlink.Bridge)
	if !ok {
		return fmt.Errorf("Wrong device type %T", brl)
	}
	host, err := netlink.LinkByName(n.HostInterfaceName)
	if err != nil {
		return err
	}

	if err := netlink.LinkSetMaster(host, br); err != nil {//桥接外部网桥
		return err
	}
	if err := netlink.LinkSetMTU(host, n.Mtu); err != nil {
		return err
	}
	if n.HairpinMode {
		if err := netlink.LinkSetHairpin(host, true); err != nil {
			return err
		}
	}
	if err := netlink.LinkSetUp(host); err != nil {
		return err
	}

	return nil
}

func (v *veth) create(n *network, nspid int) (err error) {
	tmpName, err := v.generateTempPeerName()//生成随机的桥接vethpair名
	if err != nil {
		return err
	}
	n.TempVethPeerName = tmpName
	if n.Bridge == "" {
		return fmt.Errorf("bridge is not specified")
	}
	veth := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name:   n.HostInterfaceName,
			TxQLen: n.TxQueueLen,
		},
		PeerName: n.TempVethPeerName,
	}
	if err := netlink.LinkAdd(veth); err != nil {  //
		return err
	}
	defer func() {
		if err != nil {
			netlink.LinkDel(veth)
		}
	}()
	if err := v.attach(&n.Network); err != nil {//将vethpari 一端添加到外部网络,即桥接外部网桥
		return err
	}
	child, err := netlink.LinkByName(n.TempVethPeerName)
	if err != nil {
		return err
	}
	return netlink.LinkSetNsPid(child, nspid)//将vethpari 另外一端添加到容器的网络命名空间里
}


func (v *veth) initialize(config *network) error {
	peer := config.TempVethPeerName
	if peer == "" {
		return fmt.Errorf("peer is not specified")
	}
	child, err := netlink.LinkByName(peer)
	if err != nil {
		return err
	}
	if err := netlink.LinkSetDown(child); err != nil {
		return err
	}
	if err := netlink.LinkSetName(child, config.Name); err != nil {
		return err
	}
	// get the interface again after we changed the name as the index also changes.
	if child, err = netlink.LinkByName(config.Name); err != nil {
		return err
	}
	if config.MacAddress != "" {
		mac, err := net.ParseMAC(config.MacAddress)
		if err != nil {
			return err
		}
		if err := netlink.LinkSetHardwareAddr(child, mac); err != nil {
			return err
		}
	}
	ip, err := netlink.ParseAddr(config.Address)
	if err != nil {
		return err
	}
	if err := netlink.AddrAdd(child, ip); err != nil {
		return err
	}
	if config.IPv6Address != "" {
		ip6, err := netlink.ParseAddr(config.IPv6Address)
		if err != nil {
			return err
		}
		if err := netlink.AddrAdd(child, ip6); err != nil {
			return err
		}
	}
	if err := netlink.LinkSetMTU(child, config.Mtu); err != nil {
		return err
	}
	if err := netlink.LinkSetUp(child); err != nil {
		return err
	}
	if config.Gateway != "" {//路由设置
		gw := net.ParseIP(config.Gateway)
		if err := netlink.RouteAdd(&netlink.Route{
			Scope:     netlink.SCOPE_UNIVERSE,
			LinkIndex: child.Attrs().Index,
			Gw:        gw,
		}); err != nil {
			return err
		}
	}
	if config.IPv6Gateway != "" {//网关设置
		gw := net.ParseIP(config.IPv6Gateway)
		if err := netlink.RouteAdd(&netlink.Route{
			Scope:     netlink.SCOPE_UNIVERSE,
			LinkIndex: child.Attrs().Index,
			Gw:        gw,
		}); err != nil {
			return err
		}
	}
	return nil
}



你可能感兴趣的:(Docker,SDN,go,cloud,k8s)