25

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?

3
  • Tried lspci or lshw ? Jul 30, 2015 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, 2015 at 5:22
  • Glad I could help. I'll post this as an answer, then Jul 31, 2015 at 6:29

6 Answers 6

41

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.

2
  • 3
    The lspci doesn't provide the device name so in case of 2 identical devices it's not possible to distinguish which pci address and device name match Sep 9, 2019 at 10:01
  • lshw works though, so still ⁺¹. But I agree, the information about lspci can probably be removed from the answer, it doesn't work for reasons mentioned in prev. comment.
    – Hi-Angel
    Feb 14, 2022 at 12:39
27

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
4
  • Not under vmware where there is no device symlink Mar 9, 2018 at 12:00
  • 1
    Maybe because VMware's paravirtualized network device is not based on Ethernet? Mar 9, 2018 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. Mar 12, 2018 at 15:20
  • 3
    Even more directly, $ ls -l /sys/class/net/eth0/device lrwxrwxrwx 1 root root 0 Nov 16 16:30 /sys/class/net/eth0/device -> ../../../0000:07:00.0 though device/uevent has a bunch of other useful stuff you might also need.
    – eichin
    Nov 16, 2020 at 21:35
13

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
0
5

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

1
  • Thanks for your kind response. lshw provided me a better solution :)
    – Waqas
    Jul 31, 2015 at 5:25
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
4
  • Neat program, udevadm ! learned something new. +1 Jul 31, 2015 at 7:42
  • @Serg I needed a different solution ;)
    – A.B.
    Jul 31, 2015 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, 2015 at 8:23
  • @Waqas I don't understand.
    – A.B.
    Aug 18, 2015 at 8:28
0

Sorry but PCI_SLOT_NAME in uevent isn't a PCI slot number, it is the bus.

On HP H/W you can use bus number to look up the PCI slot number from the output of hplog -i.

But I can't find similar utility for Oracle Linux on Sun H/W like M2s You can get some information using lspci -vmm & looking for PhySlot entries.

This is for older systems before Dell's biosdevnames.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .