network: Implement hotplug for physical endpoints

Enable physical network interfaces to be hotplugged.
For this, we need to change the signature of the HotAttach method
to make use of Sandbox instead of Hypervisor. Similar approach was
followed for Attach method, but this change was overlooked for
HotAttach.
The signature change is required in order to make use of
device manager and receiver for physical network
enpoints.

Fixes: #8405

Signed-off-by: Archana Shinde <archana.m.shinde@intel.com>
This commit is contained in:
Archana Shinde
2023-12-06 12:09:56 -08:00
parent 2fef4bc844
commit 1e304e6307
12 changed files with 48 additions and 15 deletions

View File

@@ -26,7 +26,7 @@ type Endpoint interface {
SetPciPath(vcTypes.PciPath) SetPciPath(vcTypes.PciPath)
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(ctx context.Context, h Hypervisor) error HotAttach(context.Context, *Sandbox) error
HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error
save() persistapi.NetworkEndpoint save() persistapi.NetworkEndpoint

View File

@@ -125,10 +125,11 @@ func (endpoint *IPVlanEndpoint) Detach(ctx context.Context, netNsCreated bool, n
}) })
} }
func (endpoint *IPVlanEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *IPVlanEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
span, ctx := ipvlanTrace(ctx, "HotAttach", endpoint) span, ctx := ipvlanTrace(ctx, "HotAttach", endpoint)
defer span.End() defer span.End()
h := s.hypervisor
if err := xConnectVMNetwork(ctx, endpoint, h); err != nil { if err := xConnectVMNetwork(ctx, endpoint, h); err != nil {
networkLogger().WithError(err).Error("Error bridging ipvlan ep") networkLogger().WithError(err).Error("Error bridging ipvlan ep")
return err return err

View File

@@ -122,10 +122,11 @@ func (endpoint *MacvlanEndpoint) Detach(ctx context.Context, netNsCreated bool,
}) })
} }
func (endpoint *MacvlanEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *MacvlanEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
span, ctx := macvlanTrace(ctx, "HotAttach", endpoint) span, ctx := macvlanTrace(ctx, "HotAttach", endpoint)
defer span.End() defer span.End()
h := s.hypervisor
if err := xConnectVMNetwork(ctx, endpoint, h); err != nil { if err := xConnectVMNetwork(ctx, endpoint, h); err != nil {
networkLogger().WithError(err).Error("Error bridging macvlan ep") networkLogger().WithError(err).Error("Error bridging macvlan ep")
return err return err

View File

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

View File

@@ -202,7 +202,7 @@ func (n *LinuxNetwork) addSingleEndpoint(ctx context.Context, s *Sandbox, netInf
networkLogger().WithField("endpoint-type", endpoint.Type()).WithField("hotplug", hotplug).Info("Attaching endpoint") networkLogger().WithField("endpoint-type", endpoint.Type()).WithField("hotplug", hotplug).Info("Attaching endpoint")
if hotplug { if hotplug {
if err := endpoint.HotAttach(ctx, s.hypervisor); err != nil { if err := endpoint.HotAttach(ctx, s); err != nil {
return nil, err return nil, err
} }
} else { } else {

View File

@@ -123,8 +123,32 @@ func (endpoint *PhysicalEndpoint) Detach(ctx context.Context, netNsCreated bool,
} }
// HotAttach for physical endpoint not supported yet // HotAttach for physical endpoint not supported yet
func (endpoint *PhysicalEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *PhysicalEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
return fmt.Errorf("PhysicalEndpoint does not support Hot attach") span, ctx := physicalTrace(ctx, "HotAttach", endpoint)
defer span.End()
// Unbind physical interface from host driver and bind to vfio
// so that it can be passed to the hypervisor.
vfioPath, err := bindNICToVFIO(endpoint)
if 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,
}
_, err = s.AddDevice(ctx, d)
return err
} }
// HotDetach for physical endpoint not supported yet // HotDetach for physical endpoint not supported yet

View File

@@ -27,9 +27,11 @@ func TestPhysicalEndpoint_HotAttach(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.HotAttach(context.Background(), h) err := v.HotAttach(context.Background(), s)
assert.Error(err) assert.Error(err)
} }

View File

@@ -92,12 +92,13 @@ func (endpoint *TapEndpoint) Detach(ctx context.Context, netNsCreated bool, netN
} }
// HotAttach for the tap endpoint uses hot plug device // HotAttach for the tap endpoint uses hot plug device
func (endpoint *TapEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *TapEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
networkLogger().Info("Hot attaching tap endpoint") networkLogger().Info("Hot attaching tap endpoint")
span, ctx := tapTrace(ctx, "HotAttach", endpoint) span, ctx := tapTrace(ctx, "HotAttach", endpoint)
defer span.End() defer span.End()
h := s.hypervisor
if err := tapNetwork(endpoint, h.HypervisorConfig().NumVCPUs(), h.HypervisorConfig().DisableVhostNet); err != nil { if err := tapNetwork(endpoint, h.HypervisorConfig().NumVCPUs(), h.HypervisorConfig().DisableVhostNet); err != nil {
networkLogger().WithError(err).Error("Error bridging tap ep") networkLogger().WithError(err).Error("Error bridging tap ep")
return err return err

View File

@@ -103,12 +103,13 @@ func (endpoint *TuntapEndpoint) Detach(ctx context.Context, netNsCreated bool, n
} }
// HotAttach for the tun/tap endpoint uses hot plug device // HotAttach for the tun/tap endpoint uses hot plug device
func (endpoint *TuntapEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *TuntapEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
networkLogger().Info("Hot attaching tun/tap endpoint") networkLogger().Info("Hot attaching tun/tap endpoint")
span, ctx := tuntapTrace(ctx, "HotAttach", endpoint) span, ctx := tuntapTrace(ctx, "HotAttach", endpoint)
defer span.End() defer span.End()
h := s.hypervisor
if err := tuntapNetwork(endpoint, h.HypervisorConfig().NumVCPUs(), h.HypervisorConfig().DisableVhostNet); err != nil { if err := tuntapNetwork(endpoint, h.HypervisorConfig().NumVCPUs(), h.HypervisorConfig().DisableVhostNet); err != nil {
networkLogger().WithError(err).Error("Error bridging tun/tap ep") networkLogger().WithError(err).Error("Error bridging tun/tap ep")
return err return err

View File

@@ -126,10 +126,11 @@ func (endpoint *VethEndpoint) Detach(ctx context.Context, netNsCreated bool, net
} }
// HotAttach for the veth endpoint uses hot plug device // HotAttach for the veth endpoint uses hot plug device
func (endpoint *VethEndpoint) HotAttach(ctx context.Context, h Hypervisor) error { func (endpoint *VethEndpoint) HotAttach(ctx context.Context, s *Sandbox) error {
span, ctx := vethTrace(ctx, "HotAttach", endpoint) span, ctx := vethTrace(ctx, "HotAttach", endpoint)
defer span.End() defer span.End()
h := s.hypervisor
if err := xConnectVMNetwork(ctx, endpoint, h); err != nil { if err := xConnectVMNetwork(ctx, endpoint, h); err != nil {
networkLogger().WithError(err).Error("Error bridging virtual ep") networkLogger().WithError(err).Error("Error bridging virtual ep")
return err return err

View File

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

View File

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