Skip to content

Instantly share code, notes, and snippets.

@cn27001
Forked from SaveTheRbtz/set_irq_affinity.sh
Created September 22, 2024 07:40
Show Gist options
  • Save cn27001/c4553fdc009eb121d38288770c52cfa6 to your computer and use it in GitHub Desktop.
Save cn27001/c4553fdc009eb121d38288770c52cfa6 to your computer and use it in GitHub Desktop.

Revisions

  1. @SaveTheRbtz SaveTheRbtz revised this gist Jan 28, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions set_irq_affinity.sh
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    #!/bin/bash
    #
    # Copyright (c) 2014, Intel Corporation
    # Copyright (c) 2015, Intel Corporation
    #
    # Redistribution and use in source and binary forms, with or without
    # modification, are permitted provided that the following conditions are met:
    @@ -261,4 +261,4 @@ if [ "$IRQBALANCE_ON" == "0" ] ; then
    echo " likely override this script's affinitization."
    echo " Please stop the irqbalance service and/or execute"
    echo " 'killall irqbalance'"
    fi
    fi
  2. @SaveTheRbtz SaveTheRbtz revised this gist Apr 19, 2017. No changes.
  3. @SaveTheRbtz SaveTheRbtz revised this gist Nov 26, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion set_irq_affinity.sh
    Original file line number Diff line number Diff line change
    @@ -261,4 +261,4 @@ if [ "$IRQBALANCE_ON" == "0" ] ; then
    echo " likely override this script's affinitization."
    echo " Please stop the irqbalance service and/or execute"
    echo " 'killall irqbalance'"
    fi
    fi
  4. @SaveTheRbtz SaveTheRbtz revised this gist Jun 28, 2016. 1 changed file with 39 additions and 4 deletions.
    43 changes: 39 additions & 4 deletions set_irq_affinity.sh
    Original file line number Diff line number Diff line change
    @@ -36,8 +36,9 @@
    usage()
    {
    echo
    echo "Usage: $0 [-x] {all|local|remote|one|custom} [ethX] <[ethY]>"
    echo "Usage: $0 [-x|-X] {all|local|remote|one|custom} [ethX] <[ethY]>"
    echo " options: -x Configure XPS as well as smp_affinity"
    echo " options: -X Disable XPS but set smp_affinity"
    echo " options: {remote|one} can be followed by a specific node number"
    echo " Ex: $0 local eth0"
    echo " Ex: $0 remote 1 eth0"
    @@ -47,11 +48,37 @@ usage()
    exit 1
    }

    usageX()
    {
    echo "options -x and -X cannot both be specified, pick one"
    exit 1
    }

    if [ "$1" == "-x" ]; then
    XPS_ENA=1
    shift
    fi

    if [ "$1" == "-X" ]; then
    if [ -n "$XPS_ENA" ]; then
    usageX
    fi
    XPS_DIS=2
    shift
    fi

    if [ "$1" == -x ]; then
    usageX
    fi

    if [ -n "$XPS_ENA" ] && [ -n "$XPS_DIS" ]; then
    usageX
    fi

    if [ -z "$XPS_ENA" ]; then
    XPS_ENA=$XPS_DIS
    fi

    num='^[0-9]+$'
    # Vars
    AFF=$1
    @@ -106,10 +133,18 @@ set_affinity()

    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
    printf "%s %d %s -> /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $MASK
    if ! [ -z "$XPS_ENA" ]; then
    case "$XPS_ENA" in
    1)
    printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1))
    printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus
    fi
    ;;
    2)
    MASK=0
    printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1))
    printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus
    ;;
    *)
    esac
    }

    # Allow usage of , or -
    @@ -226,4 +261,4 @@ if [ "$IRQBALANCE_ON" == "0" ] ; then
    echo " likely override this script's affinitization."
    echo " Please stop the irqbalance service and/or execute"
    echo " 'killall irqbalance'"
    fi
    fi
  5. @SaveTheRbtz SaveTheRbtz revised this gist Oct 8, 2015. 1 changed file with 194 additions and 60 deletions.
    254 changes: 194 additions & 60 deletions set_irq_affinity.sh
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,91 @@
    # setting up irq affinity according to /proc/interrupts
    # 2008-11-25 Robert Olsson
    # 2009-02-19 updated by Jesse Brandeburg
    #!/bin/bash
    #
    # > Dave Miller:
    # (To get consistent naming in /proc/interrups)
    # I would suggest that people use something like:
    # char buf[IFNAMSIZ+6];
    # Copyright (c) 2014, Intel Corporation
    #
    # sprintf(buf, "%s-%s-%d",
    # netdev->name,
    # (RX_INTERRUPT ? "rx" : "tx"),
    # queue->index);
    # Redistribution and use in source and binary forms, with or without
    # modification, are permitted provided that the following conditions are met:
    #
    # Assuming a device with two RX and TX queues.
    # This script will assign:
    # * Redistributions of source code must retain the above copyright notice,
    # this list of conditions and the following disclaimer.
    # * Redistributions in binary form must reproduce the above copyright
    # notice, this list of conditions and the following disclaimer in the
    # documentation and/or other materials provided with the distribution.
    # * Neither the name of Intel Corporation nor the names of its contributors
    # may be used to endorse or promote products derived from this software
    # without specific prior written permission.
    #
    # eth0-rx-0 CPU0
    # eth0-rx-1 CPU1
    # eth0-tx-0 CPU0
    # eth0-tx-1 CPU1
    # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    #
    # Affinitize interrupts to cores
    #
    # typical usage is (as root):
    # set_irq_affinity -x local eth1 <eth2> <eth3>
    #
    # to get help:
    # set_irq_affinity

    usage()
    {
    echo
    echo "Usage: $0 [-x] {all|local|remote|one|custom} [ethX] <[ethY]>"
    echo " options: -x Configure XPS as well as smp_affinity"
    echo " options: {remote|one} can be followed by a specific node number"
    echo " Ex: $0 local eth0"
    echo " Ex: $0 remote 1 eth0"
    echo " Ex: $0 custom eth0 eth1"
    echo " Ex: $0 0-7,16-23 eth0"
    echo
    exit 1
    }

    if [ "$1" == "-x" ]; then
    XPS_ENA=1
    shift
    fi

    num='^[0-9]+$'
    # Vars
    AFF=$1
    shift

    case "$AFF" in
    remote) [[ $1 =~ $num ]] && rnode=$1 && shift ;;
    one) [[ $1 =~ $num ]] && cnt=$1 && shift ;;
    all) ;;
    local) ;;
    custom) ;;
    [0-9]*) ;;
    -h|--help) usage ;;
    "") usage ;;
    *) IFACES=$AFF && AFF=all ;; # Backwards compat mode
    esac

    # append the interfaces listed to the string with spaces
    while [ "$#" -ne "0" ] ; do
    IFACES+=" $1"
    shift
    done

    # for now the user must specify interfaces
    if [ -z "$IFACES" ]; then
    usage
    exit 1
    fi

    # support functions

    set_affinity()
    {
    VEC=$core
    if [ $VEC -ge 32 ]
    then
    MASK_FILL=""
    @@ -35,24 +98,126 @@ set_affinity()

    let "VEC -= 32 * $IDX"
    MASK_TMP=$((1<<$VEC))
    MASK=`printf "%X%s" $MASK_TMP $MASK_FILL`
    MASK=$(printf "%X%s" $MASK_TMP $MASK_FILL)
    else
    MASK_TMP=$((1<<$VEC))
    MASK=`printf "%X" $MASK_TMP`
    MASK=$(printf "%X" $MASK_TMP)
    fi

    printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ
    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
    printf "%s %d %s -> /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $MASK
    if ! [ -z "$XPS_ENA" ]; then
    printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1))
    printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus
    fi
    }

    if [ "$1" = "" ] ; then
    echo "Description:"
    echo " This script attempts to bind each queue of a multi-queue NIC"
    echo " to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1"
    echo "usage:"
    echo " $0 eth0 [eth1 eth2 eth3]"
    fi
    # Allow usage of , or -
    #
    parse_range () {
    RANGE=${@//,/ }
    RANGE=${RANGE//-/..}
    LIST=""
    for r in $RANGE; do
    # eval lets us use vars in {#..#} range
    [[ $r =~ '..' ]] && r="$(eval echo {$r})"
    LIST+=" $r"
    done
    echo $LIST
    }

    # Affinitize interrupts
    #
    setaff()
    {
    CORES=$(parse_range $CORES)
    ncores=$(echo $CORES | wc -w)
    n=1

    # this script only supports interrupt vectors in pairs,
    # modification would be required to support a single Tx or Rx queue
    # per interrupt vector

    queues="${IFACE}-.*TxRx"

    irqs=$(grep "$queues" /proc/interrupts | cut -f1 -d:)
    [ -z "$irqs" ] && irqs=$(grep $IFACE /proc/interrupts | cut -f1 -d:)
    [ -z "$irqs" ] && irqs=$(for i in `ls -Ux /sys/class/net/$IFACE/device/msi_irqs` ;\
    do grep "$i:.*TxRx" /proc/interrupts | grep -v fdir | cut -f 1 -d : ;\
    done)
    [ -z "$irqs" ] && echo "Error: Could not find interrupts for $IFACE"

    echo "IFACE CORE MASK -> FILE"
    echo "======================="
    for IRQ in $irqs; do
    [ "$n" -gt "$ncores" ] && n=1
    j=1
    # much faster than calling cut for each
    for i in $CORES; do
    [ $((j++)) -ge $n ] && break
    done
    core=$i
    set_affinity
    ((n++))
    done
    }

    # now the actual useful bits of code

    # these next 2 lines would allow script to auto-determine interfaces
    #[ -z "$IFACES" ] && IFACES=$(ls /sys/class/net)
    #[ -z "$IFACES" ] && echo "Error: No interfaces up" && exit 1

    # echo IFACES is $IFACES

    CORES=$(</sys/devices/system/cpu/online)
    [ "$CORES" ] || CORES=$(grep ^proc /proc/cpuinfo | cut -f2 -d:)

    # Core list for each node from sysfs
    node_dir=/sys/devices/system/node
    for i in $(ls -d $node_dir/node*); do
    i=${i/*node/}
    corelist[$i]=$(<$node_dir/node${i}/cpulist)
    done

    for IFACE in $IFACES; do
    # echo $IFACE being modified

    dev_dir=/sys/class/net/$IFACE/device
    [ -e $dev_dir/numa_node ] && node=$(<$dev_dir/numa_node)
    [ "$node" ] && [ "$node" -gt 0 ] || node=0

    case "$AFF" in
    local)
    CORES=${corelist[$node]}
    ;;
    remote)
    [ "$rnode" ] || { [ $node -eq 0 ] && rnode=1 || rnode=0; }
    CORES=${corelist[$rnode]}
    ;;
    one)
    [ -n "$cnt" ] || cnt=0
    CORES=$cnt
    ;;
    all)
    CORES=$CORES
    ;;
    custom)
    echo -n "Input cores for $IFACE (ex. 0-7,15-23): "
    read CORES
    ;;
    [0-9]*)
    CORES=$AFF
    ;;
    *)
    usage
    exit 1
    ;;
    esac

    # call the worker function
    setaff
    done

    # check for irqbalance running
    IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?`
    @@ -61,35 +226,4 @@ if [ "$IRQBALANCE_ON" == "0" ] ; then
    echo " likely override this script's affinitization."
    echo " Please stop the irqbalance service and/or execute"
    echo " 'killall irqbalance'"
    fi

    #
    # Set up the desired devices.
    #

    for DEV in $*
    do
    for DIR in rx tx TxRx
    do
    MAX=`grep $DEV-$DIR /proc/interrupts | wc -l`
    if [ "$MAX" == "0" ] ; then
    MAX=`egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l`
    fi
    if [ "$MAX" == "0" ] ; then
    echo no $DIR vectors found on $DEV
    continue
    fi
    for VEC in `seq 0 1 $MAX`
    do
    IRQ=`cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$" | cut -d: -f1 | sed "s/ //g"`
    if [ -n "$IRQ" ]; then
    set_affinity
    else
    IRQ=`cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$" | cut -d: -f1 | sed "s/ //g"`
    if [ -n "$IRQ" ]; then
    set_affinity
    fi
    fi
    done
    done
    done
    fi
  6. @SaveTheRbtz SaveTheRbtz created this gist Feb 8, 2014.
    95 changes: 95 additions & 0 deletions set_irq_affinity.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    # setting up irq affinity according to /proc/interrupts
    # 2008-11-25 Robert Olsson
    # 2009-02-19 updated by Jesse Brandeburg
    #
    # > Dave Miller:
    # (To get consistent naming in /proc/interrups)
    # I would suggest that people use something like:
    # char buf[IFNAMSIZ+6];
    #
    # sprintf(buf, "%s-%s-%d",
    # netdev->name,
    # (RX_INTERRUPT ? "rx" : "tx"),
    # queue->index);
    #
    # Assuming a device with two RX and TX queues.
    # This script will assign:
    #
    # eth0-rx-0 CPU0
    # eth0-rx-1 CPU1
    # eth0-tx-0 CPU0
    # eth0-tx-1 CPU1
    #

    set_affinity()
    {
    if [ $VEC -ge 32 ]
    then
    MASK_FILL=""
    MASK_ZERO="00000000"
    let "IDX = $VEC / 32"
    for ((i=1; i<=$IDX;i++))
    do
    MASK_FILL="${MASK_FILL},${MASK_ZERO}"
    done

    let "VEC -= 32 * $IDX"
    MASK_TMP=$((1<<$VEC))
    MASK=`printf "%X%s" $MASK_TMP $MASK_FILL`
    else
    MASK_TMP=$((1<<$VEC))
    MASK=`printf "%X" $MASK_TMP`
    fi

    printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ
    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
    }

    if [ "$1" = "" ] ; then
    echo "Description:"
    echo " This script attempts to bind each queue of a multi-queue NIC"
    echo " to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1"
    echo "usage:"
    echo " $0 eth0 [eth1 eth2 eth3]"
    fi


    # check for irqbalance running
    IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?`
    if [ "$IRQBALANCE_ON" == "0" ] ; then
    echo " WARNING: irqbalance is running and will"
    echo " likely override this script's affinitization."
    echo " Please stop the irqbalance service and/or execute"
    echo " 'killall irqbalance'"
    fi

    #
    # Set up the desired devices.
    #

    for DEV in $*
    do
    for DIR in rx tx TxRx
    do
    MAX=`grep $DEV-$DIR /proc/interrupts | wc -l`
    if [ "$MAX" == "0" ] ; then
    MAX=`egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l`
    fi
    if [ "$MAX" == "0" ] ; then
    echo no $DIR vectors found on $DEV
    continue
    fi
    for VEC in `seq 0 1 $MAX`
    do
    IRQ=`cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$" | cut -d: -f1 | sed "s/ //g"`
    if [ -n "$IRQ" ]; then
    set_affinity
    else
    IRQ=`cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$" | cut -d: -f1 | sed "s/ //g"`
    if [ -n "$IRQ" ]; then
    set_affinity
    fi
    fi
    done
    done
    done