Files
kata-containers/virtcontainers/cni.go
Peng Tao 5fb4768f83 virtcontainers: always pass sandbox as a pointer
Currently we sometimes pass it as a pointer and other times not. As
a result, the view of sandbox across virtcontainers may not be the same
and it costs extra memory copy each time we pass it by value. Fix it
by ensuring sandbox is always passed by pointers.

Fixes: #262

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2018-05-01 20:50:07 +08:00

169 lines
4.5 KiB
Go

// Copyright (c) 2016 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
cniTypes "github.com/containernetworking/cni/pkg/types"
cniV2Types "github.com/containernetworking/cni/pkg/types/020"
cniLatestTypes "github.com/containernetworking/cni/pkg/types/current"
cniPlugin "github.com/kata-containers/runtime/virtcontainers/pkg/cni"
"github.com/sirupsen/logrus"
)
// CniPrimaryInterface Name chosen for the primary interface
// If CNI ever support multiple primary interfaces this should be revisited
const CniPrimaryInterface = "eth0"
// cni is a network implementation for the CNI plugin.
type cni struct{}
// Logger returns a logrus logger appropriate for logging cni messages
func (n *cni) Logger() *logrus.Entry {
return virtLog.WithField("subsystem", "cni")
}
func cniDNSToDNSInfo(cniDNS cniTypes.DNS) DNSInfo {
return DNSInfo{
Servers: cniDNS.Nameservers,
Domain: cniDNS.Domain,
Searches: cniDNS.Search,
Options: cniDNS.Options,
}
}
func convertLatestCNIResult(result *cniLatestTypes.Result) NetworkInfo {
return NetworkInfo{
DNS: cniDNSToDNSInfo(result.DNS),
}
}
func convertV2CNIResult(result *cniV2Types.Result) NetworkInfo {
return NetworkInfo{
DNS: cniDNSToDNSInfo(result.DNS),
}
}
func convertCNIResult(cniResult cniTypes.Result) (NetworkInfo, error) {
switch result := cniResult.(type) {
case *cniLatestTypes.Result:
return convertLatestCNIResult(result), nil
case *cniV2Types.Result:
return convertV2CNIResult(result), nil
default:
return NetworkInfo{}, fmt.Errorf("Unknown CNI result type %T", result)
}
}
func (n *cni) invokePluginsAdd(sandbox *Sandbox, networkNS *NetworkNamespace) (*NetworkInfo, error) {
netPlugin, err := cniPlugin.NewNetworkPlugin()
if err != nil {
return nil, err
}
// Note: In the case of multus or cni-genie this will return only the results
// corresponding to the primary interface. The remaining results need to be
// derived
result, err := netPlugin.AddNetwork(sandbox.id, networkNS.NetNsPath, CniPrimaryInterface)
if err != nil {
return nil, err
}
netInfo, err := convertCNIResult(result)
if err != nil {
return nil, err
}
// We do not care about this for now but
// If present, the CNI DNS result has to be updated in resolv.conf
// if the kubelet has not supplied it already
n.Logger().Infof("AddNetwork results %s", result.String())
return &netInfo, nil
}
func (n *cni) invokePluginsDelete(sandbox *Sandbox, networkNS NetworkNamespace) error {
netPlugin, err := cniPlugin.NewNetworkPlugin()
if err != nil {
return err
}
err = netPlugin.RemoveNetwork(sandbox.id, networkNS.NetNsPath, CniPrimaryInterface)
if err != nil {
return err
}
return nil
}
func (n *cni) updateEndpointsFromScan(networkNS *NetworkNamespace, netInfo *NetworkInfo, config NetworkConfig) error {
endpoints, err := createEndpointsFromScan(networkNS.NetNsPath, config)
if err != nil {
return err
}
for _, endpoint := range endpoints {
if CniPrimaryInterface == endpoint.Name() {
prop := endpoint.Properties()
prop.DNS = netInfo.DNS
endpoint.SetProperties(prop)
break
}
}
networkNS.Endpoints = endpoints
return nil
}
// init initializes the network, setting a new network namespace for the CNI network.
func (n *cni) init(config NetworkConfig) (string, bool, error) {
return initNetworkCommon(config)
}
// run runs a callback in the specified network namespace.
func (n *cni) run(networkNSPath string, cb func() error) error {
return runNetworkCommon(networkNSPath, cb)
}
// add adds all needed interfaces inside the network namespace for the CNI network.
func (n *cni) add(sandbox *Sandbox, config NetworkConfig, netNsPath string, netNsCreated bool) (NetworkNamespace, error) {
networkNS := NetworkNamespace{
NetNsPath: netNsPath,
NetNsCreated: netNsCreated,
}
netInfo, err := n.invokePluginsAdd(sandbox, &networkNS)
if err != nil {
return NetworkNamespace{}, err
}
if err := n.updateEndpointsFromScan(&networkNS, netInfo, config); err != nil {
return NetworkNamespace{}, err
}
if err := addNetworkCommon(sandbox, &networkNS); err != nil {
return NetworkNamespace{}, err
}
return networkNS, nil
}
// remove unbridges and deletes TAP interfaces. It also removes virtual network
// interfaces and deletes the network namespace for the CNI network.
func (n *cni) remove(sandbox *Sandbox, networkNS NetworkNamespace) error {
if err := removeNetworkCommon(networkNS); err != nil {
return err
}
if err := n.invokePluginsDelete(sandbox, networkNS); err != nil {
return err
}
return deleteNetNS(networkNS.NetNsPath, true)
}