8

is there a way to find out the PCI bus number of an Ethernet interface or vice versa. I am looking to write a Bash/Python script which gives some thing like

pci_address = some_function(eth0)

where pci_address is sys:bus:slot:function. How can these two elements be related to each other?

  • Tried lspci or lshw ? – Sergiy Kolodyazhnyy Jul 30 '15 at 21:31
  • I had used lspci but didn't tried lshw. Following command worked for me lshw -class network -businfo. Thanks @Serg – Waqas Jul 31 '15 at 5:22
  • Glad I could help. I'll post this as an answer, then – Sergiy Kolodyazhnyy Jul 31 '15 at 6:29
11

lshw and lspci are both capable of showing that information. As you have found out already, you can do lshw -class network -businfo. For instance, here's my output:

$ sudo lshw -c network -businfo                                                                                                                    
Bus info          Device      Class       Description
=====================================================
pci@0000:0e:00.0  wlan0       network     RTL8187SE Wireless LAN Controller
pci@0000:14:00.0  eth0        network     RTL8101E/RTL8102E PCI Express Fast Ethernet controller

What you also could use is lspci -D and pipe it to grep to filter out the ethernet controller specifically. Here's my example:

$ lspci -D | grep 'Network\|Ethernet'                                                                                                              
    0000:0e:00.0 Network controller: Realtek Semiconductor Co., Ltd. RTL8187SE Wireless LAN Controller (rev 22)
    0000:14:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8101E/RTL8102E PCI Express Fast Ethernet controller (rev 02)

Note that with the transition to systemd, one could use of Predictable Interface Naming to just look at the interface name to find out PCI information.

7

ethtool will also show you pci for an interface (bus-info:)

me@ubuntu:~$ ethtool -i eth0
driver: i40e
version: 1.5.16
firmware-version: 5.04 0x800024cd 0.0.0
bus-info: 0000:06:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
3

It looks you can tie them together by the IRQ.

ifconfig -a 

will print the ethernet devices including Interrupt.

eg.

eth2      Link encap:Ethernet  HWaddr 00:25:11:19:8b:77  
          inet addr:192.168.1.3  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::225:11ff:fe19:8b77/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:39958 errors:0 dropped:0 overruns:0 frame:0
          TX packets:34512 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:21410099 (21.4 MB)  TX bytes:4802798 (4.8 MB)
          Interrupt:43 Base address:0xa000

while

lspci -v

gives the PCI info with IRQ

eg.

04:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8101E/RTL8102E PCI Express Fast Ethernet controller (rev 01)
    Subsystem: Acer Incorporated [ALI] Device 0245
    Flags: bus master, fast devsel, latency 0, IRQ 43
    I/O ports at e800 [size=256]
    Memory at febff000 (64-bit, non-prefetchable) [size=4K]
    Expansion ROM at febc0000 [disabled] [size=128K]
    Capabilities: <access denied>
    Kernel driver in use: r8169
    Kernel modules: r8169

since I see both are 43 I can infer that eth2 matches 04:00.0

  • Thanks for your kind response. lshw provided me a better solution :) – Waqas Jul 31 '15 at 5:25
2

This information is available in sysfs, no helpers like lshw / lspci / ethtool / udevadm are needed:

$ grep PCI_SLOT_NAME /sys/class/net/*/device/uevent
/sys/class/net/enp4s0/device/uevent:PCI_SLOT_NAME=0000:04:00.0
/sys/class/net/wlp2s0/device/uevent:PCI_SLOT_NAME=0000:02:00.0
  • Not under vmware where there is no device symlink – Sam Liddicott Mar 9 '18 at 12:00
  • 1
    Maybe because VMware's paravirtualized network device is not based on Ethernet? – Vladimir Panteleev Mar 9 '18 at 15:19
  • Thanks. You are mostly right I soon discovered, but I couldn't find my comment to remove it. What had happened was the device was re-bound to igb_uio for DPDK, and so the original device nodes were no longer available. – Sam Liddicott Mar 12 '18 at 15:20
0

Another solution, using udevadm

udevadm info -a -p /sys/class/net/eth{0..10} | awk '/device.*eth/'

{0..10} – checks the initerfaces from eth0eth10

Therefore you could use this command

pci_address=$(udevadm info -a -p /sys/class/net/eth{0..10} | awk -F/ '/device.*eth/ {print $4}')

Example output

looking at device '/devices/pci0000:00/0000:00:03.0/net/eth0':

Therefore the address is

0000:00:03.0

Or in your case with a single command

% pci_address=$(udevadm info -a -p /sys/class/net/eth{0..10} | awk -F/ '/device.*eth/ {print $4}')
% echo $pci_address
0000:00:03.0

or in a script

#!/bin/bash
udevadm info -a -p /sys/class/net/"$1" | awk -F/ '/device.*eth/ {print $4}'

Call the script with

script_name eth0

Output is

0000:00:03.0
  • Neat program, udevadm ! learned something new. +1 – Sergiy Kolodyazhnyy Jul 31 '15 at 7:42
  • @Serg I needed a different solution ;) – A.B. Jul 31 '15 at 7:43
  • @A.B. lshw and above approach are giving me two different results. Shouldn't both provide same pci address? cheers – Waqas Aug 18 '15 at 8:23
  • @Waqas I don't understand. – A.B. Aug 18 '15 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.