Skip to content

Commit

Permalink
add vNUMA validation function
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim An <maksiman@microsoft.com>
  • Loading branch information
anmaxvl committed Jun 18, 2024
1 parent 8557508 commit d875d84
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
2 changes: 2 additions & 0 deletions internal/hcs/schema2/numa_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

package hcsschema

const InvalidPhysicalNodeNumber = 0xFF

type NumaNode struct {
VirtualNodeIndex uint32 `json:"VirtualNodeIndex,omitempty"`
PhysicalNodeIndex uint32 `json:"PhysicalNodeIndex,omitempty"`
Expand Down
81 changes: 81 additions & 0 deletions internal/uvm/create_wcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,78 @@ func (uvm *UtilityVM) startExternalGcsListener(ctx context.Context) error {
return nil
}

func validateNumaSettings(
vNuma []hcsschema.NumaSetting,
vmMemoryType hcsschema.MemoryBackingType,
vmMemoryInMb uint64,
vmProcessors uint32,
) error {
if len(vNuma) == 0 {
return errors.New("no vNUMA settings provided")
}

var hasComputelessNode, hasMemorylessNode bool
var hasVirtuallyBackedNode, hasPhysicallyBackedNode bool
var totalInitialMemoryInMb uint64
var totalProcessorCount uint32
hasInvalidPhysicalNode := vNuma[0].PhysicalNodeNumber == hcsschema.InvalidPhysicalNodeNumber

for _, topology := range vNuma {
if topology.CountOfProcessors == 0 && !hasComputelessNode {
hasComputelessNode = true
}
if topology.CountOfMemoryBlocks == 0 && !hasMemorylessNode {
hasMemorylessNode = true
}
if (topology.PhysicalNodeNumber == 0xFF) != hasInvalidPhysicalNode {
return errors.New("either all or none of the vNUMA nodes should have invalid physical node")
}
totalInitialMemoryInMb += topology.CountOfMemoryBlocks
totalProcessorCount += topology.CountOfProcessors
if topology.MemoryBackingType != "" && (topology.MemoryBackingType != hcsschema.MemoryBackingType_PHYSICAL && topology.MemoryBackingType != hcsschema.MemoryBackingType_VIRTUAL) {
return errors.New("invalid memory backing type")
}
if topology.MemoryBackingType == hcsschema.MemoryBackingType_VIRTUAL {
hasVirtuallyBackedNode = true
}
if topology.MemoryBackingType == hcsschema.MemoryBackingType_PHYSICAL {
hasPhysicallyBackedNode = true
}
}

hasMemorylessNode = hasMemorylessNode && totalInitialMemoryInMb != 0
// TODO: add OS version check, since depending on the OS version/VM SKU, we'd need different
// minimal OS requirements (either IRON or NICKEL).
hasComputelessNode = hasComputelessNode && totalProcessorCount != 0

if hasMemorylessNode {
return errors.New("all vNUMA nodes should have memory")
}

if (totalInitialMemoryInMb == 0) != (totalProcessorCount == 0) {
return errors.New("partial resource allocation is not supported")
}

if totalInitialMemoryInMb == 0 && hasInvalidPhysicalNode {
return errors.New("cannot have empty topology")
}

if vmMemoryType == hcsschema.MemoryBackingType_HYBRID {
if !hasVirtuallyBackedNode || !hasPhysicallyBackedNode {
return errors.New("hybrid memory backing type UVM requires vNUMA nodes with both virtual and physical memory backing types")
}
}

if totalProcessorCount != 0 && totalProcessorCount != vmProcessors {
return errors.New("processor count across vNUMA nodes doesn't match the total UVM processor count")
}

if totalInitialMemoryInMb != 0 && totalInitialMemoryInMb != vmMemoryInMb {
return errors.New("memory across vNUMA nodes don't match the total UVM memory")
}
return nil
}

func prepareVNUMATopology(vNodes, pNodes, vNumaProcs []uint32, vNumaMem []uint64) *hcsschema.Numa {
vNodesCount := len(vNodes)
if vNodesCount == 0 {
Expand Down Expand Up @@ -211,6 +283,15 @@ func prepareConfigDoc(ctx context.Context, uvm *UtilityVM, opts *OptionsWCOW) (*
opts.NumaProcessorCount,
opts.NumaMemoryBlocksCount,
)
if err := validateNumaSettings(
numa.Settings,
// for now support only physically backed VMs
hcsschema.MemoryBackingType_PHYSICAL,
memorySizeInMB,
uint32(uvm.processorCount),
); err != nil {
return nil, err
}
} else if opts.MaxProcessorsPerNumaNode > 0 {
numaProcessors = &hcsschema.NumaProcessors{
CountPerNode: hcsschema.Range{
Expand Down

0 comments on commit d875d84

Please sign in to comment.