Skip to content

Commit

Permalink
Merge pull request kata-containers#811 from amshinde/network_refactor
Browse files Browse the repository at this point in the history
Refactor network.go
  • Loading branch information
amshinde authored Oct 15, 2018
2 parents 7fb2706 + b04691e commit d00742f
Show file tree
Hide file tree
Showing 18 changed files with 1,368 additions and 1,239 deletions.
112 changes: 112 additions & 0 deletions virtcontainers/bridgedmacvlan_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package virtcontainers

import (
"fmt"

"github.com/containernetworking/plugins/pkg/ns"
)

// BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM
type BridgedMacvlanEndpoint struct {
NetPair NetworkInterfacePair
EndpointProperties NetworkInfo
EndpointType EndpointType
PCIAddr string
}

func createBridgedMacvlanNetworkEndpoint(idx int, ifName string, interworkingModel NetInterworkingModel) (*BridgedMacvlanEndpoint, error) {
if idx < 0 {
return &BridgedMacvlanEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
}

netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
if err != nil {
return nil, err
}

endpoint := &BridgedMacvlanEndpoint{
NetPair: netPair,
EndpointType: BridgedMacvlanEndpointType,
}
if ifName != "" {
endpoint.NetPair.VirtIface.Name = ifName
}

return endpoint, nil
}

// Properties returns properties of the interface.
func (endpoint *BridgedMacvlanEndpoint) Properties() NetworkInfo {
return endpoint.EndpointProperties
}

// Name returns name of the veth interface in the network pair.
func (endpoint *BridgedMacvlanEndpoint) Name() string {
return endpoint.NetPair.VirtIface.Name
}

// HardwareAddr returns the mac address that is assigned to the tap interface
// in th network pair.
func (endpoint *BridgedMacvlanEndpoint) HardwareAddr() string {
return endpoint.NetPair.TAPIface.HardAddr
}

// Type identifies the endpoint as a virtual endpoint.
func (endpoint *BridgedMacvlanEndpoint) Type() EndpointType {
return endpoint.EndpointType
}

// SetProperties sets the properties for the endpoint.
func (endpoint *BridgedMacvlanEndpoint) SetProperties(properties NetworkInfo) {
endpoint.EndpointProperties = properties
}

// PciAddr returns the PCI address of the endpoint.
func (endpoint *BridgedMacvlanEndpoint) PciAddr() string {
return endpoint.PCIAddr
}

// NetworkPair returns the network pair of the endpoint.
func (endpoint *BridgedMacvlanEndpoint) NetworkPair() *NetworkInterfacePair {
return &endpoint.NetPair
}

// Attach for virtual endpoint bridges the network pair and adds the
// tap interface of the network pair to the hypervisor.
func (endpoint *BridgedMacvlanEndpoint) Attach(h hypervisor) error {
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
networkLogger().WithError(err).Error("Error bridging virtual ep")
return err
}

return h.addDevice(endpoint, netDev)
}

// Detach for the virtual endpoint tears down the tap and bridge
// created for the veth interface.
func (endpoint *BridgedMacvlanEndpoint) Detach(netNsCreated bool, netNsPath string) error {
// The network namespace would have been deleted at this point
// if it has not been created by virtcontainers.
if !netNsCreated {
return nil
}

return doNetNS(netNsPath, func(_ ns.NetNS) error {
return xconnectVMNetwork(endpoint, false, 0, false)
})
}

// HotAttach for physical endpoint not supported yet
func (endpoint *BridgedMacvlanEndpoint) HotAttach(h hypervisor) error {
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot attach")
}

// HotDetach for physical endpoint not supported yet
func (endpoint *BridgedMacvlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot detach")
}
47 changes: 47 additions & 0 deletions virtcontainers/bridgedmacvlan_endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package virtcontainers

import (
"net"
"reflect"
"testing"
)

func TestCreateBridgedMacvlanEndpoint(t *testing.T) {
macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x04}

expected := &BridgedMacvlanEndpoint{
NetPair: NetworkInterfacePair{
ID: "uniqueTestID-4",
Name: "br4_kata",
VirtIface: NetworkInterface{
Name: "eth4",
HardAddr: macAddr.String(),
},
TAPIface: NetworkInterface{
Name: "tap4_kata",
},
NetInterworkingModel: DefaultNetInterworkingModel,
},
EndpointType: BridgedMacvlanEndpointType,
}

result, err := createBridgedMacvlanNetworkEndpoint(4, "", DefaultNetInterworkingModel)
if err != nil {
t.Fatal(err)
}

// the resulting ID will be random - so let's overwrite to test the rest of the flow
result.NetPair.ID = "uniqueTestID-4"

// the resulting mac address will be random - so lets overwrite it
result.NetPair.VirtIface.HardAddr = macAddr.String()

if reflect.DeepEqual(result, expected) == false {
t.Fatalf("\nGot: %+v, \n\nExpected: %+v", result, expected)
}
}
2 changes: 2 additions & 0 deletions virtcontainers/default_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (n *defNetwork) add(s *Sandbox) error {

err = doNetNS(s.config.NetworkConfig.NetNSPath, func(_ ns.NetNS) error {
for _, endpoint := range s.networkNS.Endpoints {
n.logger().WithField("endpoint-type", endpoint.Type()).Info("Attaching endpoint")
if err := endpoint.Attach(s.hypervisor); err != nil {
return err
}
Expand All @@ -83,6 +84,7 @@ func (n *defNetwork) remove(s *Sandbox) error {
for _, endpoint := range s.networkNS.Endpoints {
// Detach for an endpoint should enter the network namespace
// if required.
n.logger().WithField("endpoint-type", endpoint.Type()).Info("Detaching endpoint")
if err := endpoint.Detach(s.networkNS.NetNsCreated, s.networkNS.NetNsPath); err != nil {
return err
}
Expand Down
87 changes: 87 additions & 0 deletions virtcontainers/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package virtcontainers

import (
"fmt"
)

// Endpoint represents a physical or virtual network interface.
type Endpoint interface {
Properties() NetworkInfo
Name() string
HardwareAddr() string
Type() EndpointType
PciAddr() string
NetworkPair() *NetworkInterfacePair

SetProperties(NetworkInfo)
Attach(hypervisor) error
Detach(netNsCreated bool, netNsPath string) error
HotAttach(h hypervisor) error
HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error
}

// EndpointType identifies the type of the network endpoint.
type EndpointType string

const (
// PhysicalEndpointType is the physical network interface.
PhysicalEndpointType EndpointType = "physical"

// VethEndpointType is the virtual network interface.
VethEndpointType EndpointType = "virtual"

// VhostUserEndpointType is the vhostuser network interface.
VhostUserEndpointType EndpointType = "vhost-user"

// BridgedMacvlanEndpointType is macvlan network interface.
BridgedMacvlanEndpointType EndpointType = "macvlan"

// MacvtapEndpointType is macvtap network interface.
MacvtapEndpointType EndpointType = "macvtap"
)

// Set sets an endpoint type based on the input string.
func (endpointType *EndpointType) Set(value string) error {
switch value {
case "physical":
*endpointType = PhysicalEndpointType
return nil
case "virtual":
*endpointType = VethEndpointType
return nil
case "vhost-user":
*endpointType = VhostUserEndpointType
return nil
case "macvlan":
*endpointType = BridgedMacvlanEndpointType
return nil
case "macvtap":
*endpointType = MacvtapEndpointType
return nil
default:
return fmt.Errorf("Unknown endpoint type %s", value)
}
}

// String converts an endpoint type to a string.
func (endpointType *EndpointType) String() string {
switch *endpointType {
case PhysicalEndpointType:
return string(PhysicalEndpointType)
case VethEndpointType:
return string(VethEndpointType)
case VhostUserEndpointType:
return string(VhostUserEndpointType)
case BridgedMacvlanEndpointType:
return string(BridgedMacvlanEndpointType)
case MacvtapEndpointType:
return string(MacvtapEndpointType)
default:
return ""
}
}
89 changes: 89 additions & 0 deletions virtcontainers/endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package virtcontainers

import "testing"

func testEndpointTypeSet(t *testing.T, value string, expected EndpointType) {
//var netModel NetworkModel
var endpointType EndpointType

err := endpointType.Set(value)
if err != nil {
t.Fatal(err)
}

if endpointType != expected {
t.Fatal()
}
}

func TestPhysicalEndpointTypeSet(t *testing.T) {
testEndpointTypeSet(t, "physical", PhysicalEndpointType)
}

func TestVethEndpointTypeSet(t *testing.T) {
testEndpointTypeSet(t, "virtual", VethEndpointType)
}

func TestVhostUserEndpointTypeSet(t *testing.T) {
testEndpointTypeSet(t, "vhost-user", VhostUserEndpointType)
}

func TestBridgedMacvlanEndpointTypeSet(t *testing.T) {
testEndpointTypeSet(t, "macvlan", BridgedMacvlanEndpointType)
}

func TestMacvtapEndpointTypeSet(t *testing.T) {
testEndpointTypeSet(t, "macvtap", MacvtapEndpointType)
}

func TestEndpointTypeSetFailure(t *testing.T) {
var endpointType EndpointType

err := endpointType.Set("wrong-value")
if err == nil {
t.Fatal(err)
}
}

func testEndpointTypeString(t *testing.T, endpointType *EndpointType, expected string) {
result := endpointType.String()

if result != expected {
t.Fatal()
}
}

func TestPhysicalEndpointTypeString(t *testing.T) {
endpointType := PhysicalEndpointType
testEndpointTypeString(t, &endpointType, string(PhysicalEndpointType))
}

func TestVethEndpointTypeString(t *testing.T) {
endpointType := VethEndpointType
testEndpointTypeString(t, &endpointType, string(VethEndpointType))
}

func TestVhostUserEndpointTypeString(t *testing.T) {
endpointType := VhostUserEndpointType
testEndpointTypeString(t, &endpointType, string(VhostUserEndpointType))
}

func TestBridgedMacvlanEndpointTypeString(t *testing.T) {
endpointType := BridgedMacvlanEndpointType
testEndpointTypeString(t, &endpointType, string(BridgedMacvlanEndpointType))
}

func TestMacvtapEndpointTypeString(t *testing.T) {
endpointType := MacvtapEndpointType
testEndpointTypeString(t, &endpointType, string(MacvtapEndpointType))
}

func TestIncorrectEndpointTypeString(t *testing.T) {
var endpointType EndpointType
testEndpointTypeString(t, &endpointType, "")
}
Loading

0 comments on commit d00742f

Please sign in to comment.