[olug] 2.4 kernel/ SMP and APIC
VincentR
vincentr at cox.net
Tue Dec 10 23:11:03 UTC 2002
This is mostly an FYI thing for thought...
There's a little used feature in the 2.4 kernel which enables you to bind an
IRQ to a specific CPU. Why would you do this? In my case it was because
UDP packets in a stream were getting out of sequence due to the APIC
allowing multiple CPU's to service interrupts on the same ethernet device.
You could just turn off APIC with boot loader options (append="noapic"), but
that would disable most of the advantages of an SMP system. You could also
increase the number of packets serviced within an interrupt if your driver
allows that configuration in modules.conf (options 3c59x
max_interrupt_work=60). That helps, but it doesn't fix the problem.
Here's an init script to set the smp_affinity for each network device (word
wrap will probably screw it up):
[root at --- /root]# cat /etc/init.d/eth_affinity
#!/bin/bash
#
# eth_affinity
#
# chkconfig: 345 15 85
# description: Set IRQ affinity for eth devices.
# Define which networks get which CPU.
# You must use the first three octets.
CPU0="10.100.116 10.5.7 10.5.9 10.129.7 10.0.9"
CPU1="10.10.10 10.10.11 10.10.0"
# Where is /proc?
PROC=/proc
IPV4=/proc/sys/net/ipv4
# Got root?
if [ `id -u` -gt "0" ]; then
echo "You are not root!"
exit 1
fi
# Check kernel version.
if [ ! `uname --release | cut -d. -f1-2` = "2.4" ]; then
echo "You are not running a 2.4 kernel"
echo "Version detected: "`uname --release`
exit 1
fi
# Is this an SMP kernel?
if [ ! -f /proc/1/cpu ]; then
echo "Get an SMP system to do this on!"
exit 1
fi
# Check for the required files and directories.
if [ ! -d $PROC/irq ] || [ ! -d $IPV4/conf ]; then
echo "I couldn't find a required file or directory; Exiting..."
file $PROC/irq $IPV4/conf
exit 1
fi
#DEBUG SECTION##################################################
# Set DEBUG=1 to test this in /tmp.
DEBUG=0
if [ "$DEBUG" = "1" ]; then
PROC=/tmp
IPV4=/tmp/ipv4
fi
# Copy files to /tmp if needed.
if [ ! -d $PROC/irq ] || [ ! -d $IPV4/conf ]; then
cp -a /proc/irq /tmp
cp -a /proc/sys/net/ipv4 /tmp > /dev/null 2>&1
fi
#DEBUG SECTION##################################################
# Here we go...
case "$1" in
start)
# Find each eth's irq and network; set the affinity.
for ETH in `/bin/ls $IPV4/conf | egrep -v all\|default\|lo`; do
IRQ=`ifconfig $ETH | grep Interrupt | awk -F: '{print $2}' |
awk '{print $1}'`
NET=`ifconfig $ETH | grep "inet addr" | awk -F: '{print $2}'
| cut -d. -f1-3`
for net in `echo $CPU0`; do
if [ "$NET" = "$net" ]; then
echo 1 > $PROC/irq/$IRQ/smp_affinity
fi
done
for net in `echo $CPU1`; do
if [ "$NET" = "$net" ]; then
echo 2 > $PROC/irq/$IRQ/smp_affinity
fi
done
done
touch /var/lock/subsys/eth_affinity
$0 status
;;
stop)
# Find each eth's irq; unset the affinity.
for ETH in `/bin/ls $IPV4/conf | egrep -v all\|default\|lo`; do
IRQ=`ifconfig $ETH | grep Interrupt | awk -F: '{print $2}' |
awk '{print $1}'`
echo ffffffff > $PROC/irq/$IRQ/smp_affinity
done
rm -f /var/lock/subsys/eth_affinity
$0 status
;;
status)
# Find each eth's irq and network; display the affinity.
for ETH in `/bin/ls $IPV4/conf | egrep -v all\|default\|lo`; do
IRQ=`ifconfig $ETH | grep Interrupt | awk -F: '{print $2}' |
awk '{print $1}'`
NET=`ifconfig $ETH | grep "inet addr" | awk -F: '{print $2}'
| cut -d. -f1-3`
AFFINITY=`cat $PROC/irq/$IRQ/smp_affinity`
if [ "$AFFINITY" = "00000001" ]; then
echo "$ETH IRQ $IRQ has affinity with CPU0 on
network $NET."
fi
if [ "$AFFINITY" = "00000002" ]; then
echo "$ETH IRQ $IRQ has affinity with CPU1 on
network $NET."
fi
if [ "$AFFINITY" = "ffffffff" ]; then
echo "$ETH IRQ $IRQ has affinity with ALL on network
$NET."
fi
if [ ! "$AFFINITY" = "00000001" ] && [ ! "$AFFINITY" =
"00000002" ] && [ ! "$AFFINITY" = "ffffffff" ]; then
echo -e "$ETH IRQ $IRQ network $NET has an affinity
of $AFFINITY."
echo "I have no idea what this means!"
fi
done
;;
*)
echo "Usage: eth_affinity {start|stop|status}"
exit 1
esac
#EOF
More information about the OLUG
mailing list