diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2011-03-16 12:17:13 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2011-03-16 12:17:13 -0700 |
commit | 082b1f52b5d18a7d6526c6e92290a862e63ddace (patch) | |
tree | 2ebb79dc5d0246b981b69deb2a8dcbb0fdf951b8 /scripts | |
parent | 22b23b946a307375bd6eb95c87cfc59e6455a91c (diff) | |
download | vyatta-cfg-quagga-082b1f52b5d18a7d6526c6e92290a862e63ddace.tar.gz vyatta-cfg-quagga-082b1f52b5d18a7d6526c6e92290a862e63ddace.zip |
Handle irq assignment on multiqueue NIC
Bug 6845, 6821
Need to avoid using /sys/class/net/ethX/device/irq (or /sys/bus/pci/.../irq)
because these don't handle MSI or multiqueue. This also resolves issues
with Vmware/ESX.
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/system/irq-affinity.pl | 74 |
1 files changed, 21 insertions, 53 deletions
diff --git a/scripts/system/irq-affinity.pl b/scripts/system/irq-affinity.pl index b15c1168..509e4f46 100755 --- a/scripts/system/irq-affinity.pl +++ b/scripts/system/irq-affinity.pl @@ -39,21 +39,11 @@ if ($mask eq 'auto') { exit 0; -# Test if device is in up by reading /sys/class/net/ethX/flags -sub is_up { - my $ifname = shift; - - open ( my $f, '<', "/sys/class/net/$ifname/flags" ) - or return; - my $flags = <$f>; - chomp $flags; - close $f; - - return hex($flags) & 1; -} - # Get current irq assignments by reading /proc/interrupts +# returns reference to hash of interrupt infromation for given interface +# i.e. {'eth1'} => 22, {'eth1-tx-1'} => 31, ... sub irqinfo { + my $ifname = shift; my $irqmap; open( my $f, '<', "/proc/interrupts" ) @@ -70,6 +60,9 @@ sub irqinfo { # Skip columns for IRQ's per CPU foreach my $name ( @cols[ $cpus+1 .. $#cols ] ) { $name =~ s/,$//; + + next unless ($name eq $ifname || $name =~ /^$ifname-/ ); + $irqmap->{$name} = $irq; } } @@ -223,20 +216,6 @@ sub assign_single { # MAYBE - Use all cpu's if no HT } -# find irq number used for given interface using sysfs -sub get_irq { - my $ifname = shift; - - # return (undefined) unless device has irq - return unless open( my $irqf, '<', "/sys/class/net/$ifname/device/irq" ); - - my $irq = <$irqf>; - chomp $irq; - close $irqf; - - return $irq; -} - # Mask must contain at least one CPU and # no bits outside of range of available CPU's sub check_mask { @@ -265,23 +244,13 @@ sub affinity_mask { check_mask($ifname, "irq", $irqmsk); check_mask($ifname, "rps", $rpsmsk) if $rpsmsk; - return unless is_up($ifname); - - my $nirq = grep { /$ifname/ } keys %{irqinfo()}; - if ( $nirq > 1 ) { - syslog( LOG_NOTICE, "%s: device is multiqueue, ignoring affinity mask", - $ifname); - warn "$ifname: interface has multiple irq, ignoring affinity mask\n"; - } else { - my $irq = get_irq($ifname); - die "$ifname: attempt to assign affinity to device without irq\n" - unless (defined($irq)); - - syslog( LOG_INFO, "%s: assign irq %d mask %s", $ifname, $irq, $irqmsk); - - set_affinity($ifname, $irq, hex($irqmsk)); - set_rps($ifname, 0, hex($rpsmsk)) if $rpsmsk; + my $irqmap = irqinfo($ifname); + while (my ($name, $irq) = each (%{$irqmap})) { + syslog( LOG_INFO, "%s: assign irq %d mask %s", $name, $irq, $irqmsk); + set_affinity($name, $irq, hex($irqmsk)); } + + set_rps($ifname, 0, hex($rpsmsk)) if $rpsmsk; } # The auto strategy involves trying to achieve the following goals: @@ -300,20 +269,19 @@ sub affinity_mask { sub affinity_auto { my $ifname = shift; - return unless is_up($ifname); - - my $irqmap = irqinfo(); + my $irqmap = irqinfo($ifname); my @irqnames = keys %{$irqmap}; + my $numirq = scalar(@irqnames); # Figure out what style of irq naming is being used - my $numirq = grep { /$ifname/ } @irqnames; if ( $numirq == 1 ) { - my $irq = get_irq($ifname); + my $irq = $irqmap->{$ifname}; assign_single( $ifname, $irq) if $irq; } elsif ($numirq > 1) { - my $nq = grep { /$ifname-rx-/ } @irqnames; + + my $nq = grep { /^$ifname-rx-/ } @irqnames; if ( $nq > 0 ) { - my $ntx = grep { /$ifname-tx-/ } @irqnames; + my $ntx = grep { /^$ifname-tx-/ } @irqnames; die "$ifname: rx queues $nq != tx queues $ntx" unless ( $nq == $ntx ); @@ -322,19 +290,19 @@ sub affinity_auto { } # intel convention - $nq = grep { /$ifname-TxRx-/ } @irqnames; + $nq = grep { /^$ifname-TxRx-/ } @irqnames; if ( $nq > 0 ) { return assign_multiqueue( $ifname, $nq, $irqmap, ['%s-TxRx-%d'] ); } # vmxnet3 convention - $nq = grep { /$ifname-rxtx-/ } @irqnames; + $nq = grep { /^$ifname-rxtx-/ } @irqnames; if ( $nq > 0 ) { return assign_multiqueue( $ifname, $nq, $irqmap, ['%s-rxtx-%d'] ); } # old naming - $nq = grep { /$ifname-\d$/ } @irqnames; + $nq = grep { /^$ifname-\d$/ } @irqnames; if ( $nq > 0 ) { return assign_multiqueue( $ifname, $nq, $irqmap, ['%s-%d'] ); } |