1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
7 #include <net/genetlink.h>
10 #include "devl_internal.h"
12 #define DEVLINK_NL_FLAG_NEED_PORT BIT(0)
13 #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1)
14 #define DEVLINK_NL_FLAG_NEED_DEV_LOCK BIT(2)
16 static const struct genl_multicast_group devlink_nl_mcgrps
[] = {
17 [DEVLINK_MCGRP_CONFIG
] = { .name
= DEVLINK_GENL_MCGRP_CONFIG_NAME
},
20 struct devlink_nl_sock_priv
{
21 struct devlink_obj_desc __rcu
*flt
;
22 spinlock_t flt_lock
; /* Protects flt. */
25 static void devlink_nl_sock_priv_init(void *priv
)
27 struct devlink_nl_sock_priv
*sk_priv
= priv
;
29 spin_lock_init(&sk_priv
->flt_lock
);
32 static void devlink_nl_sock_priv_destroy(void *priv
)
34 struct devlink_nl_sock_priv
*sk_priv
= priv
;
35 struct devlink_obj_desc
*flt
;
37 flt
= rcu_dereference_protected(sk_priv
->flt
, true);
41 int devlink_nl_notify_filter_set_doit(struct sk_buff
*skb
,
42 struct genl_info
*info
)
44 struct devlink_nl_sock_priv
*sk_priv
;
45 struct nlattr
**attrs
= info
->attrs
;
46 struct devlink_obj_desc
*flt
;
47 size_t data_offset
= 0;
51 if (attrs
[DEVLINK_ATTR_BUS_NAME
])
52 data_size
= size_add(data_size
,
53 nla_len(attrs
[DEVLINK_ATTR_BUS_NAME
]) + 1);
54 if (attrs
[DEVLINK_ATTR_DEV_NAME
])
55 data_size
= size_add(data_size
,
56 nla_len(attrs
[DEVLINK_ATTR_DEV_NAME
]) + 1);
58 flt
= kzalloc(size_add(sizeof(*flt
), data_size
), GFP_KERNEL
);
62 pos
= (char *) flt
->data
;
63 if (attrs
[DEVLINK_ATTR_BUS_NAME
]) {
64 data_offset
+= nla_strscpy(pos
,
65 attrs
[DEVLINK_ATTR_BUS_NAME
],
70 if (attrs
[DEVLINK_ATTR_DEV_NAME
]) {
71 nla_strscpy(pos
, attrs
[DEVLINK_ATTR_DEV_NAME
],
72 data_size
- data_offset
);
76 if (attrs
[DEVLINK_ATTR_PORT_INDEX
]) {
77 flt
->port_index
= nla_get_u32(attrs
[DEVLINK_ATTR_PORT_INDEX
]);
78 flt
->port_index_valid
= true;
81 /* Don't attach empty filter. */
82 if (!flt
->bus_name
&& !flt
->dev_name
&& !flt
->port_index_valid
) {
87 sk_priv
= genl_sk_priv_get(&devlink_nl_family
, NETLINK_CB(skb
).sk
);
88 if (IS_ERR(sk_priv
)) {
90 return PTR_ERR(sk_priv
);
92 spin_lock(&sk_priv
->flt_lock
);
93 flt
= rcu_replace_pointer(sk_priv
->flt
, flt
,
94 lockdep_is_held(&sk_priv
->flt_lock
));
95 spin_unlock(&sk_priv
->flt_lock
);
100 static bool devlink_obj_desc_match(const struct devlink_obj_desc
*desc
,
101 const struct devlink_obj_desc
*flt
)
103 if (desc
->bus_name
&& flt
->bus_name
&&
104 strcmp(desc
->bus_name
, flt
->bus_name
))
106 if (desc
->dev_name
&& flt
->dev_name
&&
107 strcmp(desc
->dev_name
, flt
->dev_name
))
109 if (desc
->port_index_valid
&& flt
->port_index_valid
&&
110 desc
->port_index
!= flt
->port_index
)
115 int devlink_nl_notify_filter(struct sock
*dsk
, struct sk_buff
*skb
, void *data
)
117 struct devlink_obj_desc
*desc
= data
;
118 struct devlink_nl_sock_priv
*sk_priv
;
119 struct devlink_obj_desc
*flt
;
123 sk_priv
= __genl_sk_priv_get(&devlink_nl_family
, dsk
);
124 if (!IS_ERR_OR_NULL(sk_priv
)) {
125 flt
= rcu_dereference(sk_priv
->flt
);
127 ret
= !devlink_obj_desc_match(desc
, flt
);
133 int devlink_nl_put_nested_handle(struct sk_buff
*msg
, struct net
*net
,
134 struct devlink
*devlink
, int attrtype
)
136 struct nlattr
*nested_attr
;
137 struct net
*devl_net
;
139 nested_attr
= nla_nest_start(msg
, attrtype
);
142 if (devlink_nl_put_handle(msg
, devlink
))
143 goto nla_put_failure
;
146 devl_net
= read_pnet_rcu(&devlink
->_net
);
147 if (!net_eq(net
, devl_net
)) {
148 int id
= peernet2id_alloc(net
, devl_net
, GFP_ATOMIC
);
151 if (nla_put_s32(msg
, DEVLINK_ATTR_NETNS_ID
, id
))
157 nla_nest_end(msg
, nested_attr
);
161 nla_nest_cancel(msg
, nested_attr
);
165 int devlink_nl_msg_reply_and_new(struct sk_buff
**msg
, struct genl_info
*info
)
170 err
= genlmsg_reply(*msg
, info
);
174 *msg
= genlmsg_new(GENLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
181 devlink_get_from_attrs_lock(struct net
*net
, struct nlattr
**attrs
,
184 struct devlink
*devlink
;
189 if (!attrs
[DEVLINK_ATTR_BUS_NAME
] || !attrs
[DEVLINK_ATTR_DEV_NAME
])
190 return ERR_PTR(-EINVAL
);
192 busname
= nla_data(attrs
[DEVLINK_ATTR_BUS_NAME
]);
193 devname
= nla_data(attrs
[DEVLINK_ATTR_DEV_NAME
]);
195 devlinks_xa_for_each_registered_get(net
, index
, devlink
) {
196 if (strcmp(devlink
->dev
->bus
->name
, busname
) == 0 &&
197 strcmp(dev_name(devlink
->dev
), devname
) == 0) {
198 devl_dev_lock(devlink
, dev_lock
);
199 if (devl_is_registered(devlink
))
201 devl_dev_unlock(devlink
, dev_lock
);
203 devlink_put(devlink
);
206 return ERR_PTR(-ENODEV
);
209 static int __devlink_nl_pre_doit(struct sk_buff
*skb
, struct genl_info
*info
,
212 bool dev_lock
= flags
& DEVLINK_NL_FLAG_NEED_DEV_LOCK
;
213 struct devlink_port
*devlink_port
;
214 struct devlink
*devlink
;
217 devlink
= devlink_get_from_attrs_lock(genl_info_net(info
), info
->attrs
,
220 return PTR_ERR(devlink
);
222 info
->user_ptr
[0] = devlink
;
223 if (flags
& DEVLINK_NL_FLAG_NEED_PORT
) {
224 devlink_port
= devlink_port_get_from_info(devlink
, info
);
225 if (IS_ERR(devlink_port
)) {
226 err
= PTR_ERR(devlink_port
);
229 info
->user_ptr
[1] = devlink_port
;
230 } else if (flags
& DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT
) {
231 devlink_port
= devlink_port_get_from_info(devlink
, info
);
232 if (!IS_ERR(devlink_port
))
233 info
->user_ptr
[1] = devlink_port
;
238 devl_dev_unlock(devlink
, dev_lock
);
239 devlink_put(devlink
);
243 int devlink_nl_pre_doit(const struct genl_split_ops
*ops
,
244 struct sk_buff
*skb
, struct genl_info
*info
)
246 return __devlink_nl_pre_doit(skb
, info
, 0);
249 int devlink_nl_pre_doit_port(const struct genl_split_ops
*ops
,
250 struct sk_buff
*skb
, struct genl_info
*info
)
252 return __devlink_nl_pre_doit(skb
, info
, DEVLINK_NL_FLAG_NEED_PORT
);
255 int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops
*ops
,
256 struct sk_buff
*skb
, struct genl_info
*info
)
258 return __devlink_nl_pre_doit(skb
, info
, DEVLINK_NL_FLAG_NEED_DEV_LOCK
);
261 int devlink_nl_pre_doit_port_optional(const struct genl_split_ops
*ops
,
263 struct genl_info
*info
)
265 return __devlink_nl_pre_doit(skb
, info
, DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT
);
268 static void __devlink_nl_post_doit(struct sk_buff
*skb
, struct genl_info
*info
,
271 bool dev_lock
= flags
& DEVLINK_NL_FLAG_NEED_DEV_LOCK
;
272 struct devlink
*devlink
;
274 devlink
= info
->user_ptr
[0];
275 devl_dev_unlock(devlink
, dev_lock
);
276 devlink_put(devlink
);
279 void devlink_nl_post_doit(const struct genl_split_ops
*ops
,
280 struct sk_buff
*skb
, struct genl_info
*info
)
282 __devlink_nl_post_doit(skb
, info
, 0);
286 devlink_nl_post_doit_dev_lock(const struct genl_split_ops
*ops
,
287 struct sk_buff
*skb
, struct genl_info
*info
)
289 __devlink_nl_post_doit(skb
, info
, DEVLINK_NL_FLAG_NEED_DEV_LOCK
);
292 static int devlink_nl_inst_single_dumpit(struct sk_buff
*msg
,
293 struct netlink_callback
*cb
, int flags
,
294 devlink_nl_dump_one_func_t
*dump_one
,
295 struct nlattr
**attrs
)
297 struct devlink
*devlink
;
300 devlink
= devlink_get_from_attrs_lock(sock_net(msg
->sk
), attrs
, false);
302 return PTR_ERR(devlink
);
303 err
= dump_one(msg
, devlink
, cb
, flags
| NLM_F_DUMP_FILTERED
);
305 devl_unlock(devlink
);
306 devlink_put(devlink
);
308 if (err
!= -EMSGSIZE
)
313 static int devlink_nl_inst_iter_dumpit(struct sk_buff
*msg
,
314 struct netlink_callback
*cb
, int flags
,
315 devlink_nl_dump_one_func_t
*dump_one
)
317 struct devlink_nl_dump_state
*state
= devlink_dump_state(cb
);
318 struct devlink
*devlink
;
321 while ((devlink
= devlinks_xa_find_get(sock_net(msg
->sk
),
322 &state
->instance
))) {
325 if (devl_is_registered(devlink
))
326 err
= dump_one(msg
, devlink
, cb
, flags
);
330 devl_unlock(devlink
);
331 devlink_put(devlink
);
338 /* restart sub-object walk for the next instance */
342 if (err
!= -EMSGSIZE
)
347 int devlink_nl_dumpit(struct sk_buff
*msg
, struct netlink_callback
*cb
,
348 devlink_nl_dump_one_func_t
*dump_one
)
350 const struct genl_info
*info
= genl_info_dump(cb
);
351 struct nlattr
**attrs
= info
->attrs
;
352 int flags
= NLM_F_MULTI
;
355 (attrs
[DEVLINK_ATTR_BUS_NAME
] || attrs
[DEVLINK_ATTR_DEV_NAME
]))
356 return devlink_nl_inst_single_dumpit(msg
, cb
, flags
, dump_one
,
359 return devlink_nl_inst_iter_dumpit(msg
, cb
, flags
, dump_one
);
362 struct genl_family devlink_nl_family __ro_after_init
= {
363 .name
= DEVLINK_GENL_NAME
,
364 .version
= DEVLINK_GENL_VERSION
,
366 .parallel_ops
= true,
367 .module
= THIS_MODULE
,
368 .split_ops
= devlink_nl_ops
,
369 .n_split_ops
= ARRAY_SIZE(devlink_nl_ops
),
370 .resv_start_op
= DEVLINK_CMD_SELFTESTS_RUN
+ 1,
371 .mcgrps
= devlink_nl_mcgrps
,
372 .n_mcgrps
= ARRAY_SIZE(devlink_nl_mcgrps
),
373 .sock_priv_size
= sizeof(struct devlink_nl_sock_priv
),
374 .sock_priv_init
= devlink_nl_sock_priv_init
,
375 .sock_priv_destroy
= devlink_nl_sock_priv_destroy
,