Skip to content

Commit c65dffc

Browse files
committed
Merge branch 'genetlink-provide-struct-genl_info-to-dumps'
Jakub Kicinski says: ==================== genetlink: provide struct genl_info to dumps One of the biggest (which is not to say only) annoyances with genetlink handling today is that doit and dumpit need some of the same information, but it is passed to them in completely different structs. The implementations commonly end up writing a _fill() method which populates a message and have to pass at least 6 parameters. 3 of which are extracted manually from request info. After a lot of umming and ahing I decided to populate struct genl_info for dumps, without trying to factor out only the common parts. This makes the adoption easiest. In the future we may add a new version of dump which takes struct genl_info *info as the second argument, instead of struct netlink_callback *cb. For now developers have to call genl_info_dump(cb) to get the info. Typical genetlink families no longer get exposed to netlink protocol internals like pid and seq numbers. v3: - correct the condition in ethtool code (patch 10) v2: https://lore.kernel.org/all/20230810233845.2318049-1-kuba@kernel.org/ - replace the GENL_INFO_NTF() macro with init helper - fix the commit messages v1: https://lore.kernel.org/all/20230809182648.1816537-1-kuba@kernel.org/ ==================== Link: https://lore.kernel.org/r/20230814214723.2924989-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 479b322 + f946270 commit c65dffc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+236
-180
lines changed

drivers/block/drbd/drbd_nl.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static int drbd_msg_sprintf_info(struct sk_buff *skb, const char *fmt, ...)
159159
static int drbd_adm_prepare(struct drbd_config_context *adm_ctx,
160160
struct sk_buff *skb, struct genl_info *info, unsigned flags)
161161
{
162-
struct drbd_genlmsghdr *d_in = info->userhdr;
162+
struct drbd_genlmsghdr *d_in = genl_info_userhdr(info);
163163
const u8 cmd = info->genlhdr->cmd;
164164
int err;
165165

@@ -1396,8 +1396,9 @@ static void drbd_suspend_al(struct drbd_device *device)
13961396

13971397
static bool should_set_defaults(struct genl_info *info)
13981398
{
1399-
unsigned flags = ((struct drbd_genlmsghdr*)info->userhdr)->flags;
1400-
return 0 != (flags & DRBD_GENL_F_SET_DEFAULTS);
1399+
struct drbd_genlmsghdr *dh = genl_info_userhdr(info);
1400+
1401+
return 0 != (dh->flags & DRBD_GENL_F_SET_DEFAULTS);
14011402
}
14021403

14031404
static unsigned int drbd_al_extents_max(struct drbd_backing_dev *bdev)
@@ -4276,7 +4277,7 @@ static void device_to_info(struct device_info *info,
42764277
int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
42774278
{
42784279
struct drbd_config_context adm_ctx;
4279-
struct drbd_genlmsghdr *dh = info->userhdr;
4280+
struct drbd_genlmsghdr *dh = genl_info_userhdr(info);
42804281
enum drbd_ret_code retcode;
42814282

42824283
retcode = drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE);

drivers/net/wireguard/netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static int wg_get_device_start(struct netlink_callback *cb)
200200
{
201201
struct wg_device *wg;
202202

203-
wg = lookup_interface(genl_dumpit_info(cb)->attrs, cb->skb);
203+
wg = lookup_interface(genl_info_dump(cb)->attrs, cb->skb);
204204
if (IS_ERR(wg))
205205
return PTR_ERR(wg);
206206
DUMP_CTX(cb)->wg = wg;

include/net/genetlink.h

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ struct genl_family {
9393
* struct genl_info - receiving information
9494
* @snd_seq: sending sequence number
9595
* @snd_portid: netlink portid of sender
96+
* @family: generic netlink family
9697
* @nlhdr: netlink message header
9798
* @genlhdr: generic netlink message header
98-
* @userhdr: user specific header
9999
* @attrs: netlink attributes
100100
* @_net: network namespace
101101
* @user_ptr: user pointers
@@ -104,16 +104,16 @@ struct genl_family {
104104
struct genl_info {
105105
u32 snd_seq;
106106
u32 snd_portid;
107-
struct nlmsghdr * nlhdr;
107+
const struct genl_family *family;
108+
const struct nlmsghdr * nlhdr;
108109
struct genlmsghdr * genlhdr;
109-
void * userhdr;
110110
struct nlattr ** attrs;
111111
possible_net_t _net;
112112
void * user_ptr[2];
113113
struct netlink_ext_ack *extack;
114114
};
115115

116-
static inline struct net *genl_info_net(struct genl_info *info)
116+
static inline struct net *genl_info_net(const struct genl_info *info)
117117
{
118118
return read_pnet(&info->_net);
119119
}
@@ -123,6 +123,11 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
123123
write_pnet(&info->_net, net);
124124
}
125125

126+
static inline void *genl_info_userhdr(const struct genl_info *info)
127+
{
128+
return (u8 *)info->genlhdr + GENL_HDRLEN;
129+
}
130+
126131
#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)
127132

128133
#define GENL_SET_ERR_MSG_FMT(info, msg, args...) \
@@ -244,14 +249,13 @@ struct genl_split_ops {
244249

245250
/**
246251
* struct genl_dumpit_info - info that is available during dumpit op call
247-
* @family: generic netlink family - for internal genl code usage
248252
* @op: generic netlink ops - for internal genl code usage
249253
* @attrs: netlink attributes
254+
* @info: struct genl_info describing the request
250255
*/
251256
struct genl_dumpit_info {
252-
const struct genl_family *family;
253257
struct genl_split_ops op;
254-
struct nlattr **attrs;
258+
struct genl_info info;
255259
};
256260

257261
static inline const struct genl_dumpit_info *
@@ -260,6 +264,38 @@ genl_dumpit_info(struct netlink_callback *cb)
260264
return cb->data;
261265
}
262266

267+
static inline const struct genl_info *
268+
genl_info_dump(struct netlink_callback *cb)
269+
{
270+
return &genl_dumpit_info(cb)->info;
271+
}
272+
273+
/**
274+
* genl_info_init_ntf() - initialize genl_info for notifications
275+
* @info: genl_info struct to set up
276+
* @family: pointer to the genetlink family
277+
* @cmd: command to be used in the notification
278+
*
279+
* Initialize a locally declared struct genl_info to pass to various APIs.
280+
* Intended to be used when creating notifications.
281+
*/
282+
static inline void
283+
genl_info_init_ntf(struct genl_info *info, const struct genl_family *family,
284+
u8 cmd)
285+
{
286+
struct genlmsghdr *hdr = (void *) &info->user_ptr[0];
287+
288+
memset(info, 0, sizeof(*info));
289+
info->family = family;
290+
info->genlhdr = hdr;
291+
hdr->cmd = cmd;
292+
}
293+
294+
static inline bool genl_info_is_ntf(const struct genl_info *info)
295+
{
296+
return !info->nlhdr;
297+
}
298+
263299
int genl_register_family(struct genl_family *family);
264300
int genl_unregister_family(const struct genl_family *family);
265301
void genl_notify(const struct genl_family *family, struct sk_buff *skb,
@@ -268,6 +304,32 @@ void genl_notify(const struct genl_family *family, struct sk_buff *skb,
268304
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
269305
const struct genl_family *family, int flags, u8 cmd);
270306

307+
static inline void *
308+
__genlmsg_iput(struct sk_buff *skb, const struct genl_info *info, int flags)
309+
{
310+
return genlmsg_put(skb, info->snd_portid, info->snd_seq, info->family,
311+
flags, info->genlhdr->cmd);
312+
}
313+
314+
/**
315+
* genlmsg_iput - start genetlink message based on genl_info
316+
* @skb: skb in which message header will be placed
317+
* @info: genl_info as provided to do/dump handlers
318+
*
319+
* Convenience wrapper which starts a genetlink message based on
320+
* information in user request. @info should be either the struct passed
321+
* by genetlink core to do/dump handlers (when constructing replies to
322+
* such requests) or a struct initialized by genl_info_init_ntf()
323+
* when constructing notifications.
324+
*
325+
* Returns pointer to new genetlink header.
326+
*/
327+
static inline void *
328+
genlmsg_iput(struct sk_buff *skb, const struct genl_info *info)
329+
{
330+
return __genlmsg_iput(skb, info, 0);
331+
}
332+
271333
/**
272334
* genlmsg_nlhdr - Obtain netlink header from user specified header
273335
* @user_hdr: user header as returned from genlmsg_put()

net/core/netdev-genl.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
static int
1212
netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp,
13-
u32 portid, u32 seq, int flags, u32 cmd)
13+
const struct genl_info *info)
1414
{
1515
void *hdr;
1616

17-
hdr = genlmsg_put(rsp, portid, seq, &netdev_nl_family, flags, cmd);
17+
hdr = genlmsg_iput(rsp, info);
1818
if (!hdr)
1919
return -EMSGSIZE;
2020

@@ -41,17 +41,20 @@ netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp,
4141
static void
4242
netdev_genl_dev_notify(struct net_device *netdev, int cmd)
4343
{
44+
struct genl_info info;
4445
struct sk_buff *ntf;
4546

4647
if (!genl_has_listeners(&netdev_nl_family, dev_net(netdev),
4748
NETDEV_NLGRP_MGMT))
4849
return;
4950

51+
genl_info_init_ntf(&info, &netdev_nl_family, cmd);
52+
5053
ntf = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
5154
if (!ntf)
5255
return;
5356

54-
if (netdev_nl_dev_fill(netdev, ntf, 0, 0, 0, cmd)) {
57+
if (netdev_nl_dev_fill(netdev, ntf, &info)) {
5558
nlmsg_free(ntf);
5659
return;
5760
}
@@ -80,8 +83,7 @@ int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info)
8083

8184
netdev = __dev_get_by_index(genl_info_net(info), ifindex);
8285
if (netdev)
83-
err = netdev_nl_dev_fill(netdev, rsp, info->snd_portid,
84-
info->snd_seq, 0, info->genlhdr->cmd);
86+
err = netdev_nl_dev_fill(netdev, rsp, info);
8587
else
8688
err = -ENODEV;
8789

@@ -105,10 +107,7 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
105107

106108
rtnl_lock();
107109
for_each_netdev_dump(net, netdev, cb->args[0]) {
108-
err = netdev_nl_dev_fill(netdev, skb,
109-
NETLINK_CB(cb->skb).portid,
110-
cb->nlh->nlmsg_seq, 0,
111-
NETDEV_CMD_DEV_GET);
110+
err = netdev_nl_dev_fill(netdev, skb, genl_info_dump(cb));
112111
if (err < 0)
113112
break;
114113
}

net/devlink/health.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ static int devlink_nl_health_reporter_get_dump_one(struct sk_buff *msg,
390390
int flags)
391391
{
392392
struct devlink_nl_dump_state *state = devlink_dump_state(cb);
393-
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
393+
const struct genl_info *info = genl_info_dump(cb);
394394
struct devlink_health_reporter *reporter;
395395
unsigned long port_index_end = ULONG_MAX;
396396
struct nlattr **attrs = info->attrs;
@@ -1264,7 +1264,7 @@ int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
12641264
static struct devlink_health_reporter *
12651265
devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
12661266
{
1267-
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
1267+
const struct genl_info *info = genl_info_dump(cb);
12681268
struct devlink_health_reporter *reporter;
12691269
struct nlattr **attrs = info->attrs;
12701270
struct devlink *devlink;

net/devlink/leftover.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5201,7 +5201,7 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
52015201
struct devlink_nl_dump_state *state = devlink_dump_state(cb);
52025202
struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
52035203
u64 ret_offset, start_offset, end_offset = U64_MAX;
5204-
struct nlattr **attrs = info->attrs;
5204+
struct nlattr **attrs = info->info.attrs;
52055205
struct devlink_port *port = NULL;
52065206
devlink_chunk_fill_t *region_cb;
52075207
struct devlink_region *region;
@@ -5224,8 +5224,8 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
52245224
goto out_unlock;
52255225
}
52265226

5227-
if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
5228-
index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
5227+
if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
5228+
index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
52295229

52305230
port = devlink_port_get_by_index(devlink, index);
52315231
if (!port) {

net/devlink/netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ static int devlink_nl_inst_iter_dumpit(struct sk_buff *msg,
228228
int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
229229
devlink_nl_dump_one_func_t *dump_one)
230230
{
231-
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
231+
const struct genl_info *info = genl_info_dump(cb);
232232
struct nlattr **attrs = info->attrs;
233233
int flags = NLM_F_MULTI;
234234

net/ethtool/channels.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const struct nla_policy ethnl_channels_get_policy[] = {
2424

2525
static int channels_prepare_data(const struct ethnl_req_info *req_base,
2626
struct ethnl_reply_data *reply_base,
27-
struct genl_info *info)
27+
const struct genl_info *info)
2828
{
2929
struct channels_reply_data *data = CHANNELS_REPDATA(reply_base);
3030
struct net_device *dev = reply_base->dev;

net/ethtool/coalesce.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ const struct nla_policy ethnl_coalesce_get_policy[] = {
5959

6060
static int coalesce_prepare_data(const struct ethnl_req_info *req_base,
6161
struct ethnl_reply_data *reply_base,
62-
struct genl_info *info)
62+
const struct genl_info *info)
6363
{
6464
struct coalesce_reply_data *data = COALESCE_REPDATA(reply_base);
65-
struct netlink_ext_ack *extack = info ? info->extack : NULL;
6665
struct net_device *dev = reply_base->dev;
6766
int ret;
6867

@@ -73,7 +72,8 @@ static int coalesce_prepare_data(const struct ethnl_req_info *req_base,
7372
if (ret < 0)
7473
return ret;
7574
ret = dev->ethtool_ops->get_coalesce(dev, &data->coalesce,
76-
&data->kernel_coalesce, extack);
75+
&data->kernel_coalesce,
76+
info->extack);
7777
ethnl_ops_complete(dev);
7878

7979
return ret;

net/ethtool/debug.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const struct nla_policy ethnl_debug_get_policy[] = {
2323

2424
static int debug_prepare_data(const struct ethnl_req_info *req_base,
2525
struct ethnl_reply_data *reply_base,
26-
struct genl_info *info)
26+
const struct genl_info *info)
2727
{
2828
struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
2929
struct net_device *dev = reply_base->dev;

0 commit comments

Comments
 (0)