Skip to content

Commit c661050

Browse files
leitaodavem330
authored andcommitted
net: create a dummy net_device allocator
It is impossible to use init_dummy_netdev together with alloc_netdev() as the 'setup' argument. This is because alloc_netdev() initializes some fields in the net_device structure, and later init_dummy_netdev() memzero them all. This causes some problems as reported here: https://lore.kernel.org/all/20240322082336.49f110cc@kernel.org/ Split the init_dummy_netdev() function in two. Create a new function called init_dummy_netdev_core() that does not memzero the net_device structure. Then have init_dummy_netdev() memzero-ing and calling init_dummy_netdev_core(), keeping the old behaviour. init_dummy_netdev_core() is the new function that could be called as an argument for alloc_netdev(). Also, create a helper to allocate and initialize dummy net devices, leveraging init_dummy_netdev_core() as the setup argument. This function basically simplify the allocation of dummy devices, by allocating and initializing it. Freeing the device continue to be done through free_netdev() Suggested-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f8d0567 commit c661050

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4519,6 +4519,9 @@ static inline void netif_addr_unlock_bh(struct net_device *dev)
45194519

45204520
void ether_setup(struct net_device *dev);
45214521

4522+
/* Allocate dummy net_device */
4523+
struct net_device *alloc_netdev_dummy(int sizeof_priv);
4524+
45224525
/* Support for loadable net-drivers */
45234526
struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
45244527
unsigned char name_assign_type,

net/core/dev.c

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10420,25 +10420,12 @@ int register_netdevice(struct net_device *dev)
1042010420
}
1042110421
EXPORT_SYMBOL(register_netdevice);
1042210422

10423-
/**
10424-
* init_dummy_netdev - init a dummy network device for NAPI
10425-
* @dev: device to init
10426-
*
10427-
* This takes a network device structure and initializes the minimum
10428-
* amount of fields so it can be used to schedule NAPI polls without
10429-
* registering a full blown interface. This is to be used by drivers
10430-
* that need to tie several hardware interfaces to a single NAPI
10431-
* poll scheduler due to HW limitations.
10423+
/* Initialize the core of a dummy net device.
10424+
* This is useful if you are calling this function after alloc_netdev(),
10425+
* since it does not memset the net_device fields.
1043210426
*/
10433-
void init_dummy_netdev(struct net_device *dev)
10427+
static void init_dummy_netdev_core(struct net_device *dev)
1043410428
{
10435-
/* Clear everything. Note we don't initialize spinlocks
10436-
* as they aren't supposed to be taken by any of the
10437-
* NAPI code and this dummy netdev is supposed to be
10438-
* only ever used for NAPI polls
10439-
*/
10440-
memset(dev, 0, sizeof(struct net_device));
10441-
1044210429
/* make sure we BUG if trying to hit standard
1044310430
* register/unregister code path
1044410431
*/
@@ -10459,8 +10446,28 @@ void init_dummy_netdev(struct net_device *dev)
1045910446
* its refcount.
1046010447
*/
1046110448
}
10462-
EXPORT_SYMBOL_GPL(init_dummy_netdev);
1046310449

10450+
/**
10451+
* init_dummy_netdev - init a dummy network device for NAPI
10452+
* @dev: device to init
10453+
*
10454+
* This takes a network device structure and initializes the minimum
10455+
* amount of fields so it can be used to schedule NAPI polls without
10456+
* registering a full blown interface. This is to be used by drivers
10457+
* that need to tie several hardware interfaces to a single NAPI
10458+
* poll scheduler due to HW limitations.
10459+
*/
10460+
void init_dummy_netdev(struct net_device *dev)
10461+
{
10462+
/* Clear everything. Note we don't initialize spinlocks
10463+
* as they aren't supposed to be taken by any of the
10464+
* NAPI code and this dummy netdev is supposed to be
10465+
* only ever used for NAPI polls
10466+
*/
10467+
memset(dev, 0, sizeof(struct net_device));
10468+
init_dummy_netdev_core(dev);
10469+
}
10470+
EXPORT_SYMBOL_GPL(init_dummy_netdev);
1046410471

1046510472
/**
1046610473
* register_netdev - register a network device
@@ -11080,6 +11087,19 @@ void free_netdev(struct net_device *dev)
1108011087
}
1108111088
EXPORT_SYMBOL(free_netdev);
1108211089

11090+
/**
11091+
* alloc_netdev_dummy - Allocate and initialize a dummy net device.
11092+
* @sizeof_priv: size of private data to allocate space for
11093+
*
11094+
* Return: the allocated net_device on success, NULL otherwise
11095+
*/
11096+
struct net_device *alloc_netdev_dummy(int sizeof_priv)
11097+
{
11098+
return alloc_netdev(sizeof_priv, "dummy#", NET_NAME_UNKNOWN,
11099+
init_dummy_netdev_core);
11100+
}
11101+
EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
11102+
1108311103
/**
1108411104
* synchronize_net - Synchronize with packet receive processing
1108511105
*

0 commit comments

Comments
 (0)