linux, is it possible to get the driver name of a built-in ethernet device? - Page 1
Forum section: electronics / general

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 06:37:38 pm
content: I'm writing a rather peculiar software, that runs in an equally peculiar scenarioBasically I can't have kernel modules, all the devices are "kernel-builtin", and there are about two Tulip cards, each quad-ethernet, plus two more VIA, also quad-ethernetThere are too many network ports ... but that's not the problem, when it comes to the fact that only the Tulips offer "CPU offloading" and are capable of working in extra-jumbo.I work with several kernels, some of the old 4 family, some of the 5 family, some of the 6 family, all compiled for the same target, even if not always both types of network cards are installed.Sometimes only the Tulips, sometimes only the VIAs, sometimes there are also some 3Coms.To make it short, and for how my software works, I would need to know which driver is associated with a network interface.eth0 <---- SoC built-ineth1 <---- Tulips? Via? 3Com? Other? Which kernel driver?...ethN <---- Tulips? Via? 3Com? Other? Which kernel driver?How can I get this information?Code:# ls /sys/class/net/eth*/I looked into something like this, but is seems it doesn't export anything about the kernel driver.As a temporary solution, I identify the driver by the mac-address.That is, I made a table of all the mac-addresses of all the network cards used.But it is not practical .... at the moment it is a file with about 242 lines!

author: Siwastaja
author_rank: Super Contributor
timestamp: May 31, 2025, 06:45:29 pm
content: This problem was recognized... at least 10 years ago, if not more? We got deterministic interface names, which irritated many in the beginning, but has obvious advantages.If you are forced to use 15-year old versions, maybe you could take a look how it's implemented more recently and apply a patch?

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 07:07:30 pm
content: driver_name = get_it(interface name)How?

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 07:08:02 pm
content: Quote from: Siwastaja on May 31, 2025, 06:45:29 pmDon't troll, please.Otherwise, enjoy my ignore list, again.

author: madires
author_rank: Super Contributor
timestamp: May 31, 2025, 07:14:35 pm
content: ethtool -i eth0 | grep driver

author: Traceless
author_rank: Frequent Contributor
timestamp: May 31, 2025, 07:17:59 pm
content: Hi DiTBho,you should be able to get the information you need by using the commandlshw -C network. The output also contains some information that you do not require. If you want to filter those you could uselshw -C network | grep -E "(product|configuration|logical name):". The command also supports alternative output formats like JSON (-json), HTML (-html) or XML (-xml) for easier processing with external tools. If you don't want to rely on lshw being installed or run it as external command you could take a look at its source code and replicate the portions required in your program.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 07:22:10 pm
content: A solution likethisdoesn't see to work with "network devices", as not listed in /dev.I am tempted to hack the kernel to extract the information I need when the kernel driver registers itself and gets its interface name.It would niceDev name -> kernel driver nameE.g.Eth0 -> ppc4xx-netEth1 -> tulip...Eth9 -> viaExported in ? /proc/net/name_driver ?But umm, I have to carefully think about this hack.

author: nctnico
author_rank: Super Contributor
timestamp: May 31, 2025, 08:12:35 pm
content: Use the MAC address but filter by manufacturer. Don't use the entire MAC address!

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 31, 2025, 08:45:09 pm
content: You can obtain the kernel driver name forethXusingreadlink /sys/class/net/ethX/device/driver/module | sed -e 's,^.*/,,'or in your own code, usingreadlinkat()and skipping everything up to and including the last slash, if it has any slashes (it should).Quote from: DiTBho on May 31, 2025, 07:22:10 pmThe device path for Ethernet devices is/sys/class/net/device, so the key thing would be to see what yourudevadm info /sys/class/net/eth0andudevadm info /sys/class/net/eth1so that we can see what you can use in an udev rule to set the device names (just by assigning toNAME).Note that the above does apply even if you use eudev instead of systemd-subsumed udev.If you use mdev or an old-style fixed/dev, then populate/dev/mactabwithdev-namemac-addressand before bringing up any network interfaces, run/sbin/nameif -s(fromnet-toolspackage,official Github source mirror).

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:17:44 pm
content: Code:ls /sys/class/net/eth0/device/driver/0000:00:0a.0/ bind new_id remove_id uevent unbind"module" is not thereI am writing a C application, I need a way to get the information possibly without having to depend on an external program

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:19:01 pm
content: Quote from: Nominal Animal on May 31, 2025, 08:45:09 pmI forgot: I don't need to "change" the device names, and I can't use udev.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:29:45 pm
content: Code:# udevadm info /sys/class/net/eth0P: /devices/pci0000:00/0000:00:0a.0/net/eth0M: eth0R: 0U: netI: 2E: DEVPATH=/devices/pci0000:00/0000:00:0a.0/net/eth0E: SUBSYSTEM=netE: INTERFACE=eth0E: IFINDEX=2E: USEC_INITIALIZED=8738139E: ID_NET_NAMING_SCHEME=v251E: ID_NET_NAME_MAC=enx00264a1bf770E: ID_OUI_FROM_DATABASE=Apple, Inc.E: ID_NET_NAME_PATH=enp0s10E: ID_BUS=pciE: ID_VENDOR_ID=0x10deE: ID_MODEL_ID=0x0ab0E: ID_PCI_CLASS_FROM_DATABASE=Network controllerE: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controllerE: ID_VENDOR_FROM_DATABASE=NVIDIA CorporationE: ID_MODEL_FROM_DATABASE=MCP79 Ethernet (Apple iMac 9,1)E: ID_PATH=pci-0000:00:0a.0E: ID_PATH_TAG=pci-0000_00_0a_0E: ID_NET_DRIVER=forcedeth <------------- this one!E: ID_NET_LINK_FILE=/lib/systemd/network/99-default.linkE: ID_NET_NAME=eth0(Apple MacMini/Intel-2009)It works.But where does it get the driver information from?I would like to replicate the code in C.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:35:58 pm
content: Code:# udevadm info /sys/class/net/eth0/missing option# uname -r2.6.39-apple-minimac-G4does it also work for 2.6 kernels?

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:41:24 pm
content: Quote from: nctnico on May 31, 2025, 08:12:35 pmyeah, that's plan-B"and it's already ready!edit:There is a problem with reprogrammed NICs, anyway.Things with a on-chip (EEPROM) "reprogrammed" mac-address.Fake vendor, crazy mac-address, e.g. "deadcafe00"Umm, and with "firmware defined" mac-address.e.g. PPC4xx boards with u-boot.You can change the mac-address from the env console(envset macaddr deadcafe00), and Linux will simply take what passed from u-boot.Anyway, these two are extrame examples of hobby stuff.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 31, 2025, 09:42:38 pm
content: udev/eudev is a daemon which receives device events using netlink (socket type) from the kernel.The udevadm command queries that daemon as to what information was available at the time the event occurred.Problem is, you don't have anything listening to those events.Doesethtool -iethXreport thedriver:?

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:45:31 pm
content: Code:/sys/class/net/eth0/device/uevent:DRIVER=forcedeth(macmini-intel/2009)Code:/sys/class/net/eth0/device/ueventDRIVER=gem(macmini-pcc/2005)Code:/sys/class/net/eth12/device/uevent:DRIVER=tulip(zserver with DEC nics)it sounds, the information I was looking for

author: Monkeh
author_rank: Super Contributor
timestamp: May 31, 2025, 09:46:03 pm
content: The symlink /sys/class/net/*/device/driver will tell you the driver name just fine. Otherwise, see the ethtool source for inspiration on querying more directly.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:47:57 pm
content: Quote from: Nominal Animal on May 31, 2025, 09:42:38 pmNo, I don't have anything listening to these events, especially on embedded profiled machines.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:51:15 pm
content: Quote from: Monkeh on May 31, 2025, 09:46:03 pmCode:grep "gem" /sys/class/net/eth0/device/driver/0002\:20\:0f.0/ueventDRIVER=gem

author: Monkeh
author_rank: Super Contributor
timestamp: May 31, 2025, 09:54:37 pm
content: Quote from: DiTBho on May 31, 2025, 09:51:15 pmCode:$ basename $(readlink /sys/class/net/eno1/device/driver)e1000e$ basename $(readlink /sys/class/net/enp3s0/device/driver)r8169$ basename $(readlink /sys/class/net/eth0/device/driver)e1000eDoes not require determining any further path.

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 09:57:26 pm
content: Quote from: DiTBho on May 31, 2025, 09:47:57 pmjust emergedCode:2025-05-31--23-00-53---2025-05-31--23-02-00 - [ sys-apps/ethtool ] - success - root@dev2.38/13Code:macmini2-intel # ethtool -i eth0driver: forcedeth <---------- correct!version: 0.64firmware-version:expansion-rom-version:bus-info: 0000:00:0a.0supports-statistics: yessupports-test: yessupports-eeprom-access: nosupports-register-dump: yessupports-priv-flags: no

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 10:12:08 pm
content: Quote from: Monkeh on May 31, 2025, 09:54:37 pmBingo!I have a library, written in C, that implents something similar to "basename"Code:# myfilename_depath "`readlink /sys/class/net/eth0/device/driver`"forcedethAnd I also have something similar to "readlink".I can combine them to get the "driver name" without any external support (exec(...)->fork()?) to the main application, which is written in C.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 31, 2025, 10:35:55 pm
content: Quote from: DiTBho on May 31, 2025, 09:57:26 pm(Edited to fix messy description)Initializestruct ethtool_drvinfoinfoto zeros, but setinfo.cmd = ETHTOOL_GDRVINFO.Initializestruct ifreqreqto zeros, fillreq.if_namewith the network device name (terminated with nul, preferably padded with nuls), and setreq.if_datato point toinfo.Create a socket usingintsockfd= socket(AF_INET, SOCK_DGRAM, 0).Callioctl(sockfd, SIOCETHTOOL, &req).Close the socket usingclose(sockfd).The ioctl filled in theinfostructure, including driver name ininfo.driver, driver version string ininfo.version, and so on.Crude example program:Code:#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <net/if.h>#include <linux/ethtool.h>#include <linux/sockios.h>#include <stdio.h>#include <errno.h>#define DRIVER_NAMELEN (1 + sizeof ((struct ethtool_drvinfo *)0)->driver)int get_driver(char driver, const char *device) {const int device_len = (device) ? strlen(device) : 0;struct ethtool_drvinfo info;struct ifreq req;int fd, err;memset(driver, 0, DRIVER_NAMELEN);memset(&info, 0, sizeof info);info.cmd = ETHTOOL_GDRVINFO;if (device_len < 1 || (size_t)device_len >= sizeof req.ifr_ifrn.ifrn_name) {errno = EINVAL;return -1;}fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd == -1) {return -2; // errno set by socket()}memset(&req, 0, sizeof req);memcpy(req.ifr_ifrn.ifrn_name, device, device_len);req.ifr_data = (void *)&info;if (ioctl(fd, SIOCETHTOOL, &req) == -1) {err = errno;close(fd);errno = err;return -3; // errno set by ioctl()}if (close(fd) == -1) {return -4; // errno set by close()}memcpy(driver, info.driver, sizeof info.driver);return 0;}int main(int argc, char *argv[]) {const char *const arg0 = (argc > 0 && argv && argv && argv) ? argv : "this";if (argc != 2 || !strcmp(argv, "-h") || !strcmp(argv, "--help")) {fprintf(stderr, "\n");fprintf(stderr, "Usage: %s [ -h | --help ]\n", arg0);fprintf(stderr, " %s ethernet-device\n", arg0);fprintf(stderr, "\n");fprintf(stderr, "This program outputs the driver name for the given net device.\n");fprintf(stderr, "\n");return EXIT_SUCCESS;}char driver;int result = get_driver(driver, argv);if (result) {fprintf(stderr, "Error %d: %s.\n", -result, strerror(errno));return EXIT_FAILURE;}printf("%s\n", driver);return EXIT_SUCCESS;}

author: DiTBho
author_rank: Super Contributor
timestamp: May 31, 2025, 11:15:07 pm
content: Quote from: Nominal Animal on May 31, 2025, 10:35:55 pmExcellent!I wrote a simple draft, it works!It's nice that there is a way to "query" for information from the kernel about a specific network interface.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 31, 2025, 11:51:19 pm
content: Note that I edited my post for clarity; I definitely wasn't initially as clear/simple as the actual procedure is! Apologies for changing the discussion history, though.Quote from: DiTBho on May 31, 2025, 11:15:07 pmIt does get messy if you want more in-depth driver-specific data, becauseethtoolis so closely tied to the Linux kernel.Do note that bothnameifandifconfigcan rename an ethernet interface as long as the interface is down, so youcanhave persistent network/ethernet device names even without dynamic device event support (udev/eudev daemon): just add an init step to do that after all network devices have been probed and drivers loaded, but before any network interfaces are enabled/up'd. Then you do know all the network devices, too.

author: macboy
author_rank: Super Contributor
timestamp: June 02, 2025, 03:07:18 am
content: lspci -kWill show kernel module in use for each PCI or PCIe device and kernel modules compatible with each, if more than one. e.g. I have 2.5 GbE cards compatible with r8169 built into kernel and r8125 as a loadable module. It shows both as compatible and which is actually controlling the device.