Skip to content

Commit

Permalink
rtnetlink: add alloc() method to rtnl_link_ops
Browse files Browse the repository at this point in the history
In order to make rtnetlink ops that can create different
kinds of devices, like what we want to add to the WWAN
framework, the priv_size and setup parameters aren't quite
sufficient. Make this easier to manage by allowing ops to
allocate their own netdev via an @alloc method that gets
the tb netlink data.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Johannes Berg authored and David S. Miller committed Jun 12, 2021
1 parent 73214a6 commit 8c713dc
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
8 changes: 8 additions & 0 deletions include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
* @maxtype: Highest device specific netlink attribute number
* @policy: Netlink policy for device specific attribute validation
* @validate: Optional validation function for netlink/changelink parameters
* @alloc: netdev allocation function, can be %NULL and is then used
* in place of alloc_netdev_mqs(), in this case @priv_size
* and @setup are unused. Returns a netdev or ERR_PTR().
* @priv_size: sizeof net_device private space
* @setup: net_device setup function
* @newlink: Function for configuring and registering a new device
Expand All @@ -63,6 +66,11 @@ struct rtnl_link_ops {
const char *kind;

size_t priv_size;
struct net_device *(*alloc)(struct nlattr *tb[],
const char *ifname,
unsigned char name_assign_type,
unsigned int num_tx_queues,
unsigned int num_rx_queues);
void (*setup)(struct net_device *dev);

bool netns_refund;
Expand Down
19 changes: 14 additions & 5 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,12 +376,12 @@ int __rtnl_link_register(struct rtnl_link_ops *ops)
if (rtnl_link_ops_get(ops->kind))
return -EEXIST;

/* The check for setup is here because if ops
/* The check for alloc/setup is here because if ops
* does not have that filled up, it is not possible
* to use the ops for creating device. So do not
* fill up dellink as well. That disables rtnl_dellink.
*/
if (ops->setup && !ops->dellink)
if ((ops->alloc || ops->setup) && !ops->dellink)
ops->dellink = unregister_netdevice_queue;

list_add_tail(&ops->list, &link_ops);
Expand Down Expand Up @@ -3165,8 +3165,17 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
return ERR_PTR(-EINVAL);
}

dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type,
ops->setup, num_tx_queues, num_rx_queues);
if (ops->alloc) {
dev = ops->alloc(tb, ifname, name_assign_type,
num_tx_queues, num_rx_queues);
if (IS_ERR(dev))
return dev;
} else {
dev = alloc_netdev_mqs(ops->priv_size, ifname,
name_assign_type, ops->setup,
num_tx_queues, num_rx_queues);
}

if (!dev)
return ERR_PTR(-ENOMEM);

Expand Down Expand Up @@ -3399,7 +3408,7 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
return -EOPNOTSUPP;
}

if (!ops->setup)
if (!ops->alloc && !ops->setup)
return -EOPNOTSUPP;

if (!ifname[0]) {
Expand Down

0 comments on commit 8c713dc

Please sign in to comment.