mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-22 01:43:04 +00:00
virtcontainers: refactor hotplug qmp functions
Refactor these functions so differernt types of endpoints can use a unified function to hotplug nics. Fixes #731 Signed-off-by: Ruidong Cao <caoruidong@huawei.com>
This commit is contained in:
parent
daf52dec57
commit
f8f29622a4
@ -71,6 +71,11 @@ func (endpoint *BridgedMacvlanEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *BridgedMacvlanEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *BridgedMacvlanEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return &endpoint.NetPair
|
return &endpoint.NetPair
|
||||||
|
@ -16,15 +16,17 @@ func TestCreateBridgedMacvlanEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
expected := &BridgedMacvlanEndpoint{
|
expected := &BridgedMacvlanEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
ID: "uniqueTestID-4",
|
TapInterface: TapInterface{
|
||||||
Name: "br4_kata",
|
ID: "uniqueTestID-4",
|
||||||
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: BridgedMacvlanEndpointType,
|
EndpointType: BridgedMacvlanEndpointType,
|
||||||
|
@ -19,6 +19,7 @@ type Endpoint interface {
|
|||||||
NetworkPair() *NetworkInterfacePair
|
NetworkPair() *NetworkInterfacePair
|
||||||
|
|
||||||
SetProperties(NetworkInfo)
|
SetProperties(NetworkInfo)
|
||||||
|
SetPciAddr(string)
|
||||||
Attach(hypervisor) error
|
Attach(hypervisor) error
|
||||||
Detach(netNsCreated bool, netNsPath string) error
|
Detach(netNsCreated bool, netNsPath string) error
|
||||||
HotAttach(h hypervisor) error
|
HotAttach(h hypervisor) error
|
||||||
|
@ -93,6 +93,11 @@ func (endpoint *MacvtapEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return nil
|
return nil
|
||||||
|
@ -122,17 +122,22 @@ type NetworkInterface struct {
|
|||||||
Addrs []netlink.Addr
|
Addrs []netlink.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
|
// TapInterface defines a tap nic.
|
||||||
type NetworkInterfacePair struct {
|
type TapInterface struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
VirtIface NetworkInterface
|
TAPIface NetworkInterface
|
||||||
TAPIface NetworkInterface
|
|
||||||
NetInterworkingModel
|
|
||||||
VMFds []*os.File
|
VMFds []*os.File
|
||||||
VhostFds []*os.File
|
VhostFds []*os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
|
||||||
|
type NetworkInterfacePair struct {
|
||||||
|
TapInterface
|
||||||
|
VirtIface NetworkInterface
|
||||||
|
NetInterworkingModel
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkConfig is the network configuration related to a network.
|
// NetworkConfig is the network configuration related to a network.
|
||||||
type NetworkConfig struct {
|
type NetworkConfig struct {
|
||||||
NetNSPath string
|
NetNSPath string
|
||||||
@ -962,15 +967,17 @@ func createNetworkInterfacePair(idx int, ifName string, interworkingModel NetInt
|
|||||||
}
|
}
|
||||||
|
|
||||||
netPair := NetworkInterfacePair{
|
netPair := NetworkInterfacePair{
|
||||||
ID: uniqueID,
|
TapInterface: TapInterface{
|
||||||
Name: fmt.Sprintf("br%d_kata", idx),
|
ID: uniqueID,
|
||||||
|
Name: fmt.Sprintf("br%d_kata", idx),
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: fmt.Sprintf("tap%d_kata", idx),
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: fmt.Sprintf("eth%d", idx),
|
Name: fmt.Sprintf("eth%d", idx),
|
||||||
HardAddr: randomMacAddr,
|
HardAddr: randomMacAddr,
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: fmt.Sprintf("tap%d_kata", idx),
|
|
||||||
},
|
|
||||||
NetInterworkingModel: interworkingModel,
|
NetInterworkingModel: interworkingModel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,11 @@ func (endpoint *PhysicalEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// SetProperties sets the properties of the physical endpoint.
|
// SetProperties sets the properties of the physical endpoint.
|
||||||
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
endpoint.EndpointProperties = properties
|
endpoint.EndpointProperties = properties
|
||||||
|
@ -838,66 +838,77 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) hotplugMacvtap(drive *VethEndpoint) error {
|
func (q *qemu) hotAddNetDevice(name, hardAddr string, VMFds, VhostFds []*os.File) error {
|
||||||
var (
|
var (
|
||||||
VMFdNames []string
|
VMFdNames []string
|
||||||
VhostFdNames []string
|
VhostFdNames []string
|
||||||
)
|
)
|
||||||
for i, VMFd := range drive.NetPair.VMFds {
|
for i, VMFd := range VMFds {
|
||||||
fdName := fmt.Sprintf("fd%d", i)
|
fdName := fmt.Sprintf("fd%d", i)
|
||||||
err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VMFd)
|
if err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VMFd); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
VMFdNames = append(VMFdNames, fdName)
|
VMFdNames = append(VMFdNames, fdName)
|
||||||
}
|
}
|
||||||
for i, VhostFd := range drive.NetPair.VhostFds {
|
for i, VhostFd := range VhostFds {
|
||||||
fdName := fmt.Sprintf("vhostfd%d", i)
|
fdName := fmt.Sprintf("vhostfd%d", i)
|
||||||
err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VhostFd)
|
if err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VhostFd); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
VhostFdNames = append(VhostFdNames, fdName)
|
VhostFdNames = append(VhostFdNames, fdName)
|
||||||
}
|
}
|
||||||
return q.qmpMonitorCh.qmp.ExecuteNetdevAddByFds(q.qmpMonitorCh.ctx, "tap", drive.NetPair.Name, VMFdNames, VhostFdNames)
|
return q.qmpMonitorCh.qmp.ExecuteNetdevAddByFds(q.qmpMonitorCh.ctx, "tap", name, VMFdNames, VhostFdNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) hotplugNetDevice(drive *VethEndpoint, op operation) error {
|
func (q *qemu) hotplugNetDevice(endpoint Endpoint, op operation) error {
|
||||||
err := q.qmpSetup()
|
err := q.qmpSetup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
devID := "virtio-" + drive.NetPair.ID
|
var tap TapInterface
|
||||||
|
|
||||||
if op == addDevice {
|
if op == addDevice {
|
||||||
switch drive.NetPair.NetInterworkingModel {
|
switch endpoint.Type() {
|
||||||
case NetXConnectBridgedModel:
|
case VethEndpointType:
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteNetdevAdd(q.qmpMonitorCh.ctx, "tap", drive.NetPair.Name, drive.NetPair.TAPIface.Name, "no", "no", int(q.config.NumVCPUs)); err != nil {
|
drive := endpoint.(*VethEndpoint)
|
||||||
return err
|
tap = drive.NetPair.TapInterface
|
||||||
}
|
|
||||||
case NetXConnectMacVtapModel:
|
|
||||||
if err := q.hotplugMacvtap(drive); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("this net interworking model is not supported")
|
return fmt.Errorf("this endpoint is not supported")
|
||||||
}
|
}
|
||||||
addr, bridge, err := q.addDeviceToBridge(drive.NetPair.ID)
|
|
||||||
|
if err = q.hotAddNetDevice(tap.Name, endpoint.HardwareAddr(), tap.VMFds, tap.VhostFds); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, bridge, err := q.addDeviceToBridge(tap.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
drive.PCIAddr = fmt.Sprintf("%02x/%s", bridge.Addr, addr)
|
pciAddr := fmt.Sprintf("%02x/%s", bridge.Addr, addr)
|
||||||
if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, drive.NetPair.Name, devID, drive.NetPair.TAPIface.HardAddr, addr, bridge.ID, romFile, int(q.config.NumVCPUs)); err != nil {
|
endpoint.SetPciAddr(pciAddr)
|
||||||
|
|
||||||
|
devID := "virtio-" + tap.ID
|
||||||
|
if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, tap.Name, devID, endpoint.HardwareAddr(), addr, bridge.ID, romFile, int(q.config.NumVCPUs)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := q.removeDeviceFromBridge(drive.NetPair.ID); err != nil {
|
switch endpoint.Type() {
|
||||||
|
case VethEndpointType:
|
||||||
|
drive := endpoint.(*VethEndpoint)
|
||||||
|
tap = drive.NetPair.TapInterface
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("this endpoint is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.removeDeviceFromBridge(tap.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devID := "virtio-" + tap.ID
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil {
|
if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteNetdevDel(q.qmpMonitorCh.ctx, drive.NetPair.Name); err != nil {
|
if err := q.qmpMonitorCh.qmp.ExecuteNetdevDel(q.qmpMonitorCh.ctx, tap.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -919,7 +930,7 @@ func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operati
|
|||||||
memdev := devInfo.(*memoryDevice)
|
memdev := devInfo.(*memoryDevice)
|
||||||
return q.hotplugMemory(memdev, op)
|
return q.hotplugMemory(memdev, op)
|
||||||
case netDev:
|
case netDev:
|
||||||
device := devInfo.(*VethEndpoint)
|
device := devInfo.(Endpoint)
|
||||||
return nil, q.hotplugNetDevice(device, op)
|
return nil, q.hotplugNetDevice(device, op)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("cannot hotplug device: unsupported device type '%v'", devType)
|
return nil, fmt.Errorf("cannot hotplug device: unsupported device type '%v'", devType)
|
||||||
|
@ -443,15 +443,17 @@ func TestQemuArchBaseAppendNetwork(t *testing.T) {
|
|||||||
|
|
||||||
macvlanEp := &BridgedMacvlanEndpoint{
|
macvlanEp := &BridgedMacvlanEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
ID: "uniqueTestID-4",
|
TapInterface: TapInterface{
|
||||||
Name: "br4_kata",
|
ID: "uniqueTestID-4",
|
||||||
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: BridgedMacvlanEndpointType,
|
EndpointType: BridgedMacvlanEndpointType,
|
||||||
|
@ -1142,6 +1142,9 @@ func (s *Sandbox) RemoveInterface(inf *grpc.Interface) (*grpc.Interface, error)
|
|||||||
return inf, err
|
return inf, err
|
||||||
}
|
}
|
||||||
s.networkNS.Endpoints = append(s.networkNS.Endpoints[:i], s.networkNS.Endpoints[i+1:]...)
|
s.networkNS.Endpoints = append(s.networkNS.Endpoints[:i], s.networkNS.Endpoints[i+1:]...)
|
||||||
|
if err := s.storage.storeSandboxNetwork(s.id, s.networkNS); err != nil {
|
||||||
|
return inf, err
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,11 @@ func (endpoint *VethEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *VethEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *VethEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *VethEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return &endpoint.NetPair
|
return &endpoint.NetPair
|
||||||
|
@ -16,15 +16,17 @@ func TestCreateVethNetworkEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
expected := &VethEndpoint{
|
expected := &VethEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
ID: "uniqueTestID-4",
|
TapInterface: TapInterface{
|
||||||
Name: "br4_kata",
|
ID: "uniqueTestID-4",
|
||||||
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: VethEndpointType,
|
EndpointType: VethEndpointType,
|
||||||
@ -51,15 +53,17 @@ func TestCreateVethNetworkEndpointChooseIfaceName(t *testing.T) {
|
|||||||
|
|
||||||
expected := &VethEndpoint{
|
expected := &VethEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
ID: "uniqueTestID-4",
|
TapInterface: TapInterface{
|
||||||
Name: "br4_kata",
|
ID: "uniqueTestID-4",
|
||||||
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth1",
|
Name: "eth1",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: VethEndpointType,
|
EndpointType: VethEndpointType,
|
||||||
|
@ -62,6 +62,11 @@ func (endpoint *VhostUserEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user