Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
network: Add tuntap device
Browse files Browse the repository at this point in the history
The tuntap network device is for tuntap interfaces to connect
to the container. A specific use case is the slirp4netns tap
interface for rootless kata-runtime.

Fixes: #1878

Signed-off-by: Gabi Beyer <gabrielle.n.beyer@intel.com>
  • Loading branch information
Gabi Beyer committed Sep 5, 2019
1 parent bb7fac5 commit c676a6d
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 5 deletions.
38 changes: 38 additions & 0 deletions virtcontainers/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ const (
// TapEndpointType is tap network interface.
TapEndpointType EndpointType = "tap"

// TuntapEndpointType is a tap network interface.
TuntapEndpointType EndpointType = "tuntap"

// IPVlanEndpointType is ipvlan network interface.
IPVlanEndpointType EndpointType = "ipvlan"
)
Expand All @@ -78,6 +81,9 @@ func (endpointType *EndpointType) Set(value string) error {
case "tap":
*endpointType = TapEndpointType
return nil
case "tuntap":
*endpointType = TuntapEndpointType
return nil
case "ipvlan":
*endpointType = IPVlanEndpointType
return nil
Expand All @@ -101,6 +107,8 @@ func (endpointType *EndpointType) String() string {
return string(MacvtapEndpointType)
case TapEndpointType:
return string(TapEndpointType)
case TuntapEndpointType:
return string(TuntapEndpointType)
case IPVlanEndpointType:
return string(IPVlanEndpointType)
default:
Expand Down Expand Up @@ -183,3 +191,33 @@ func loadNetIfPair(pair *persistapi.NetworkInterfacePair) *NetworkInterfacePair
NetInterworkingModel: NetInterworkingModel(pair.NetInterworkingModel),
}
}

func saveTuntapIf(tuntapif *TuntapInterface) *persistapi.TuntapInterface {
if tuntapif == nil {
return nil
}

return &persistapi.TuntapInterface{
Name: tuntapif.Name,
TAPIface: persistapi.NetworkInterface{
Name: tuntapif.TAPIface.Name,
HardAddr: tuntapif.TAPIface.HardAddr,
Addrs: tuntapif.TAPIface.Addrs,
},
}
}

func loadTuntapIf(tuntapif *persistapi.TuntapInterface) *TuntapInterface {
if tuntapif == nil {
return nil
}

return &TuntapInterface{
Name: tuntapif.Name,
TAPIface: NetworkInterface{
Name: tuntapif.TAPIface.Name,
HardAddr: tuntapif.TAPIface.HardAddr,
Addrs: tuntapif.TAPIface.Addrs,
},
}
}
39 changes: 35 additions & 4 deletions virtcontainers/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ type TapInterface struct {
VhostFds []*os.File
}

// TuntapInterface defines a tap interface
type TuntapInterface struct {
Name string
TAPIface NetworkInterface
}

// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
type NetworkInterfacePair struct {
TapInterface
Expand Down Expand Up @@ -262,6 +268,10 @@ func generateEndpoints(typedEndpoints []TypedJSONEndpoint) ([]Endpoint, error) {
var endpoint IPVlanEndpoint
endpointInf = &endpoint

case TuntapEndpointType:
var endpoint TuntapEndpoint
endpointInf = &endpoint

default:
networkLogger().WithField("endpoint-type", e.Type).Error("Ignoring unknown endpoint type")
}
Expand Down Expand Up @@ -373,6 +383,8 @@ func getLinkForEndpoint(endpoint Endpoint, netHandle *netlink.Handle) (netlink.L
link = &netlink.Macvlan{}
case *IPVlanEndpoint:
link = &netlink.IPVlan{}
case *TuntapEndpoint:
link = &netlink.Tuntap{}
default:
return nil, fmt.Errorf("Unexpected endpointType %s", ep.Type())
}
Expand All @@ -392,7 +404,7 @@ func getLinkByName(netHandle *netlink.Handle, name string, expectedLink netlink.
return l, nil
}
case (&netlink.Tuntap{}).Type():
if l, ok := link.(*netlink.GenericLink); ok {
if l, ok := link.(*netlink.Tuntap); ok {
return l, nil
}
case (&netlink.Veth{}).Type():
Expand Down Expand Up @@ -1237,6 +1249,10 @@ func createNetworkInterfacePair(idx int, ifName string, interworkingModel NetInt
NetInterworkingModel: interworkingModel,
}

if ifName != "" {
netPair.VirtIface.Name = ifName
}

return netPair, nil
}

Expand Down Expand Up @@ -1323,7 +1339,7 @@ func createEndpointsFromScan(networkNSPath string, config *NetworkConfig) ([]End
}

if err := doNetNS(networkNSPath, func(_ ns.NetNS) error {
endpoint, errCreate = createEndpoint(netInfo, idx, config.InterworkingModel)
endpoint, errCreate = createEndpoint(netInfo, idx, config.InterworkingModel, link)
return errCreate
}); err != nil {
return []Endpoint{}, err
Expand All @@ -1344,7 +1360,7 @@ func createEndpointsFromScan(networkNSPath string, config *NetworkConfig) ([]End
return endpoints, nil
}

func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (Endpoint, error) {
func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel, link netlink.Link) (Endpoint, error) {
var endpoint Endpoint
// TODO: This is the incoming interface
// based on the incoming interface we should create
Expand Down Expand Up @@ -1382,12 +1398,27 @@ func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (E
} else if netInfo.Iface.Type == "tap" {
networkLogger().Info("tap interface found")
endpoint, err = createTapNetworkEndpoint(idx, netInfo.Iface.Name)
} else if netInfo.Iface.Type == "tuntap" {
if link != nil {
switch link.(*netlink.Tuntap).Mode {
case 0:
// mount /sys/class/net to get links
return nil, fmt.Errorf("Network device mode not determined correctly. Mount sysfs in caller")
case 1:
return nil, fmt.Errorf("tun networking device not yet supported")
case 2:
networkLogger().Info("tuntap tap interface found")
endpoint, err = createTuntapNetworkEndpoint(idx, netInfo.Iface.Name, netInfo.Iface.HardwareAddr, model)
default:
return nil, fmt.Errorf("tuntap network %v mode unsupported", link.(*netlink.Tuntap).Mode)
}
}
} else if netInfo.Iface.Type == "veth" {
endpoint, err = createVethNetworkEndpoint(idx, netInfo.Iface.Name, model)
} else if netInfo.Iface.Type == "ipvlan" {
endpoint, err = createIPVlanNetworkEndpoint(idx, netInfo.Iface.Name)
} else {
return nil, fmt.Errorf("Unsupported network interface")
return nil, fmt.Errorf("Unsupported network interface: %s", netInfo.Iface.Type)
}
}

Expand Down
11 changes: 11 additions & 0 deletions virtcontainers/persist/api/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type TapInterface struct {
// remove VMFds and VhostFds
}

// TuntapInterface defines a tap interface
type TuntapInterface struct {
Name string
TAPIface NetworkInterface
}

// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
type NetworkInterfacePair struct {
TapInterface
Expand All @@ -49,6 +55,10 @@ type TapEndpoint struct {
TapInterface TapInterface
}

type TuntapEndpoint struct {
TuntapInterface TuntapInterface
}

type BridgedMacvlanEndpoint struct {
NetPair NetworkInterfacePair
}
Expand Down Expand Up @@ -80,6 +90,7 @@ type NetworkEndpoint struct {
Macvtap *MacvtapEndpoint `json:",omitempty"`
Tap *TapEndpoint `json:",omitempty"`
IPVlan *IPVlanEndpoint `json:",omitempty"`
Tuntap *TuntapEndpoint `json:",omitempty"`
}

// NetworkInfo contains network information of sandbox
Expand Down
15 changes: 15 additions & 0 deletions virtcontainers/qemu_arch_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,21 @@ func genericNetwork(endpoint Endpoint, vhost, nestedRun bool, index int) (govmmQ
FDs: ep.VMFds,
VhostFDs: ep.VhostFds,
}
case *TuntapEndpoint:
netPair := ep.NetworkPair()
d = govmmQemu.NetDevice{
Type: govmmQemu.NetDeviceType("tap"),
Driver: govmmQemu.VirtioNet,
ID: fmt.Sprintf("network-%d", q.networkIndex),
IFName: netPair.TAPIface.Name,
MACAddress: netPair.TAPIface.HardAddr,
DownScript: "no",
Script: "no",
VHost: q.vhost,
DisableModern: q.nestedRun,
FDs: netPair.VMFds,
VhostFDs: netPair.VhostFds,
}
default:
return govmmQemu.NetDevice{}, fmt.Errorf("Unknown type for endpoint")
}
Expand Down
2 changes: 1 addition & 1 deletion virtcontainers/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ func (s *Sandbox) AddInterface(inf *vcTypes.Interface) (*vcTypes.Interface, erro
return nil, err
}

endpoint, err := createEndpoint(netInfo, len(s.networkNS.Endpoints), s.config.NetworkConfig.InterworkingModel)
endpoint, err := createEndpoint(netInfo, len(s.networkNS.Endpoints), s.config.NetworkConfig.InterworkingModel, nil)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit c676a6d

Please sign in to comment.