mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-17 06:14:26 +01:00
First of all, this is a controversial piece, and I know that. In this commit we're trying to make a less greedy approach regards the amount of vCPUs we allocate for the VMM, which will be advantageous mainly when using the `static_sandbox_resource_mgmt` feature, which is used by the confidential guests. The current approach we have basically does: * Gets the amount of vCPUs set in the config (an integer) * Gets the amount of vCPUs set as limit (an integer) * Sum those up * Starts / Updates the VMM to use that total amount of vCPUs The fact we're dealing with integers is logical, as we cannot request 500m vCPUs to the VMMs. However, it leads us to, in several cases, be wasting one vCPU. Let's take the example that we know the VMM requires 500m vCPUs to be running, and the workload sets 250m vCPUs as a resource limit. In that case, we'd do: * Gets the amount of vCPUs set in the config: 1 * Gets the amount of vCPUs set as limit: ceil(0.25) * 1 + ceil(0.25) = 1 + 1 = 2 vCPUs * Starts / Updates the VMM to use 2 vCPUs With the logic changed here, what we're doing is considering everything as float till just before we start / update the VMM. So, the flow describe above would be: * Gets the amount of vCPUs set in the config: 0.5 * Gets the amount of vCPUs set as limit: 0.25 * ceil(0.5 + 0.25) = 1 vCPUs * Starts / Updates the VMM to use 1 vCPUs In the way I've written this patch we introduce zero regressions, as the default values set are still the same, and those will only be changed for the TEE use cases (although I can see firecracker, or any other user of `static_sandbox_resource_mgmt=true` taking advantage of this). There's, though, an implicit assumption in this patch that we'd need to make explicit, and that's that the default_vcpus / default_memory is the amount of vcpus / memory required by the VMM, and absolutely nothing else. Also, the amount set there should be reflected in the podOverhead for the specific runtime class. One other possible approach, which I am not that much in favour of taking as I think it's **less clear**, is that we could actually get the podOverhead amount, subtract it from the default_vcpus (treating the result as a float), then sum up what the user set as limit (as a float), and finally ceil the result. It could work, but IMHO this is **less clear**, and **less explicit** on what we're actually doing, and how the default_vcpus / default_memory should be used. Fixes: #6909 Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@intel.com> Signed-off-by: Christophe de Dinechin <dinechin@redhat.com>
154 lines
4.3 KiB
Go
154 lines
4.3 KiB
Go
//go:build linux
|
|
|
|
// Copyright (c) 2018 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package virtcontainers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
|
|
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
|
|
)
|
|
|
|
var macvtapTrace = getNetworkTrace(MacvtapEndpointType)
|
|
|
|
// MacvtapEndpoint represents a macvtap endpoint
|
|
type MacvtapEndpoint struct {
|
|
EndpointProperties NetworkInfo
|
|
EndpointType EndpointType
|
|
VMFds []*os.File
|
|
VhostFds []*os.File
|
|
PCIPath vcTypes.PciPath
|
|
RxRateLimiter bool
|
|
TxRateLimiter bool
|
|
}
|
|
|
|
func createMacvtapNetworkEndpoint(netInfo NetworkInfo) (*MacvtapEndpoint, error) {
|
|
endpoint := &MacvtapEndpoint{
|
|
EndpointType: MacvtapEndpointType,
|
|
EndpointProperties: netInfo,
|
|
}
|
|
|
|
return endpoint, nil
|
|
}
|
|
|
|
// Properties returns the properties of the macvtap interface.
|
|
func (endpoint *MacvtapEndpoint) Properties() NetworkInfo {
|
|
return endpoint.EndpointProperties
|
|
}
|
|
|
|
// HardwareAddr returns the mac address of the macvtap network interface.
|
|
func (endpoint *MacvtapEndpoint) HardwareAddr() string {
|
|
return endpoint.EndpointProperties.Iface.HardwareAddr.String()
|
|
}
|
|
|
|
// Name returns name of the macvtap interface.
|
|
func (endpoint *MacvtapEndpoint) Name() string {
|
|
return endpoint.EndpointProperties.Iface.Name
|
|
}
|
|
|
|
// Type indentifies the endpoint as a macvtap endpoint.
|
|
func (endpoint *MacvtapEndpoint) Type() EndpointType {
|
|
return endpoint.EndpointType
|
|
}
|
|
|
|
// SetProperties sets the properties of the macvtap endpoint.
|
|
func (endpoint *MacvtapEndpoint) SetProperties(properties NetworkInfo) {
|
|
endpoint.EndpointProperties = properties
|
|
}
|
|
|
|
// Attach for macvtap endpoint passes macvtap device to the hypervisor.
|
|
func (endpoint *MacvtapEndpoint) Attach(ctx context.Context, s *Sandbox) error {
|
|
var err error
|
|
span, ctx := macvtapTrace(ctx, "Attach", endpoint)
|
|
defer span.End()
|
|
|
|
h := s.hypervisor
|
|
|
|
endpoint.VMFds, err = createMacvtapFds(endpoint.EndpointProperties.Iface.Index, int(h.HypervisorConfig().NumVCPUs()))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not setup macvtap fds %s: %s", endpoint.EndpointProperties.Iface.Name, err)
|
|
}
|
|
|
|
if !h.HypervisorConfig().DisableVhostNet {
|
|
vhostFds, err := createVhostFds(int(h.HypervisorConfig().NumVCPUs()))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not setup vhost fds %s : %s", endpoint.EndpointProperties.Iface.Name, err)
|
|
}
|
|
endpoint.VhostFds = vhostFds
|
|
}
|
|
|
|
return h.AddDevice(ctx, endpoint, NetDev)
|
|
}
|
|
|
|
// Detach for macvtap endpoint does nothing.
|
|
func (endpoint *MacvtapEndpoint) Detach(ctx context.Context, netNsCreated bool, netNsPath string) error {
|
|
return nil
|
|
}
|
|
|
|
// HotAttach for macvtap endpoint not supported yet
|
|
func (endpoint *MacvtapEndpoint) HotAttach(ctx context.Context, h Hypervisor) error {
|
|
return fmt.Errorf("MacvtapEndpoint does not support Hot attach")
|
|
}
|
|
|
|
// HotDetach for macvtap endpoint not supported yet
|
|
func (endpoint *MacvtapEndpoint) HotDetach(ctx context.Context, h Hypervisor, netNsCreated bool, netNsPath string) error {
|
|
return fmt.Errorf("MacvtapEndpoint does not support Hot detach")
|
|
}
|
|
|
|
// PciPath returns the PCI path of the endpoint.
|
|
func (endpoint *MacvtapEndpoint) PciPath() vcTypes.PciPath {
|
|
return endpoint.PCIPath
|
|
}
|
|
|
|
// SetPciPath sets the PCI path of the endpoint.
|
|
func (endpoint *MacvtapEndpoint) SetPciPath(pciPath vcTypes.PciPath) {
|
|
endpoint.PCIPath = pciPath
|
|
}
|
|
|
|
// NetworkPair returns the network pair of the endpoint.
|
|
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
|
return nil
|
|
}
|
|
|
|
func (endpoint *MacvtapEndpoint) save() persistapi.NetworkEndpoint {
|
|
return persistapi.NetworkEndpoint{
|
|
Type: string(endpoint.Type()),
|
|
|
|
Macvtap: &persistapi.MacvtapEndpoint{
|
|
PCIPath: endpoint.PCIPath,
|
|
},
|
|
}
|
|
}
|
|
func (endpoint *MacvtapEndpoint) load(s persistapi.NetworkEndpoint) {
|
|
endpoint.EndpointType = MacvtapEndpointType
|
|
|
|
if s.Macvtap != nil {
|
|
endpoint.PCIPath = s.Macvtap.PCIPath
|
|
}
|
|
}
|
|
|
|
func (endpoint *MacvtapEndpoint) GetRxRateLimiter() bool {
|
|
return endpoint.RxRateLimiter
|
|
}
|
|
|
|
func (endpoint *MacvtapEndpoint) SetRxRateLimiter() error {
|
|
endpoint.RxRateLimiter = true
|
|
return nil
|
|
}
|
|
|
|
func (endpoint *MacvtapEndpoint) GetTxRateLimiter() bool {
|
|
return endpoint.TxRateLimiter
|
|
}
|
|
|
|
func (endpoint *MacvtapEndpoint) SetTxRateLimiter() error {
|
|
endpoint.TxRateLimiter = true
|
|
return nil
|
|
}
|