summaryrefslogtreecommitdiff
path: root/scripts/system/vyatta-irqaffin
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/system/vyatta-irqaffin')
-rwxr-xr-xscripts/system/vyatta-irqaffin198
1 files changed, 198 insertions, 0 deletions
diff --git a/scripts/system/vyatta-irqaffin b/scripts/system/vyatta-irqaffin
new file mode 100755
index 00000000..6fa0e086
--- /dev/null
+++ b/scripts/system/vyatta-irqaffin
@@ -0,0 +1,198 @@
+#!/bin/bash
+
+# Author: Robert E. Gilligan <gilligan@vyatta.com>
+# Date: 2008
+# Description: CLI back-end script to manipulate NIC interrupt CPU affinity.
+
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+# Provides sub-commands to:
+# - Check the validity of an affinity mask value
+# - Set the affinity mask to the IRQs being used by an interface
+# - Reset the affinity mask of the IRQs being used by an interface to the
+# system default value of all-ones.
+# - Print the affinity mask of the IRQs being used by an interface
+#
+# If the NIC in question supports multiple IRQs, the "set" sub-command
+# sets all IRQs to the same mask. The "print" sub-command displays
+# the mask of each IRQ individually.
+#
+
+# Max number of hex characters in an IRQ affinity mask. Support up to 64 CPUs.
+MAX_MASK=16
+
+# Set up some global values...
+numcpus=`grep -c -e "^processor" /proc/cpuinfo`
+declare -i maxmask=(2**numcpus)
+let maxmask=maxmask-1
+maxmaskhex=`printf "%x" ${maxmask}`
+
+print_usage()
+{
+ echo "Usage:"
+ echo -e "\t$0 check <ifname> <mask>"
+ echo -e "\t$0 set <ifname> <mask>"
+ echo -e "\t$0 reset <ifname>"
+ echo -e "\t$0 print <ifname>"
+}
+
+get_irqnums()
+{
+ irqnums=`grep $1 /proc/interrupts | awk -F ': ' '{ print $1 }'`
+ if [ -z "$irqnums" ]; then
+ echo "Unable to determine IRQs for interface $1"
+ return 1
+ fi
+ return 0
+}
+
+
+get_mask()
+{
+ mask=$1
+
+ # mask must be a short hex value
+ if [ ${#mask} -gt $MAX_MASK ]; then
+ echo "mask too long: ${#2} characters."
+ return 1
+ fi
+
+ # strip out all the hex digits
+ exmask=`echo $mask | sed -e s/[0-9a-fA-F]//g`
+
+ # if anything is left, its not hex
+ if [ ! -z "$exmask" ]; then
+ echo "Invalid characters in hex mask: $exmask"
+ return 1
+ fi
+
+ declare -i intmask=0x${mask}
+
+ # Make sure that mask holds at least one bit, and holds no more bits
+ # than we have CPUs.
+
+ if [ ${intmask} -eq 0 ]; then
+ echo "Mask can not be 0."
+ return 1
+ fi
+
+ if [ $intmask -gt $maxmask ]; then
+ echo "Mask is too large. Maximum hexidecimal bitmask is: ${maxmaskhex}"
+ return 1
+ fi
+
+ return 0
+}
+
+
+case "$1" in
+ check)
+ # Note: We don't validate the interface name even though
+ # it is available as a command argument. That is because
+ # the interface may not exist or may not be configured at
+ # the time the check is performed.
+ #
+ if [ $# -ne 3 ]; then
+ print_usage
+ exit 1
+ fi
+
+ if ! get_mask $3 ; then
+ exit 1
+ fi
+ exit 0
+ ;;
+
+ set)
+ if [ $# -ne 3 ]; then
+ print_usage
+ exit 1
+ fi
+
+ if ! check_uniproc ; then
+ exit 1
+ fi
+
+ if ! get_irqnums $2 ; then
+ exit 1
+ fi
+
+ if ! get_mask $3 ; then
+ exit 1
+ fi
+
+ for irqnum in $irqnums ; do
+ echo $mask > /proc/irq/$irqnum/smp_affinity
+ done
+
+ if [ $? -ne 0 ]; then
+ echo "Couldn't assign smp_affinity. Exit status: $?"
+ exit 1
+ fi
+ ;;
+
+ reset)
+ if [ $# -ne 2 ]; then
+ print_usage
+ exit 1
+ fi
+ if ! get_irqnums $2 ; then
+ exit 1
+ fi
+
+ if [ -e /proc/irq/default_smp_affinity ]; then
+ defmask=`cat /proc/irq/default_smp_affinity`
+ else
+ defmask=$maxmaskhex
+ fi
+
+ for irqnum in $irqnums ; do
+ echo $defmask > /proc/irq/$irqnum/smp_affinity
+ if [ $? -ne 0 ]; then
+ echo "Couldn't assign smp_affinity for IRQ $irqnum. Exit status: $?"
+ exit 1
+ fi
+ done
+ ;;
+
+
+ print)
+ if [ $# -ne 2 ]; then
+ print_usage
+ exit 1
+ fi
+ if ! get_irqnums $2 ; then
+ exit 1
+ fi
+
+ for irqnum in $irqnums ; do
+ mask=`cat /proc/irq/$irqnum/smp_affinity`
+
+ if [ -z $mask ]; then
+ echo "Couldn't get smp_affinity for interface $2, irq $irqnum"
+ exit 1
+ fi
+
+ echo "Interface: $2 IRQ: $irqnum Mask: $mask"
+ done
+ ;;
+
+ *)
+ print_usage
+ exit 1
+ ;;
+
+esac