network: Implement network hotunplug for physical endpoints

Similar to HotAttach, the HotDetach method signature for network
endoints needs to be changed as well to allow for the method to make
use of device manager to manage the hot unplug of physical network
devices.

Signed-off-by: Archana Shinde <archana.m.shinde@intel.com>
This commit is contained in:
Archana Shinde 2023-12-06 21:40:15 -08:00
parent c6390f2a2a
commit 1636c201f4
14 changed files with 55 additions and 17 deletions

View File

@ -94,4 +94,5 @@ type DeviceManager interface {
GetDeviceByID(string) Device GetDeviceByID(string) Device
GetAllDevices() []Device GetAllDevices() []Device
LoadDevices([]config.DeviceState) LoadDevices([]config.DeviceState)
FindDevice(*config.DeviceInfo) Device
} }

View File

@ -82,7 +82,7 @@ func NewDeviceManager(blockDriver string, vhostUserStoreEnabled bool, vhostUserS
return dm return dm
} }
func (dm *deviceManager) findDevice(devInfo *config.DeviceInfo) api.Device { func (dm *deviceManager) FindDevice(devInfo *config.DeviceInfo) api.Device {
// For devices with a major of -1, we use the host path to find existing instances. // For devices with a major of -1, we use the host path to find existing instances.
if devInfo.Major == -1 { if devInfo.Major == -1 {
for _, dev := range dm.devices { for _, dev := range dm.devices {
@ -121,7 +121,7 @@ func (dm *deviceManager) createDevice(devInfo config.DeviceInfo) (dev api.Device
} }
}() }()
if existingDev := dm.findDevice(&devInfo); existingDev != nil { if existingDev := dm.FindDevice(&devInfo); existingDev != nil {
return existingDev, nil return existingDev, nil
} }

View File

@ -27,7 +27,7 @@ type Endpoint interface {
Attach(context.Context, *Sandbox) error Attach(context.Context, *Sandbox) error
Detach(ctx context.Context, netNsCreated bool, netNsPath string) error Detach(ctx context.Context, netNsCreated bool, netNsPath string) error
HotAttach(context.Context, *Sandbox) error HotAttach(context.Context, *Sandbox) error
HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error
save() persistapi.NetworkEndpoint save() persistapi.NetworkEndpoint
load(persistapi.NetworkEndpoint) load(persistapi.NetworkEndpoint)

View File

@ -143,7 +143,7 @@ func (endpoint *IPVlanEndpoint) HotAttach(ctx context.Context, s *Sandbox) error
return nil return nil
} }
func (endpoint *IPVlanEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *IPVlanEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
if !netNsCreated { if !netNsCreated {
return nil return nil
} }
@ -157,6 +157,7 @@ func (endpoint *IPVlanEndpoint) HotDetach(ctx context.Context, h Hypervisor, net
networkLogger().WithError(err).Warn("Error un-bridging ipvlan ep") networkLogger().WithError(err).Warn("Error un-bridging ipvlan ep")
} }
h := s.hypervisor
if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil { if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil {
networkLogger().WithError(err).Error("Error detach ipvlan ep") networkLogger().WithError(err).Error("Error detach ipvlan ep")
return err return err

View File

@ -140,7 +140,7 @@ func (endpoint *MacvlanEndpoint) HotAttach(ctx context.Context, s *Sandbox) erro
return nil return nil
} }
func (endpoint *MacvlanEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *MacvlanEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
if !netNsCreated { if !netNsCreated {
return nil return nil
} }
@ -154,6 +154,7 @@ func (endpoint *MacvlanEndpoint) HotDetach(ctx context.Context, h Hypervisor, ne
networkLogger().WithError(err).Warn("Error un-bridging macvlan ep") networkLogger().WithError(err).Warn("Error un-bridging macvlan ep")
} }
h := s.hypervisor
if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil { if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil {
networkLogger().WithError(err).Error("Error detach macvlan ep") networkLogger().WithError(err).Error("Error detach macvlan ep")
return err return err

View File

@ -98,7 +98,7 @@ func (endpoint *MacvtapEndpoint) HotAttach(ctx context.Context, s *Sandbox) erro
} }
// HotDetach for macvtap endpoint not supported yet // HotDetach for macvtap endpoint not supported yet
func (endpoint *MacvtapEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *MacvtapEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
return fmt.Errorf("MacvtapEndpoint does not support Hot detach") return fmt.Errorf("MacvtapEndpoint does not support Hot detach")
} }

View File

@ -265,7 +265,7 @@ func (n *LinuxNetwork) removeSingleEndpoint(ctx context.Context, s *Sandbox, end
// if required. // if required.
networkLogger().WithField("endpoint-type", endpoint.Type()).Info("Detaching endpoint") networkLogger().WithField("endpoint-type", endpoint.Type()).Info("Detaching endpoint")
if hotplug && s != nil { if hotplug && s != nil {
if err := endpoint.HotDetach(ctx, s.hypervisor, n.netNSCreated, n.netNSPath); err != nil { if err := endpoint.HotDetach(ctx, s, n.netNSCreated, n.netNSPath); err != nil {
return err return err
} }
} else { } else {

View File

@ -152,8 +152,36 @@ func (endpoint *PhysicalEndpoint) HotAttach(ctx context.Context, s *Sandbox) err
} }
// HotDetach for physical endpoint not supported yet // HotDetach for physical endpoint not supported yet
func (endpoint *PhysicalEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *PhysicalEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
return fmt.Errorf("PhysicalEndpoint does not support Hot detach") span, _ := physicalTrace(ctx, "HotDetach", endpoint)
defer span.End()
var vfioPath string
var err error
if vfioPath, err = drivers.GetVFIODevPath(endpoint.BDF); err != nil {
return err
}
c, err := resCtrl.DeviceToCgroupDeviceRule(vfioPath)
if err != nil {
return err
}
d := config.DeviceInfo{
ContainerPath: vfioPath,
DevType: string(c.Type),
Major: c.Major,
Minor: c.Minor,
ColdPlug: false,
}
device := s.devManager.FindDevice(&d)
s.devManager.RemoveDevice(device.DeviceID())
// We do not need to enter the network namespace to bind back the
// physical interface to host driver.
return bindNICToHost(endpoint)
} }
// isPhysicalIface checks if an interface is a physical device. // isPhysicalIface checks if an interface is a physical device.

View File

@ -42,9 +42,11 @@ func TestPhysicalEndpoint_HotDetach(t *testing.T) {
HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(), HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(),
} }
h := &mockHypervisor{} s := &Sandbox{
hypervisor: &mockHypervisor{},
}
err := v.HotDetach(context.Background(), h, true, "") err := v.HotDetach(context.Background(), s, true, "")
assert.Error(err) assert.Error(err)
} }

View File

@ -112,7 +112,7 @@ func (endpoint *TapEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
} }
// HotDetach for the tap endpoint uses hot pull device // HotDetach for the tap endpoint uses hot pull device
func (endpoint *TapEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *TapEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
networkLogger().Info("Hot detaching tap endpoint") networkLogger().Info("Hot detaching tap endpoint")
span, ctx := tapTrace(ctx, "HotDetach", endpoint) span, ctx := tapTrace(ctx, "HotDetach", endpoint)
@ -124,6 +124,7 @@ func (endpoint *TapEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsC
networkLogger().WithError(err).Warn("Error un-bridging tap ep") networkLogger().WithError(err).Warn("Error un-bridging tap ep")
} }
h := s.hypervisor
if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil { if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil {
networkLogger().WithError(err).Error("Error detach tap ep") networkLogger().WithError(err).Error("Error detach tap ep")
return err return err

View File

@ -123,7 +123,7 @@ func (endpoint *TuntapEndpoint) HotAttach(ctx context.Context, s *Sandbox) error
} }
// HotDetach for the tun/tap endpoint uses hot pull device // HotDetach for the tun/tap endpoint uses hot pull device
func (endpoint *TuntapEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *TuntapEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
networkLogger().Info("Hot detaching tun/tap endpoint") networkLogger().Info("Hot detaching tun/tap endpoint")
span, ctx := tuntapTrace(ctx, "HotDetach", endpoint) span, ctx := tuntapTrace(ctx, "HotDetach", endpoint)
@ -135,6 +135,7 @@ func (endpoint *TuntapEndpoint) HotDetach(ctx context.Context, h Hypervisor, net
networkLogger().WithError(err).Warn("Error un-bridging tun/tap ep") networkLogger().WithError(err).Warn("Error un-bridging tun/tap ep")
} }
h := s.hypervisor
if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil { if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil {
networkLogger().WithError(err).Error("Error detach tun/tap ep") networkLogger().WithError(err).Error("Error detach tun/tap ep")
return err return err

View File

@ -144,7 +144,7 @@ func (endpoint *VethEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
} }
// HotDetach for the veth endpoint uses hot pull device // HotDetach for the veth endpoint uses hot pull device
func (endpoint *VethEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *VethEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
if !netNsCreated { if !netNsCreated {
return nil return nil
} }
@ -158,6 +158,7 @@ func (endpoint *VethEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNs
networkLogger().WithError(err).Warn("Error un-bridging virtual ep") networkLogger().WithError(err).Warn("Error un-bridging virtual ep")
} }
h := s.hypervisor
if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil { if _, err := h.HotplugRemoveDevice(ctx, endpoint, NetDev); err != nil {
networkLogger().WithError(err).Error("Error detach virtual ep") networkLogger().WithError(err).Error("Error detach virtual ep")
return err return err

View File

@ -112,7 +112,7 @@ func (endpoint *VhostUserEndpoint) HotAttach(ctx context.Context, s *Sandbox) er
} }
// HotDetach for vhostuser endpoint not supported yet // HotDetach for vhostuser endpoint not supported yet
func (endpoint *VhostUserEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error { func (endpoint *VhostUserEndpoint) HotDetach(ctx context.Context, s *Sandbox, netNsCreated bool, netNsPath string) error {
return fmt.Errorf("VhostUserEndpoint does not support Hot detach") return fmt.Errorf("VhostUserEndpoint does not support Hot detach")
} }

View File

@ -113,9 +113,11 @@ func TestVhostUserEndpoint_HotDetach(t *testing.T) {
EndpointType: VhostUserEndpointType, EndpointType: VhostUserEndpointType,
} }
h := &mockHypervisor{} s := &Sandbox{
hypervisor: &mockHypervisor{},
}
err := v.HotDetach(context.Background(), h, true, "") err := v.HotDetach(context.Background(), s, true, "")
assert.Error(err) assert.Error(err)
} }