Skip to content

Commit 02a68a4

Browse files
Jiri Pirkokuba-moo
authored andcommitted
net: devlink: track netdev with devlink_port assigned
Currently, ethernet drivers are using devlink_port_type_eth_set() and devlink_port_type_clear() to set devlink port type and link to related netdev. Instead of calling them directly, let the driver use SET_NETDEV_DEVLINK_PORT macro to assign devlink_port pointer and let devlink to track it. Note the devlink port pointer is static during the time netdevice is registered. In devlink code, use per-namespace netdev notifier to track the netdevices with devlink_port assigned and change the internal devlink_port type and related type pointer accordingly. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d41c9db commit 02a68a4

File tree

3 files changed

+99
-9
lines changed

3 files changed

+99
-9
lines changed

include/linux/netdevice.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,11 @@ enum netdev_ml_priv_type {
19991999
* registered
20002000
* @offload_xstats_l3: L3 HW stats for this netdevice.
20012001
*
2002+
* @devlink_port: Pointer to related devlink port structure.
2003+
* Assigned by a driver before netdev registration using
2004+
* SET_NETDEV_DEVLINK_PORT macro. This pointer is static
2005+
* during the time netdevice is registered.
2006+
*
20022007
* FIXME: cleanup struct net_device such that network protocol info
20032008
* moves out.
20042009
*/
@@ -2349,9 +2354,22 @@ struct net_device {
23492354
netdevice_tracker watchdog_dev_tracker;
23502355
netdevice_tracker dev_registered_tracker;
23512356
struct rtnl_hw_stats64 *offload_xstats_l3;
2357+
2358+
struct devlink_port *devlink_port;
23522359
};
23532360
#define to_net_dev(d) container_of(d, struct net_device, dev)
23542361

2362+
/*
2363+
* Driver should use this to assign devlink port instance to a netdevice
2364+
* before it registers the netdevice. Therefore devlink_port is static
2365+
* during the netdev lifetime after it is registered.
2366+
*/
2367+
#define SET_NETDEV_DEVLINK_PORT(dev, port) \
2368+
({ \
2369+
WARN_ON((dev)->reg_state != NETREG_UNINITIALIZED); \
2370+
((dev)->devlink_port = (port)); \
2371+
})
2372+
23552373
static inline bool netif_elide_gro(const struct net_device *dev)
23562374
{
23572375
if (!(dev->features & NETIF_F_GRO) || dev->xdp_prog)
@@ -2785,6 +2803,7 @@ enum netdev_cmd {
27852803
NETDEV_PRE_TYPE_CHANGE,
27862804
NETDEV_POST_TYPE_CHANGE,
27872805
NETDEV_POST_INIT,
2806+
NETDEV_PRE_UNINIT,
27882807
NETDEV_RELEASE,
27892808
NETDEV_NOTIFY_PEERS,
27902809
NETDEV_JOIN,

net/core/dev.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,10 +1621,10 @@ const char *netdev_cmd_to_name(enum netdev_cmd cmd)
16211621
N(UP) N(DOWN) N(REBOOT) N(CHANGE) N(REGISTER) N(UNREGISTER)
16221622
N(CHANGEMTU) N(CHANGEADDR) N(GOING_DOWN) N(CHANGENAME) N(FEAT_CHANGE)
16231623
N(BONDING_FAILOVER) N(PRE_UP) N(PRE_TYPE_CHANGE) N(POST_TYPE_CHANGE)
1624-
N(POST_INIT) N(RELEASE) N(NOTIFY_PEERS) N(JOIN) N(CHANGEUPPER)
1625-
N(RESEND_IGMP) N(PRECHANGEMTU) N(CHANGEINFODATA) N(BONDING_INFO)
1626-
N(PRECHANGEUPPER) N(CHANGELOWERSTATE) N(UDP_TUNNEL_PUSH_INFO)
1627-
N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN)
1624+
N(POST_INIT) N(PRE_UNINIT) N(RELEASE) N(NOTIFY_PEERS) N(JOIN)
1625+
N(CHANGEUPPER) N(RESEND_IGMP) N(PRECHANGEMTU) N(CHANGEINFODATA)
1626+
N(BONDING_INFO) N(PRECHANGEUPPER) N(CHANGELOWERSTATE)
1627+
N(UDP_TUNNEL_PUSH_INFO) N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN)
16281628
N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO)
16291629
N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO)
16301630
N(PRE_CHANGEADDR) N(OFFLOAD_XSTATS_ENABLE) N(OFFLOAD_XSTATS_DISABLE)
@@ -10060,7 +10060,7 @@ int register_netdevice(struct net_device *dev)
1006010060
dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED;
1006110061
write_unlock(&dev_base_lock);
1006210062
if (ret)
10063-
goto err_uninit;
10063+
goto err_uninit_notify;
1006410064

1006510065
__netdev_update_features(dev);
1006610066

@@ -10107,6 +10107,8 @@ int register_netdevice(struct net_device *dev)
1010710107
out:
1010810108
return ret;
1010910109

10110+
err_uninit_notify:
10111+
call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev);
1011010112
err_uninit:
1011110113
if (dev->netdev_ops->ndo_uninit)
1011210114
dev->netdev_ops->ndo_uninit(dev);
@@ -10856,6 +10858,8 @@ void unregister_netdevice_many_notify(struct list_head *head,
1085610858
netdev_name_node_alt_flush(dev);
1085710859
netdev_name_node_free(dev->name_node);
1085810860

10861+
call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev);
10862+
1085910863
if (dev->netdev_ops->ndo_uninit)
1086010864
dev->netdev_ops->ndo_uninit(dev);
1086110865

net/core/devlink.c

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct devlink {
7171
refcount_t refcount;
7272
struct completion comp;
7373
struct rcu_head rcu;
74+
struct notifier_block netdevice_nb;
7475
char priv[] __aligned(NETDEV_ALIGN);
7576
};
7677

@@ -9615,6 +9616,9 @@ void devlink_set_features(struct devlink *devlink, u64 features)
96159616
}
96169617
EXPORT_SYMBOL_GPL(devlink_set_features);
96179618

9619+
static int devlink_netdevice_event(struct notifier_block *nb,
9620+
unsigned long event, void *ptr);
9621+
96189622
/**
96199623
* devlink_alloc_ns - Allocate new devlink instance resources
96209624
* in specific namespace
@@ -9645,10 +9649,13 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
96459649

96469650
ret = xa_alloc_cyclic(&devlinks, &devlink->index, devlink, xa_limit_31b,
96479651
&last_id, GFP_KERNEL);
9648-
if (ret < 0) {
9649-
kfree(devlink);
9650-
return NULL;
9651-
}
9652+
if (ret < 0)
9653+
goto err_xa_alloc;
9654+
9655+
devlink->netdevice_nb.notifier_call = devlink_netdevice_event;
9656+
ret = register_netdevice_notifier_net(net, &devlink->netdevice_nb);
9657+
if (ret)
9658+
goto err_register_netdevice_notifier;
96529659

96539660
devlink->dev = dev;
96549661
devlink->ops = ops;
@@ -9675,6 +9682,12 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
96759682
init_completion(&devlink->comp);
96769683

96779684
return devlink;
9685+
9686+
err_register_netdevice_notifier:
9687+
xa_erase(&devlinks, devlink->index);
9688+
err_xa_alloc:
9689+
kfree(devlink);
9690+
return NULL;
96789691
}
96799692
EXPORT_SYMBOL_GPL(devlink_alloc_ns);
96809693

@@ -9828,6 +9841,10 @@ void devlink_free(struct devlink *devlink)
98289841
WARN_ON(!list_empty(&devlink->port_list));
98299842

98309843
xa_destroy(&devlink->snapshot_ids);
9844+
9845+
unregister_netdevice_notifier_net(devlink_net(devlink),
9846+
&devlink->netdevice_nb);
9847+
98319848
xa_erase(&devlinks, devlink->index);
98329849

98339850
kfree(devlink);
@@ -10121,6 +10138,56 @@ void devlink_port_type_clear(struct devlink_port *devlink_port)
1012110138
}
1012210139
EXPORT_SYMBOL_GPL(devlink_port_type_clear);
1012310140

10141+
static int devlink_netdevice_event(struct notifier_block *nb,
10142+
unsigned long event, void *ptr)
10143+
{
10144+
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
10145+
struct devlink_port *devlink_port = netdev->devlink_port;
10146+
struct devlink *devlink;
10147+
10148+
devlink = container_of(nb, struct devlink, netdevice_nb);
10149+
10150+
if (!devlink_port || devlink_port->devlink != devlink)
10151+
return NOTIFY_OK;
10152+
10153+
switch (event) {
10154+
case NETDEV_POST_INIT:
10155+
/* Set the type but not netdev pointer. It is going to be set
10156+
* later on by NETDEV_REGISTER event. Happens once during
10157+
* netdevice register
10158+
*/
10159+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH,
10160+
NULL, true);
10161+
break;
10162+
case NETDEV_REGISTER:
10163+
/* Set the netdev on top of previously set type. Note this
10164+
* event happens also during net namespace change so here
10165+
* we take into account netdev pointer appearing in this
10166+
* namespace.
10167+
*/
10168+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH,
10169+
netdev, true);
10170+
break;
10171+
case NETDEV_UNREGISTER:
10172+
/* Clear netdev pointer, but not the type. This event happens
10173+
* also during net namespace change so we need to clear
10174+
* pointer to netdev that is going to another net namespace.
10175+
*/
10176+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH,
10177+
NULL, true);
10178+
break;
10179+
case NETDEV_PRE_UNINIT:
10180+
/* Clear the type and the netdev pointer. Happens one during
10181+
* netdevice unregister.
10182+
*/
10183+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET,
10184+
NULL, true);
10185+
break;
10186+
}
10187+
10188+
return NOTIFY_OK;
10189+
}
10190+
1012410191
static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
1012510192
enum devlink_port_flavour flavour)
1012610193
{

0 commit comments

Comments
 (0)