Reputation: 199
For Linux kernel 2.4 or 2.6 earlier than 2.6.31, the net_device
struct for each registered network device has a private data block associated with it, which is pointed to by the priv
pointer in the net_device
struct. However, for kernel version 2.6.32 or later, the priv
pointer has been deprecated.
I am wondering where the network interface driver's private data can be stored now. Is anyone clear of the relatively new implementation of net_device
struct? Thanks in advance.
Upvotes: 4
Views: 4085
Reputation: 137398
This answer references version 3.14 of the Linux kernel.
The private data is stored at the end of the net_device
structure.
You allocate a net_device
by calling alloc_netdev
, which is just a macro for alloc_netdev_mqs
. The first parameter is int sizeof_priv
, which specifies the amount of additional space you wish to be allocated at the end of the net_device
for your private data.
You access this private data by calling the (inline) function netdev_priv
. By looking at that function, you can see it just returns an aligned pointer after the end of the real struct net_device
:
static inline void *netdev_priv(const struct net_device *dev)
{
return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);
}
I'm going to assume that the developers did this for cache reasons. This way, the private data will fall on the same cache line as the rest of the structure, instead of having to access memory very far away from the net_device
via the priv
pointer.
As an example, the Intel e100 driver defines a private struct nic
in e100.c, and allocates its net_device
in e100_probe
. You see that it passes sizeof(struct nic)
to alloc_etherdev
, which is a convenience function for allocating Ethernet devices:
static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct nic *nic;
int err;
if (!(netdev = alloc_etherdev(sizeof(struct nic))))
return -ENOMEM;
Then to access this private data elsewhere, they call netdev_priv
, as seen here in mdio_write
:
static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
{
struct nic *nic = netdev_priv(netdev);
nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
}
Upvotes: 7