1c1e9ed6dSMichal Berger#!/usr/bin/env bash 2c1e9ed6dSMichal Berger# SPDX-License-Identifier: BSD-3-Clause 3c1e9ed6dSMichal Berger# Copyright (C) 2022 Intel Corporation. 4c1e9ed6dSMichal Berger# All rights reserved. 5c1e9ed6dSMichal Berger 6c1e9ed6dSMichal Bergercurdir=$(readlink -f "$(dirname "$0")") 7c1e9ed6dSMichal Bergerrootdir=$(readlink -f "$curdir/../../../") 8c1e9ed6dSMichal Berger 948945e3dSMichal Bergershopt -s nullglob extglob 1048945e3dSMichal Berger 11c1e9ed6dSMichal Bergersource "$rootdir/scripts/common.sh" 12c1e9ed6dSMichal Bergersource "$rootdir/test/scheduler/common.sh" 13c1e9ed6dSMichal Berger 14c1e9ed6dSMichal Bergerget_auto_cfg() { 15cca7c14aSMichal Berger local vm_cpus vm_node vm vms 16c1e9ed6dSMichal Berger local cpu node nodes_idxs node_idx 17c1e9ed6dSMichal Berger local nvmes nvme nvme_idx nvme_diff nvmes_per_node 18c1e9ed6dSMichal Berger local vm_diff aligned_number_of_vms=0 19c1e9ed6dSMichal Berger local diff iter 20c1e9ed6dSMichal Berger 21c1e9ed6dSMichal Berger local -g auto_cpu_map=() auto_disk_map=() spdk=() 22c1e9ed6dSMichal Berger 23c1e9ed6dSMichal Berger map_cpus 24c1e9ed6dSMichal Berger get_nvme_numa_map 25c1e9ed6dSMichal Berger 26c1e9ed6dSMichal Berger nodes_idxs=("${!nodes[@]}") 27c1e9ed6dSMichal Berger 28c1e9ed6dSMichal Berger # Construct initial NUMA-aware setup by pinning VM to given nvme's node. First run is meant 29c1e9ed6dSMichal Berger # to pin enough number of VMs (as per vm_count) to match the number of available nvme ctrls. 30c1e9ed6dSMichal Berger vm=0 31c1e9ed6dSMichal Berger for node in "${nodes_idxs[@]}"; do 32c1e9ed6dSMichal Berger nvmes=(${!nvme_numa_map[node]}) 33c1e9ed6dSMichal Berger for ((nvme_idx = 0; nvme_idx < ${#nvmes[@]} && vm < vm_count; vm++, nvme_idx++)); do 34c1e9ed6dSMichal Berger eval "vm${vm}_node=$node" 35c1e9ed6dSMichal Berger done 36c1e9ed6dSMichal Berger nvmes_per_node[node]=${#nvmes[@]} 37c1e9ed6dSMichal Berger done 38c1e9ed6dSMichal Berger 39c1e9ed6dSMichal Berger vm_diff=$((vm_count - vm)) 40c1e9ed6dSMichal Berger 41c1e9ed6dSMichal Berger # Align extra number of VMs in case nvme ctrls are not distributed evenly across the existing 42c1e9ed6dSMichal Berger # NUMA nodes. 43c1e9ed6dSMichal Berger # FIXME: This is targeted for systems with only 2 NUMA nodes. Technically, kernel supports 44c1e9ed6dSMichal Berger # more than that - it's possible to achieve setups with > 2 NUMA nodes under virtual env 45c1e9ed6dSMichal Berger # for instance. Should this be of any concern? 46c1e9ed6dSMichal Berger if ((nvmes_per_node[0] < nvmes_per_node[1])); then 47c1e9ed6dSMichal Berger nvme_diff=$((nvmes_per_node[1] - nvmes_per_node[0])) 48c1e9ed6dSMichal Berger elif ((nvmes_per_node[0] > nvmes_per_node[1])); then 49c1e9ed6dSMichal Berger nvme_diff=$((nvmes_per_node[0] - nvmes_per_node[1])) 50c1e9ed6dSMichal Berger else 51c1e9ed6dSMichal Berger nvme_diff=0 52c1e9ed6dSMichal Berger fi 53c1e9ed6dSMichal Berger 54c1e9ed6dSMichal Berger diff=$((vm_diff + nvme_diff)) 55c1e9ed6dSMichal Berger 56c1e9ed6dSMichal Berger if ((diff % 2 == 0)); then 57c1e9ed6dSMichal Berger aligned_number_of_vms=$((diff / ${#nodes_idxs[@]})) 58c1e9ed6dSMichal Berger fi 59c1e9ed6dSMichal Berger 60c1e9ed6dSMichal Berger # Second run distributes extra VMs across existing NUMA nodes. In case we can distribute even 61c1e9ed6dSMichal Berger # number of extra VMs (as per vm_count) then simply assign them in bulk. In case there's an 62c1e9ed6dSMichal Berger # odd number, do some simple rr balancing where we assign them one by one - first to node0, 63c1e9ed6dSMichal Berger # second to node1, third to node0, etc. 64c1e9ed6dSMichal Berger if ((aligned_number_of_vms)); then 65c1e9ed6dSMichal Berger for node in "${nodes_idxs[@]}"; do 66c1e9ed6dSMichal Berger for ((iter = 0; iter < aligned_number_of_vms && vm < vm_count; iter++, vm++)); do 67c1e9ed6dSMichal Berger eval "vm${vm}_node=$node" 68c1e9ed6dSMichal Berger done 69c1e9ed6dSMichal Berger done 70c1e9ed6dSMichal Berger else 71c1e9ed6dSMichal Berger while ((vm < vm_count)); do 72c1e9ed6dSMichal Berger for node in "${nodes_idxs[@]}"; do 73c1e9ed6dSMichal Berger eval "vm${vm}_node=$node" 74c1e9ed6dSMichal Berger ((++vm)) 75c1e9ed6dSMichal Berger done 76c1e9ed6dSMichal Berger done 77c1e9ed6dSMichal Berger fi 78c1e9ed6dSMichal Berger 79c1e9ed6dSMichal Berger local -g vm_numa_map=() 80c1e9ed6dSMichal Berger for ((vm = 0; vm < vm_count; vm++)); do 81c1e9ed6dSMichal Berger # Load balance the cpus across available numa nodes based on the pinning 82c1e9ed6dSMichal Berger # done prior. If there are no cpus left under selected node, iterate over 83c1e9ed6dSMichal Berger # all available nodes. If no cpus are left, fail. We don't allow to mix 84c1e9ed6dSMichal Berger # cpus from different nodes for the sake of the performance. 85c1e9ed6dSMichal Berger node_idx=0 node_idx_perc=0 86b86184c5SMichal Berger eval "vm_node=\${VM${vm}_NODE:-\$vm${vm}_node}" 87c1e9ed6dSMichal Berger 88c1e9ed6dSMichal Berger local -n node_cpus=node_${vm_node}_cpu 89c1e9ed6dSMichal Berger local -n vm_nodes=node_${vm_node}_vm 90c1e9ed6dSMichal Berger 91c1e9ed6dSMichal Berger vm_numa_map[vm_node]="node_${vm_node}_vm[@]" 92c1e9ed6dSMichal Berger 93c1e9ed6dSMichal Berger while ((${#node_cpus[@]} < vm_cpu_num && node_idx < ${#nodes_idxs[@]})); do 94c1e9ed6dSMichal Berger vm_node=${nodes_idxs[node_idx]} 95c1e9ed6dSMichal Berger local -n node_cpus=node_${nodes_idxs[node_idx++]}_cpu 96c1e9ed6dSMichal Berger done 97c1e9ed6dSMichal Berger 98c1e9ed6dSMichal Berger if ((${#node_cpus[@]} < vm_cpu_num)); then 99c1e9ed6dSMichal Berger printf 'Not enough CPUs available for VM %u (CPUs: %u, Nodes: %u, CPUs per VM: %u)\n' \ 100c1e9ed6dSMichal Berger "$vm" "${#cpus[@]}" "${#nodes_idxs[@]}" "$vm_cpu_num" >&2 101c1e9ed6dSMichal Berger return 1 102c1e9ed6dSMichal Berger fi 103c1e9ed6dSMichal Berger 104c1e9ed6dSMichal Berger # Normalize indexes 105c1e9ed6dSMichal Berger node_cpus=("${node_cpus[@]}") 106c1e9ed6dSMichal Berger 107c1e9ed6dSMichal Berger vm_cpus=("${node_cpus[@]::vm_cpu_num}") 108c1e9ed6dSMichal Berger node_cpus=("${node_cpus[@]:vm_cpu_num}") 109c1e9ed6dSMichal Berger 110c1e9ed6dSMichal Berger auto_cpu_map+=("$( 111c1e9ed6dSMichal Berger cat <<- CPU_VM 112c1e9ed6dSMichal Berger VM_${vm}_qemu_mask=$( 113c1e9ed6dSMichal Berger IFS="," 114c1e9ed6dSMichal Berger echo "${vm_cpus[*]}" 115c1e9ed6dSMichal Berger ) 116c1e9ed6dSMichal Berger VM_${vm}_qemu_numa_node=$vm_node 117c1e9ed6dSMichal Berger CPU_VM 118c1e9ed6dSMichal Berger )") 119c1e9ed6dSMichal Berger 120c1e9ed6dSMichal Berger # Save map of each VM->NUMA node to be able to construct a disk map in later steps. 121c1e9ed6dSMichal Berger vm_nodes+=("$vm") 122c1e9ed6dSMichal Berger done 123c1e9ed6dSMichal Berger 124c1e9ed6dSMichal Berger # auto_cpu_map is ready, all requested VMs should be balanced across all NUMA nodes 125c1e9ed6dSMichal Berger # making sure each nvme drive will be bound to at least 1 VM placed on the 126c1e9ed6dSMichal Berger # corresponding NUMA node. Now, construct disk_cfg and assign VMs, with proper 127c1e9ed6dSMichal Berger # split value, to each nvme - extra VMs will be added to nvme drives in their 128c1e9ed6dSMichal Berger # bus order. 129c1e9ed6dSMichal Berger local -A nvme_vm_map=() 130cca7c14aSMichal Berger local iter nvmes_no=0 vms_no=0 _vms_per_nvme 131c1e9ed6dSMichal Berger for node in "${nodes_idxs[@]}"; do 132c1e9ed6dSMichal Berger if [[ ! -v nvme_numa_map[node] ]]; then 133c1e9ed6dSMichal Berger # There are no drives available on that node, skip it 134c1e9ed6dSMichal Berger continue 135c1e9ed6dSMichal Berger fi 136c1e9ed6dSMichal Berger nvmes=(${!nvme_numa_map[node]}) nvmes_no=${#nvmes[@]} 137c1e9ed6dSMichal Berger vms=(${!vm_numa_map[node]}) vms_no=${#vms[@]} 138c1e9ed6dSMichal Berger for ((iter = 0; iter <= (vms_no - nvmes_no <= 0 ? 1 : vms_no - nvmes_no); iter++)); do 139c1e9ed6dSMichal Berger for nvme in "${nvmes[@]}"; do 140cca7c14aSMichal Berger _vms_per_nvme=0 141c1e9ed6dSMichal Berger if ((${#vms[@]} == 0)); then 142c1e9ed6dSMichal Berger # No VMs on given node or they have been exhausted - skip all remaining drives. 143c1e9ed6dSMichal Berger continue 3 144c1e9ed6dSMichal Berger fi 145c1e9ed6dSMichal Berger nvme_vm_map["$nvme"]="_${nvme//[:.]/_}_[@]" 146c1e9ed6dSMichal Berger local -n nvme_vms=_${nvme//[:.]/_}_ 147cca7c14aSMichal Berger while ((++_vms_per_nvme <= vms_per_nvme)); do 148c1e9ed6dSMichal Berger nvme_vms+=("${vms[0]}") vms=("${vms[@]:1}") 149c1e9ed6dSMichal Berger done 150c1e9ed6dSMichal Berger done 151c1e9ed6dSMichal Berger done 152cca7c14aSMichal Berger done 153c1e9ed6dSMichal Berger 154c1e9ed6dSMichal Berger local sorted_nvmes=() 155c1e9ed6dSMichal Berger sorted_nvmes=($(printf '%s\n' "${!nvme_vm_map[@]}" | sort)) 156c1e9ed6dSMichal Berger for nvme in "${!sorted_nvmes[@]}"; do 157c1e9ed6dSMichal Berger vms=(${!nvme_vm_map["${sorted_nvmes[nvme]}"]}) 158c1e9ed6dSMichal Berger auto_disk_map+=("${sorted_nvmes[nvme]},Nvme$((nvme++)),${#vms[*]},${vms[*]}") 159c1e9ed6dSMichal Berger done 160c1e9ed6dSMichal Berger 161c1e9ed6dSMichal Berger get_spdk_cpus || return 1 162c1e9ed6dSMichal Berger 163c1e9ed6dSMichal Berger auto_cpu_map+=("vhost_0_reactor_mask=[$( 164c1e9ed6dSMichal Berger IFS="," 165c1e9ed6dSMichal Berger echo "${spdk[*]}" 166c1e9ed6dSMichal Berger )]") 167*161ef3f5SMichal Berger auto_cpu_map+=("vhost_0_main_core=${spdk[0]}") 168c1e9ed6dSMichal Berger} 169c1e9ed6dSMichal Berger 170c1e9ed6dSMichal Bergerget_nvme_numa_map() { 171c1e9ed6dSMichal Berger local nvmes nvme node 172c1e9ed6dSMichal Berger local -g nvme_numa_map=() 173c1e9ed6dSMichal Berger 174c1e9ed6dSMichal Berger cache_pci_bus 175c1e9ed6dSMichal Berger 176c1e9ed6dSMichal Berger for nvme in ${pci_bus_cache[0x010802]}; do 177c1e9ed6dSMichal Berger node=$(< "/sys/bus/pci/devices/$nvme/numa_node") 178c1e9ed6dSMichal Berger nvme_numa_map[node]="node_${node}_nvme[@]" 179c1e9ed6dSMichal Berger local -n node_nvmes=node_${node}_nvme 180c1e9ed6dSMichal Berger node_nvmes+=("$nvme") 181c1e9ed6dSMichal Berger done 182c1e9ed6dSMichal Berger} 183c1e9ed6dSMichal Berger 184c1e9ed6dSMichal Bergerget_spdk_cpus() { 185c1e9ed6dSMichal Berger local -g spdk=() 186c1e9ed6dSMichal Berger local node vms perc 187c1e9ed6dSMichal Berger local cpus_per_node cpus_exhausted=() cpus_remained=() 188c1e9ed6dSMichal Berger 189c1e9ed6dSMichal Berger if [[ -z $spdk_cpu_num ]]; then 190c1e9ed6dSMichal Berger spdk=(0) 191c1e9ed6dSMichal Berger return 0 192c1e9ed6dSMichal Berger fi 193c1e9ed6dSMichal Berger 194c1e9ed6dSMichal Berger if [[ -n $spdk_cpu_list ]]; then 195c1e9ed6dSMichal Berger spdk=($(parse_cpu_list <(echo "$spdk_cpu_list"))) 196c1e9ed6dSMichal Berger return 0 197c1e9ed6dSMichal Berger fi 198c1e9ed6dSMichal Berger 199c1e9ed6dSMichal Berger # Start allocating from NUMA node with greater number of pinned VMs. 200c1e9ed6dSMichal Berger node_sort=($(for node in "${!vm_numa_map[@]}"; do 201c1e9ed6dSMichal Berger vms=(${!vm_numa_map[node]}) 202c1e9ed6dSMichal Berger echo "${#vms[@]}:$node" 203c1e9ed6dSMichal Berger done | sort -rn)) 204c1e9ed6dSMichal Berger 205c1e9ed6dSMichal Berger for _node in "${node_sort[@]}"; do 206c1e9ed6dSMichal Berger node=${_node#*:} vms=${_node%:*} 207c1e9ed6dSMichal Berger local -n node_all_cpus=node_${node}_cpu 208c1e9ed6dSMichal Berger perc=$((vms * 100 / vm_count)) 209c1e9ed6dSMichal Berger cpus_per_node=$((spdk_cpu_num * perc / 100)) 210c1e9ed6dSMichal Berger cpus_per_node=$((cpus_per_node == 0 ? 1 : cpus_per_node)) 211c1e9ed6dSMichal Berger 212c1e9ed6dSMichal Berger if ((${#node_all_cpus[@]} == 0)); then 213c1e9ed6dSMichal Berger printf 'No CPUs left to allocate for SPDK on node%u. Need %u CPUs\n' \ 214c1e9ed6dSMichal Berger "$node" "$cpus_per_node" >&2 215c1e9ed6dSMichal Berger 216c1e9ed6dSMichal Berger cpus_exhausted[node]=1 217c1e9ed6dSMichal Berger continue 218c1e9ed6dSMichal Berger fi 219c1e9ed6dSMichal Berger if ((${#node_all_cpus[@]} < cpus_per_node)); then 220c1e9ed6dSMichal Berger printf 'Not enough CPUs to allocate for SPDK on node%u. Need %u CPUs, getting %u\n' \ 221c1e9ed6dSMichal Berger "$node" "$cpus_per_node" "${#node_all_cpus[@]}" >&2 222c1e9ed6dSMichal Berger cpus_per_node=${#node_all_cpus[@]} 223c1e9ed6dSMichal Berger cpus_exhauseted[node]=1 224c1e9ed6dSMichal Berger fi 225c1e9ed6dSMichal Berger 226c1e9ed6dSMichal Berger spdk+=("${node_all_cpus[@]::cpus_per_node}") 227c1e9ed6dSMichal Berger node_all_cpus=("${node_all_cpus[@]:cpus_per_node}") 228c1e9ed6dSMichal Berger cpus_remained+=("${node_all_cpus[@]}") 229c1e9ed6dSMichal Berger done 230c1e9ed6dSMichal Berger 231c1e9ed6dSMichal Berger # If we didn't allocate the entire number of requested cpus in the initial run, 232c1e9ed6dSMichal Berger # adjust it by adding the remaining portion from the node having greater number 233c1e9ed6dSMichal Berger # of pinned VMs. 234c1e9ed6dSMichal Berger if ((${#spdk[@]} < spdk_cpu_num)); then 235c1e9ed6dSMichal Berger if [[ -n $ALIGN_FROM_ALL_NODES ]] && ((${#cpus_remained[@]} > 0)); then 236c1e9ed6dSMichal Berger printf 'Trying to get extra CPUs from all nodes\n' 237c1e9ed6dSMichal Berger local -n node_all_cpus=cpus_remained 238c1e9ed6dSMichal Berger else 239c1e9ed6dSMichal Berger node=${node_sort[0]#*:} 240c1e9ed6dSMichal Berger printf 'Trying to get extra CPUs from the dominant node%u to align: %u < %u\n' \ 241c1e9ed6dSMichal Berger "$node" "${#spdk[@]}" "$spdk_cpu_num" 242c1e9ed6dSMichal Berger if ((cpus_exhausted[node])); then 243c1e9ed6dSMichal Berger printf 'No CPUs available on node%u\n' "$node" 244c1e9ed6dSMichal Berger else 245c1e9ed6dSMichal Berger local -n node_all_cpus=node_${node}_cpu 246c1e9ed6dSMichal Berger fi 247c1e9ed6dSMichal Berger fi 248c1e9ed6dSMichal Berger spdk+=("${node_all_cpus[@]::spdk_cpu_num-${#spdk[@]}}") 249c1e9ed6dSMichal Berger fi >&2 250c1e9ed6dSMichal Berger if ((${#spdk[@]} != spdk_cpu_num)); then 251c1e9ed6dSMichal Berger printf 'Different number of SPDK CPUs allocated to meet the requirements: requested %u, got %u\n' \ 252c1e9ed6dSMichal Berger "$spdk_cpu_num" "${#spdk[@]}" 253c1e9ed6dSMichal Berger else 254c1e9ed6dSMichal Berger printf 'Requested number of SPDK CPUs allocated: %u\n' "$spdk_cpu_num" 255c1e9ed6dSMichal Berger fi >&2 256c1e9ed6dSMichal Berger} 257c1e9ed6dSMichal Berger 258c1e9ed6dSMichal Berger_p_disk_map() { 259c1e9ed6dSMichal Berger ((${#auto_disk_map[@]} > 0)) || return 0 260c1e9ed6dSMichal Berger printf '%s\n' "${auto_disk_map[@]}" 261c1e9ed6dSMichal Berger} 262c1e9ed6dSMichal Berger 263c1e9ed6dSMichal Berger_p_cpu_map() { 264c1e9ed6dSMichal Berger ((${#auto_cpu_map[@]} > 0)) || return 0 265c1e9ed6dSMichal Berger printf '%s\n' "${auto_cpu_map[@]}" 266c1e9ed6dSMichal Berger} 267c1e9ed6dSMichal Berger 268c1e9ed6dSMichal Bergerp_disk_map() { 269c1e9ed6dSMichal Berger cat <<- DISK_MAP 270c1e9ed6dSMichal Berger # Generated automatically by ${0##*/} 271c1e9ed6dSMichal Berger # NVMe Drives: ${#auto_disk_map[@]} VM count: $vm_count 272c1e9ed6dSMichal Berger $(_p_disk_map) 273c1e9ed6dSMichal Berger DISK_MAP 274c1e9ed6dSMichal Berger} 275c1e9ed6dSMichal Berger 276c1e9ed6dSMichal Bergerp_vms_in_node() { 277c1e9ed6dSMichal Berger ((${#vm_numa_map[@]} > 0)) || return 0 278c1e9ed6dSMichal Berger 279c1e9ed6dSMichal Berger local node vms 280c1e9ed6dSMichal Berger for node in "${!vm_numa_map[@]}"; do 281c1e9ed6dSMichal Berger vms=(${!vm_numa_map[node]}) 282c1e9ed6dSMichal Berger echo "Node$node: ${#vms[@]} VMs" 283c1e9ed6dSMichal Berger done 284c1e9ed6dSMichal Berger} 285c1e9ed6dSMichal Berger 286c1e9ed6dSMichal Bergerp_cpu_map() { 287c1e9ed6dSMichal Berger local node_stats 288c1e9ed6dSMichal Berger 289c1e9ed6dSMichal Berger mapfile -t node_stats < <(p_vms_in_node) 290c1e9ed6dSMichal Berger cat <<- CPU_MAP 291c1e9ed6dSMichal Berger # Generated automatically by ${0##*/} 292c1e9ed6dSMichal Berger # VM NUMA Nodes: ${#vm_numa_map[@]} VM count: $vm_count CPU Per VM: $vm_cpu_num SPDK CPU count: ${#spdk[@]} 293c1e9ed6dSMichal Berger $(printf '# - %s\n' "${node_stats[@]}") 294c1e9ed6dSMichal Berger $(_p_cpu_map) 295c1e9ed6dSMichal Berger CPU_MAP 296c1e9ed6dSMichal Berger} 297c1e9ed6dSMichal Berger 298c1e9ed6dSMichal Bergerp_all() { 299c1e9ed6dSMichal Berger p_disk_map 300c1e9ed6dSMichal Berger printf '\n' 301c1e9ed6dSMichal Berger p_cpu_map 302c1e9ed6dSMichal Berger} 303c1e9ed6dSMichal Berger 304c1e9ed6dSMichal Bergerfetch_env() { 305c1e9ed6dSMichal Berger spdk_cpu_num=${spdk_cpu_num:-1} 306c1e9ed6dSMichal Berger vm_count=${vm_count:-1} 307c1e9ed6dSMichal Berger vm_cpu_num=${vm_cpu_num:-1} 308cca7c14aSMichal Berger vms_per_nvme=${vms_per_nvme:-1} 309c1e9ed6dSMichal Berger 310c1e9ed6dSMichal Berger # Normalize 311c1e9ed6dSMichal Berger spdk_cpu_num=$((spdk_cpu_num <= 0 ? 1 : spdk_cpu_num)) 312c1e9ed6dSMichal Berger vm_count=$((vm_count <= 0 ? 1 : vm_count)) 313c1e9ed6dSMichal Berger vm_cpu_num=$((vm_cpu_num <= 0 ? 1 : vm_cpu_num)) 314cca7c14aSMichal Berger vms_per_nvme=$((vms_per_nvme <= 0 ? 1 : vms_per_nvme)) 315c1e9ed6dSMichal Berger 316c1e9ed6dSMichal Berger cpu_out=${cpu_out:-"$PWD/auto-cpu.conf"} 317c1e9ed6dSMichal Berger disk_out=${disk_out:-"$PWD/auto-disk.conf"} 318c1e9ed6dSMichal Berger} 319c1e9ed6dSMichal Berger 320c1e9ed6dSMichal Bergerhelp() { 321c1e9ed6dSMichal Berger cat <<- HELP 322c1e9ed6dSMichal Berger ${0##*/}: [-p all|cpu|disk -s] 323c1e9ed6dSMichal Berger 324c1e9ed6dSMichal Berger Configuration is generated based on system's cpu and nvme topology. Parameters 325c1e9ed6dSMichal Berger taken directly from the environment: 326c1e9ed6dSMichal Berger 327c1e9ed6dSMichal Berger spdk_cpu_list - list of CPUs to assign to a SPDK app 328c1e9ed6dSMichal Berger spdk_cpu_num - number of CPUs to use across all NUMA nodes 329c1e9ed6dSMichal Berger (spdk_cpu_list takes priority, default: 1) 330c1e9ed6dSMichal Berger vm_count - number of VMs to prepare the configuration for 331c1e9ed6dSMichal Berger (default: 1) 332c1e9ed6dSMichal Berger vm_cpu_num - number of CPUs to assign per VM (default: 1) 333cca7c14aSMichal Berger vms_per_nvme - Number of VMs to pin to a single nvme (default: 1) 334c1e9ed6dSMichal Berger 335c1e9ed6dSMichal Berger Override parameters: 336b86184c5SMichal Berger VM[N]_NODE - overrides selected NUMA node for VM N - by default, 337c1e9ed6dSMichal Berger this is allocated up to number of nvme drives 338c1e9ed6dSMichal Berger cpu_out - with -s, points at location where to save cpu conf 339c1e9ed6dSMichal Berger disk_out - with -s, points at location where to save disk conf 340c1e9ed6dSMichal Berger 341c1e9ed6dSMichal Berger Note: VMs are pinned to nvme drives based on their NUMA location. 342c1e9ed6dSMichal Berger 343c1e9ed6dSMichal Berger Example: 344c1e9ed6dSMichal Berger # Allocate 6 cpus from node1 for SPDK. Configure 24 VMs, 2 CPUs per VM 345c1e9ed6dSMichal Berger $ export spdk_cpu_num=6 vm_count=24 vm_cpu_num=2 346c1e9ed6dSMichal Berger $ ${0##*/} -p all 347c1e9ed6dSMichal Berger HELP 348c1e9ed6dSMichal Berger} 349c1e9ed6dSMichal Berger 350c1e9ed6dSMichal Bergerprint="" 351c1e9ed6dSMichal Bergersave=no 352c1e9ed6dSMichal Berger 353c1e9ed6dSMichal Bergerfetch_env 354c1e9ed6dSMichal Berger 355c1e9ed6dSMichal Bergerwhile getopts :hsp: arg; do 356c1e9ed6dSMichal Berger case "$arg" in 357c1e9ed6dSMichal Berger h) 358c1e9ed6dSMichal Berger help 359c1e9ed6dSMichal Berger exit 0 360c1e9ed6dSMichal Berger ;; 361c1e9ed6dSMichal Berger p) print=$OPTARG ;; 362c1e9ed6dSMichal Berger s) save=yes ;; 363c1e9ed6dSMichal Berger *) ;; 364c1e9ed6dSMichal Berger esac 365c1e9ed6dSMichal Bergerdone 366c1e9ed6dSMichal Berger 367c1e9ed6dSMichal Bergerget_auto_cfg || exit 1 368c1e9ed6dSMichal Berger 369c1e9ed6dSMichal Bergercase "$print" in 370c1e9ed6dSMichal Berger all) p_all ;; 371c1e9ed6dSMichal Berger cpu) p_cpu_map ;; 372c1e9ed6dSMichal Berger disk) p_disk_map ;; 373c1e9ed6dSMichal Berger *) ;; 374c1e9ed6dSMichal Bergeresac 375c1e9ed6dSMichal Berger 376c1e9ed6dSMichal Bergerif [[ $save == yes ]]; then 377c1e9ed6dSMichal Berger p_cpu_map > "$cpu_out" 378c1e9ed6dSMichal Berger p_disk_map > "$disk_out" 379c1e9ed6dSMichal Bergerfi 380