How to map ethtool's bus-info to /sys/devices/? - linux

How are the bus-info addresses from ethtool -i <netdev> to be interpreted in order to address the corresponding HW device in /sys/devices/? That is, using the Linux sysfs API with the information returned by the ethtool ioctl SIOCETHTOOL (or similar) API?
Please note that I'm in a situation where I cannot use /sys/class/net/ due to the way that sysfs filters the net/ branch(es) based on the mounting process' network namespace. sysfs does not filter net/ based on the sysfs-reading process' current network namespace; compare this with procfs which always correctly adapts to the procfs-reading process' current PID namespace.
For instance, on a Raspberry Pi 4B with Ubuntu 21.10 ethtool -i eth0 for the integrated eth0 HW NIC just draws a literal blank:
bus-info:
The eth0 device seems to be located here: /sys/devices/platform/emmc2bus/subsystem/devices/fd580000.ethernet/.
Plugging in an USB-based Ethernet dongle and then querying it I get:
bus-info: usb-0000:01:00.0-1.1
Unfortunately, that's not a directly valid item in, say, /sys/devices/...
How are the bus-info addresses reported by the ethtool API (socket/RTNETLINK) to be resolved depending on the different "bus" systems?

Related

How is the Hardware address mapped to eth0/eth1 on a Linux(Ubuntu) machine.?

What goes behind the hood when i add a new NIC card to my Ubuntu machine.?
Which program/module is responsible for mapping the HardWare address of the device to a name(eth0/eth1). Where are this mappings(HWaddress1-eth0, HWaddress2-eth1) actually stored.?
As far as I know the kernel itself will name the nics depending on the order they are connected to the bus. This behavior is very similar to SCSI/SATA naming.
Take a look at the output of
lspci
You should find the corresponding network card there. The first column e.g. 0000:00:03.0 contains the following information:
0000 : PCI domain (each domain can contain up to 256 PCI buses)
00 : the bus number the device is attached to
03 : the device number
.0 : PCI device function
(source: http://prefetch.net/articles/linuxpci.html)
under /sys/bus/pci(_express)/devices/ you will find links that match to the lspci output. When you enter the folder of your network card, there are lots of files and folders.
You can do a find and grep
cd /sys/bus/.../devices/0000:00:03.0/
someuser#somemachine:/sys/bus/pci/devices/0000:00:03.0$ find -type f -exec grep 'ethX' /dev/null {} \; 2>/dev/null
where ethX is your device name to get an output like
./virtio0/net/ethX/uevent:INTERFACE=eth0
(in my case a virtual machine with a virtio device)
Since this information is derived from the running kernel I bet you will also find the hardware-address there.
Happy grepping!

Raspberry Pi Zero USB device emulation

I know that the Raspberry Pi Zero supports OTG and USB Peripheral protocols, and there's a lot of cool built in peripherals shown here: https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget?view=all#other-modules
The problem is that I need to emulate a USB Peripheral device that does not appear on this list. I have a vendor ID and product ID for the device, and I'm trying to figure out how exactly to go about doing this. Do I need to modify the OTG USB drivers in the Raspbian kernel? Do I have to completely build my own kernel? Or is there a better option I don't even realize?
Thanks in advance!!
Do I need to modify the OTG USB drivers in the Raspbian kernel?
The answer to your first question is "it depends", but if your device
doesn't do anything too unusual this could be a No: you need not
modify source code for kernel modules nor the kernel.
You're fortunate that Raspbian supports a modern kernel with ConfigFS support. Once you are set up with dtoverlay=dwc2, you can open up a FunctionFS bulk endpoint as root like so:
modprobe libcomposite
modprobe usb_f_fs
cd /sys/kernel/config/usb_gadget
mkdir -p myperipheral; cd myperipheral
echo 0x1234 > idVendor # put actual vendor ID here
echo 0xabcd > idProduct # put actual product ID here
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "My Peripheral" > configs/c.1/strings/0x409/configuration
mkdir functions/ffs.my_func_name
ln -s functions/ffs.my_func_name configs/c.1/
mkdir -p /tmp/mount_point
mount my_func_name -t functionfs /tmp/mount_point
# compile ffs-test from source, then copy and run it from /tmp/mount_point
ls /sys/class/udc > UDC
If you need to emulate the other device more closely, it's up to you to set bcdDevice, bcdUSB, serial number, manufacturer, product string, max power, os_desc, and possibly other fields.
AFAIK FunctionFS does not support isochronous endpoints, interrupt transfers, nor out-of-the-ordinary control transfers. If you require this, you may need to start looking into extending existing gadget modules, with source code here.
Update: When I got home to test this, I encountered a severe caveat with Raspbian. It'll initially fail to create ffs.my_func_name because usb_f_fs is not enabled by default. Although you need not modify any kernel modules, you must recompile with an alternate configuration. make menuconfig -> Device Drivers -> USB support -> USB Gadget Support -> USB functions configurable through configfs / Function filesystem (FunctionFS) + some other modules to test. After uploading a new kernel/modules, I tested the above script on Raspbian 8. I would also recommend setting USB Gadget Drivers / Function Filesystem to (M) in case you resort to the simpler g_ffs legacy module in lieu of ConfigFS.

Read WLAN Link Layer packages using tcpdump/tshark in raspberry pi

I have a raspberry pi, a WLAN stick (Ralink Technology, Corp. RT5370) in monitor mode and tcpdump (+tshark) installed.
Now I want to read link layer packages from a WLAN wristband device that patients in a retirement home use. This device sends link layer data every second in order to be detected by access points using fingerprinting. The content of this packages is not important, only the RSSI values and the MAC of the device is needed.
With my rPi now I wants to detect when a patient is neat to its own flat door in order to open it automatically. For this, the Pi needs to receives this LLC packages so that I can use the associated RSSI value to calculate the distance.
Using Wireshark and Windows (Airpcap) I can read these LLC packages without problems. The output is for example:
35748 152.953461000 00:00:00_00:00:00 57:01:ff:00:00:00 LLC 62 I, N(R)=0, N(S)=0; DSAP NULL LSAP Individual, SSAP 0x1e Command
If I do the same thing on raspbian using tcpdump or tshark, I don't receive data at all.
tcpdump (command is sudo tcpdump llc -i wlan1) returns
tcpdump: 'llc' supported only on raw ATM
Looks like my linux/driver is not able to pass link layer data to tcpdump. How can I enable it?
Thank you for any hint
UPDATE
Thanks to Guy Harris I found a solution
sudo tcpdump -e -i wlan1 type data
returns all LLC packages and the -e value adds all types of mac. Output is something like this where TA is the MAC of the device. I parsed it using python line by line to get the data I needed
02:56:21.346146 11.0 Mb/s 2462 MHz 11b -53dB signal antenna 1 RA:01:40:96:00:00:03 (oui Unknown) TA:00:18:8e:40:62:03 (oui Unknown) DA:00:00:00:00:00:00 (oui Ethernet) SA:00:00:00:00:00:00 (oui Ethernet) LLC, dsap Null (0x00) Individual, ssap OSI (0xfe) Response, ctrl 0x0b: Unnumbered, 0b, Flags [Response], length 24
BR
Stefan
tcpdump: 'llc' supported only on raw ATM
First of all, the filter comes after all the command-line flags, including -i, so, if you're going to be capturing on wlan1 with a filter, what you want is
sudo tcpdump -i wlan1 {filter}
That's how tcpdump works - the filter comes after all the command-line flags and the arguments to those flags, including -i, -r, etc.
Second of all, "llc" means something very specific - from the "pcap-filter" man page (with older versions of libpcap and tcpdump, it's in the tcpdump man page, but the filter expressions aren't understood by tcpdump, they're understood by libpcap, the library tcpdump uses to capture and to read capture files):
llc True if the packet is an ATM packet, for SunATM on Solaris, and
is an LLC-encapsulated packet.
On 802.11, all 802.11 data frames have an 802.2 LLC header, so you want
tcpdump -i wlan1 type data
which will filter out management and control frames (which don't have 802.2 LLC headers).

tcpdump catching mac and rssi in linux

I'm trying to use a wlan adapter (TP-link TL-WN722N) in monitor mode to pick up RSS from signals in the environment (both beacons and clients). What I would like to do is to get the MAC address and RSS value into my own code somehow (preferably python). I'm planning to use these values for a rough estimate of locations of nearby devices.
I've looked into scapy, but it does not seem to provide RSS values.
tcpdump seems to be able to get both values, but I have been unable to catch client devices.
Is it possible?
If so can I filter MAC and RSS somehow?
I got it working with tcpdump!
To setup a monitor mode adapter, you first need to check which interface to use:
iw list
Select the correct phy (for me its phy1) and create an adapter (I called it moni0):
sudo iw phy phy1 interface add moni0 type monitor
Then add your adapter to the ifconfig:
sudo ifconfig moni0 up
See this guide for more details.
I used the following params for tcpdump to get the values that I needed. (you can pipe the output to your program, main.py in my case):
sudo tcpdump -n -e -tttt -vvvv -i moni0 | python main.py
You can find my project here.

In Linux, is there a way to find out which PCI card is plugged into which PCI slot?

In Linux, is there a way to find out which PCI card is plugged into which PCI slot?
/sys/bus/pci/devices/ contains many devices (bridges, CPU channels, etc.) that are not cards and I was not able to find any information about slot-card mappings in the device directories.
You can use
dmidecode –t slot
to find all available pci slots
than you can run
lspci -s <slot number>
command to list device connected to specified slot. You must take bus address from first command and use this address as parameter in second command.
Nebojsa's answer is good, but here's a little more information and an answer to magmabyte's comment.
dmidecode gives you the number of slots, however, those slots are not the only things using the PCI bridge which is why you see many more devices than slots.
Secondly, you may see multiple "devices" per slot, but they are likely just multiple ports on the same card. To give you an example using network interface cards (NICs):
megaman#someserver $ lspci | grep 10Gb
07:00.0 Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (rev 02)
07:00.1 Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (rev 02)
dmidecode indicates that this server has three slots (and it does). Slot 1 has the 10Gb NIC above (you can see that it has 2 ports), slot 2 has a fibre channel card (which also happens to have 2 ports), and finally slot 3 is empty.
There are three physical slots in the server, one is empty, two are filled with multi port cards (an HBA and a NIC).
To answer your question in the comment, the 3 slots you have are the ones indicated by dmidecode and they are likely populated with multi port interface cards.
In my kickstart, I use the following to determine the NIC to use for the OS. For example, some of our servers use an HPE 562SFP+ 2port 10Gb NIC. It would be:
NICPROD=562
USENIC=''
for NIC in /sys/class/net/e*; do
NIC=$(basename ${NIC})
FOUNDNIC=$(lspci -s $(ethtool -i ${NIC} | awk '/bus-info/ { print $2 }' | cut -d: -f2-) -vv | grep -E 'Product Name:')
if [[ "${FOUNDNIC}" == *${NICPROD}* && "${FOUNDNIC}" != *"FLR"* ]]; then
USENIC=${NIC}
break
fi
done
Hopefully this helps?

Resources