diff options
author | Zach Marano <zmarano@google.com> | 2017-02-24 15:43:01 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-24 15:43:01 -0800 |
commit | f611604a5404f2a742c05722e96aab86dd9844f3 (patch) | |
tree | 7ab4a5509430dfa12c742e971259cf4b8c147ce7 | |
parent | b896567ee2979ecb35a66523209f9a4a8d8db3c8 (diff) | |
download | google-compute-image-packages-f611604a5404f2a742c05722e96aab86dd9844f3.tar.gz |
Support >32 vCPU's in set_multiqueue. (#375)
-rwxr-xr-x | build_packages.sh | 1 | ||||
-rwxr-xr-x | scripts/set_multiqueue | 78 |
2 files changed, 41 insertions, 38 deletions
diff --git a/build_packages.sh b/build_packages.sh index a2c5cef..6205077 100755 --- a/build_packages.sh +++ b/build_packages.sh @@ -42,6 +42,7 @@ function build_distro() { fpm \ -s python \ -t "${pkg_type}" \ + --conflicts 'irqbalance' \ --depends "${depends}" \ --depends 'python-boto' \ --depends 'python-setuptools' \ diff --git a/scripts/set_multiqueue b/scripts/set_multiqueue index 636ee90..9dfe45f 100755 --- a/scripts/set_multiqueue +++ b/scripts/set_multiqueue @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2016 Google Inc. All Rights Reserved. +# Copyright 2017 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ function set_channels() { ethtool -L "${1}" combined "${2}" > /dev/null 2>&1 } -echo "Running $(basename "$0")." +echo "Running $(basename $0)." NET_DEVS=/sys/bus/virtio/drivers/virtio_net/virtio* # Loop through all the virtionet devices and enable multi-queue @@ -68,7 +68,7 @@ do irq_dir=/proc/irq/* for irq in $irq_dir do - smp_affinity="${irq}/smp_affinity" + smp_affinity="${irq}/smp_affinity_list" [ ! -f "${smp_affinity}" ] && continue # Classify this IRQ as virtionet intx, virtionet MSI-X, or non-virtionet # If the IRQ type is virtionet intx, a subdirectory with the same name as @@ -78,7 +78,7 @@ do # a decimal integer ranging from 0 to K - 1 where K is the number of # input (output) queues in the virtionet device. virtionet_intx_dir="${irq}/${dev}" - virtionet_msix_dir_regex=".*/${dev}-(input|output)\.[0-9]+$" + virtionet_msix_dir_regex=".*/${dev}-(input|output)\.([0-9]+)$" if [ -d "${virtionet_intx_dir}" ]; then # All virtionet intx IRQs are delivered to CPU 0 echo "Setting ${smp_affinity} to 01 for device ${dev}." @@ -90,44 +90,46 @@ do for entry in ${irq}/${dev}*; do if [[ "$entry" =~ ${virtionet_msix_dir_regex} ]]; then virtionet_msix_found=1 + queue_num=${BASH_REMATCH[2]} fi done affinity_hint="${irq}/affinity_hint" [ "$virtionet_msix_found" -eq 0 -o ! -f "${affinity_hint}" ] && continue - # The affinity hint file contains a CPU mask, consisting of - # groups of up to 8 hexadecimal digits, separated by a comma. Each bit - # position in the CPU mask hex value specifies whether this interrupt - # should be delivered to the corresponding CPU. For example, if bits 0 - # and 3 are set in the affinity hint CPU mask hex value, then the - # interrupt should be delivered to CPUs 0 and 3. The virtionet device - # driver should set only a single bit in the affinity hint per MSI-X - # interrupt, ensuring each TX (RX) queue is used only by a single CPU. - # The virtionet driver will only specify an affinity hint if the number of - # TX (RX) queues equals the number of online CPUs. If no affinity hint is - # specified for an IRQ, the affinity hint file will contain all zeros. - affinity_cpumask=$(cat "${affinity_hint}") - affinity_hint_enabled=0 - # Parse the affinity hint, skip if mask is invalid or is empty (all-zeros) - OIFS=${IFS} - IFS="," - for cpu_bitmap in ${affinity_cpumask}; do - bitmap_val=$(printf "%d" "0x${cpu_bitmap}" 2>/dev/null) - if [ "$?" -ne 0 ]; then - echo "Invalid affinity hint ${affinity_hint}: ${affinity_cpumask}." - affinity_hint_enabled=0 - break - elif [ "${bitmap_val}" -ne 0 ]; then - affinity_hint_enabled=1 - fi - done - IFS=${OIFS} - if [ "${affinity_hint_enabled}" -eq 0 ]; then - echo "Cannot set IRQ affinity ${smp_affinity}, affinity hint disabled." - else - # Set the IRQ CPU affinity to the virtionet-initialized affinity hint - echo "Setting ${smp_affinity} to ${affinity_cpumask} for device ${dev}." - echo "${affinity_cpumask}" > "${smp_affinity}" - fi + # Set the IRQ CPU affinity to the virtionet-initialized affinity hint + echo "Setting ${smp_affinity} to ${queue_num} for device ${dev}." + echo "${queue_num}" > "${smp_affinity}" + real_affinity=`cat ${smp_affinity}` + echo "${smp_affinity}: real affinity ${real_affinity}" done done + +XPS=/sys/class/net/e*/queues/tx*/xps_cpus +num_cpus=$(nproc) + +num_queues=0 +for q in $XPS; do + num_queues=$((num_queues + 1)) +done + +# If we have more CPUs than queues, then stripe CPUs across tx affinity +# as CPUNumber % queue_count. +for q in $XPS; do + queue_re=".*tx-([0-9]+).*$" + if [[ "$q" =~ ${queue_re} ]]; then + queue_num=${BASH_REMATCH[1]} + fi + + xps=0 + for cpu in `seq $queue_num $num_queues $((num_cpus - 1))`; do + xps=$((xps | (1 << cpu))) + done + + # Linux xps_cpus requires a hex number with commas every 32 bits. + # It ignores all bits above # cpus, so unconditionally write a + # 64 bit hex value, with a comma between dwords. + xps_string=`printf "%08x,%08x" $((xps >> 32 & 0xffffffff)) $((xps & 0xffffffff))` + + echo ${xps_string} > $q + printf "Queue %d XPS=%s for %s\n" $queue_num `cat $q` $q +done | sort -n -k2 |