xref: /linux/net/ethtool/rss.c (revision 10171b938330f6e625e7dc8dd24a15cc96218172)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <net/netdev_lock.h>
4 
5 #include "common.h"
6 #include "netlink.h"
7 
8 struct rss_req_info {
9 	struct ethnl_req_info		base;
10 	u32				rss_context;
11 };
12 
13 struct rss_reply_data {
14 	struct ethnl_reply_data		base;
15 	bool				has_flow_hash;
16 	bool				no_key_fields;
17 	u32				indir_size;
18 	u32				hkey_size;
19 	u32				hfunc;
20 	u32				input_xfrm;
21 	u32				*indir_table;
22 	u8				*hkey;
23 	int				flow_hash[__ETHTOOL_A_FLOW_CNT];
24 };
25 
26 static const u8 ethtool_rxfh_ft_nl2ioctl[] = {
27 	[ETHTOOL_A_FLOW_ETHER]		= ETHER_FLOW,
28 	[ETHTOOL_A_FLOW_IP4]		= IPV4_FLOW,
29 	[ETHTOOL_A_FLOW_IP6]		= IPV6_FLOW,
30 	[ETHTOOL_A_FLOW_TCP4]		= TCP_V4_FLOW,
31 	[ETHTOOL_A_FLOW_UDP4]		= UDP_V4_FLOW,
32 	[ETHTOOL_A_FLOW_SCTP4]		= SCTP_V4_FLOW,
33 	[ETHTOOL_A_FLOW_AH_ESP4]	= AH_ESP_V4_FLOW,
34 	[ETHTOOL_A_FLOW_TCP6]		= TCP_V6_FLOW,
35 	[ETHTOOL_A_FLOW_UDP6]		= UDP_V6_FLOW,
36 	[ETHTOOL_A_FLOW_SCTP6]		= SCTP_V6_FLOW,
37 	[ETHTOOL_A_FLOW_AH_ESP6]	= AH_ESP_V6_FLOW,
38 	[ETHTOOL_A_FLOW_AH4]		= AH_V4_FLOW,
39 	[ETHTOOL_A_FLOW_ESP4]		= ESP_V4_FLOW,
40 	[ETHTOOL_A_FLOW_AH6]		= AH_V6_FLOW,
41 	[ETHTOOL_A_FLOW_ESP6]		= ESP_V6_FLOW,
42 	[ETHTOOL_A_FLOW_GTPU4]		= GTPU_V4_FLOW,
43 	[ETHTOOL_A_FLOW_GTPU6]		= GTPU_V6_FLOW,
44 	[ETHTOOL_A_FLOW_GTPC4]		= GTPC_V4_FLOW,
45 	[ETHTOOL_A_FLOW_GTPC6]		= GTPC_V6_FLOW,
46 	[ETHTOOL_A_FLOW_GTPC_TEID4]	= GTPC_TEID_V4_FLOW,
47 	[ETHTOOL_A_FLOW_GTPC_TEID6]	= GTPC_TEID_V6_FLOW,
48 	[ETHTOOL_A_FLOW_GTPU_EH4]	= GTPU_EH_V4_FLOW,
49 	[ETHTOOL_A_FLOW_GTPU_EH6]	= GTPU_EH_V6_FLOW,
50 	[ETHTOOL_A_FLOW_GTPU_UL4]	= GTPU_UL_V4_FLOW,
51 	[ETHTOOL_A_FLOW_GTPU_UL6]	= GTPU_UL_V6_FLOW,
52 	[ETHTOOL_A_FLOW_GTPU_DL4]	= GTPU_DL_V4_FLOW,
53 	[ETHTOOL_A_FLOW_GTPU_DL6]	= GTPU_DL_V6_FLOW,
54 };
55 
56 #define RSS_REQINFO(__req_base) \
57 	container_of(__req_base, struct rss_req_info, base)
58 
59 #define RSS_REPDATA(__reply_base) \
60 	container_of(__reply_base, struct rss_reply_data, base)
61 
62 const struct nla_policy ethnl_rss_get_policy[] = {
63 	[ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
64 	[ETHTOOL_A_RSS_CONTEXT] = { .type = NLA_U32 },
65 	[ETHTOOL_A_RSS_START_CONTEXT] = { .type = NLA_U32 },
66 };
67 
68 static int
69 rss_parse_request(struct ethnl_req_info *req_info,
70 		  const struct genl_info *info,
71 		  struct nlattr **tb,
72 		  struct netlink_ext_ack *extack)
73 {
74 	struct rss_req_info *request = RSS_REQINFO(req_info);
75 
76 	if (tb[ETHTOOL_A_RSS_CONTEXT])
77 		request->rss_context = nla_get_u32(tb[ETHTOOL_A_RSS_CONTEXT]);
78 	if (tb[ETHTOOL_A_RSS_START_CONTEXT]) {
79 		NL_SET_BAD_ATTR(extack, tb[ETHTOOL_A_RSS_START_CONTEXT]);
80 		return -EINVAL;
81 	}
82 
83 	return 0;
84 }
85 
86 static void
87 rss_prepare_flow_hash(const struct rss_req_info *req, struct net_device *dev,
88 		      struct rss_reply_data *data, const struct genl_info *info)
89 {
90 	int i;
91 
92 	data->has_flow_hash = false;
93 
94 	if (!dev->ethtool_ops->get_rxfh_fields)
95 		return;
96 	if (req->rss_context && !dev->ethtool_ops->rxfh_per_ctx_fields)
97 		return;
98 
99 	mutex_lock(&dev->ethtool->rss_lock);
100 	for (i = 1; i < __ETHTOOL_A_FLOW_CNT; i++) {
101 		struct ethtool_rxfh_fields fields = {
102 			.flow_type	= ethtool_rxfh_ft_nl2ioctl[i],
103 			.rss_context	= req->rss_context,
104 		};
105 
106 		if (dev->ethtool_ops->get_rxfh_fields(dev, &fields)) {
107 			data->flow_hash[i] = -1; /* Unsupported */
108 			continue;
109 		}
110 
111 		data->flow_hash[i] = fields.data;
112 		data->has_flow_hash = true;
113 	}
114 	mutex_unlock(&dev->ethtool->rss_lock);
115 }
116 
117 static int
118 rss_get_data_alloc(struct net_device *dev, struct rss_reply_data *data)
119 {
120 	const struct ethtool_ops *ops = dev->ethtool_ops;
121 	u32 total_size, indir_bytes;
122 	u8 *rss_config;
123 
124 	data->indir_size = 0;
125 	data->hkey_size = 0;
126 	if (ops->get_rxfh_indir_size)
127 		data->indir_size = ops->get_rxfh_indir_size(dev);
128 	if (ops->get_rxfh_key_size)
129 		data->hkey_size = ops->get_rxfh_key_size(dev);
130 
131 	indir_bytes = data->indir_size * sizeof(u32);
132 	total_size = indir_bytes + data->hkey_size;
133 	rss_config = kzalloc(total_size, GFP_KERNEL);
134 	if (!rss_config)
135 		return -ENOMEM;
136 
137 	if (data->indir_size)
138 		data->indir_table = (u32 *)rss_config;
139 	if (data->hkey_size)
140 		data->hkey = rss_config + indir_bytes;
141 
142 	return 0;
143 }
144 
145 static void rss_get_data_free(const struct rss_reply_data *data)
146 {
147 	kfree(data->indir_table);
148 }
149 
150 static int
151 rss_prepare_get(const struct rss_req_info *request, struct net_device *dev,
152 		struct rss_reply_data *data, const struct genl_info *info)
153 {
154 	const struct ethtool_ops *ops = dev->ethtool_ops;
155 	struct ethtool_rxfh_param rxfh = {};
156 	int ret;
157 
158 	ret = ethnl_ops_begin(dev);
159 	if (ret < 0)
160 		return ret;
161 	mutex_lock(&dev->ethtool->rss_lock);
162 
163 	ret = rss_get_data_alloc(dev, data);
164 	if (ret)
165 		goto out_unlock;
166 
167 	rxfh.indir_size = data->indir_size;
168 	rxfh.indir = data->indir_table;
169 	rxfh.key_size = data->hkey_size;
170 	rxfh.key = data->hkey;
171 
172 	ret = ops->get_rxfh(dev, &rxfh);
173 	if (ret)
174 		goto out_unlock;
175 
176 	data->hfunc = rxfh.hfunc;
177 	data->input_xfrm = rxfh.input_xfrm;
178 out_unlock:
179 	mutex_unlock(&dev->ethtool->rss_lock);
180 	ethnl_ops_complete(dev);
181 	return ret;
182 }
183 
184 static void
185 __rss_prepare_ctx(struct net_device *dev, struct rss_reply_data *data,
186 		  struct ethtool_rxfh_context *ctx)
187 {
188 	if (WARN_ON_ONCE(data->indir_size != ctx->indir_size ||
189 			 data->hkey_size != ctx->key_size))
190 		return;
191 
192 	data->no_key_fields = !dev->ethtool_ops->rxfh_per_ctx_key;
193 
194 	data->hfunc = ctx->hfunc;
195 	data->input_xfrm = ctx->input_xfrm;
196 	memcpy(data->indir_table, ethtool_rxfh_context_indir(ctx),
197 	       data->indir_size * sizeof(u32));
198 	if (data->hkey_size)
199 		memcpy(data->hkey, ethtool_rxfh_context_key(ctx),
200 		       data->hkey_size);
201 }
202 
203 static int
204 rss_prepare_ctx(const struct rss_req_info *request, struct net_device *dev,
205 		struct rss_reply_data *data, const struct genl_info *info)
206 {
207 	struct ethtool_rxfh_context *ctx;
208 	u32 total_size, indir_bytes;
209 	u8 *rss_config;
210 	int ret;
211 
212 	mutex_lock(&dev->ethtool->rss_lock);
213 	ctx = xa_load(&dev->ethtool->rss_ctx, request->rss_context);
214 	if (!ctx) {
215 		ret = -ENOENT;
216 		goto out_unlock;
217 	}
218 
219 	data->indir_size = ctx->indir_size;
220 	data->hkey_size = ctx->key_size;
221 
222 	indir_bytes = data->indir_size * sizeof(u32);
223 	total_size = indir_bytes + data->hkey_size;
224 	rss_config = kzalloc(total_size, GFP_KERNEL);
225 	if (!rss_config) {
226 		ret = -ENOMEM;
227 		goto out_unlock;
228 	}
229 
230 	data->indir_table = (u32 *)rss_config;
231 	if (data->hkey_size)
232 		data->hkey = rss_config + indir_bytes;
233 
234 	__rss_prepare_ctx(dev, data, ctx);
235 
236 	ret = 0;
237 out_unlock:
238 	mutex_unlock(&dev->ethtool->rss_lock);
239 	return ret;
240 }
241 
242 static int
243 rss_prepare(const struct rss_req_info *request, struct net_device *dev,
244 	    struct rss_reply_data *data, const struct genl_info *info)
245 {
246 	rss_prepare_flow_hash(request, dev, data, info);
247 
248 	/* Coming from RSS_SET, driver may only have flow_hash_fields ops */
249 	if (!dev->ethtool_ops->get_rxfh)
250 		return 0;
251 
252 	if (request->rss_context)
253 		return rss_prepare_ctx(request, dev, data, info);
254 	return rss_prepare_get(request, dev, data, info);
255 }
256 
257 static int
258 rss_prepare_data(const struct ethnl_req_info *req_base,
259 		 struct ethnl_reply_data *reply_base,
260 		 const struct genl_info *info)
261 {
262 	struct rss_reply_data *data = RSS_REPDATA(reply_base);
263 	struct rss_req_info *request = RSS_REQINFO(req_base);
264 	struct net_device *dev = reply_base->dev;
265 	const struct ethtool_ops *ops;
266 
267 	ops = dev->ethtool_ops;
268 	if (!ops->get_rxfh)
269 		return -EOPNOTSUPP;
270 
271 	/* Some drivers don't handle rss_context */
272 	if (request->rss_context && !ops->create_rxfh_context)
273 		return -EOPNOTSUPP;
274 
275 	return rss_prepare(request, dev, data, info);
276 }
277 
278 static int
279 rss_reply_size(const struct ethnl_req_info *req_base,
280 	       const struct ethnl_reply_data *reply_base)
281 {
282 	const struct rss_reply_data *data = RSS_REPDATA(reply_base);
283 	int len;
284 
285 	len = nla_total_size(sizeof(u32)) +	/* _RSS_CONTEXT */
286 	      nla_total_size(sizeof(u32)) +	/* _RSS_HFUNC */
287 	      nla_total_size(sizeof(u32)) +	/* _RSS_INPUT_XFRM */
288 	      nla_total_size(sizeof(u32) * data->indir_size) + /* _RSS_INDIR */
289 	      nla_total_size(data->hkey_size) + /* _RSS_HKEY */
290 	      nla_total_size(0) +		/* _RSS_FLOW_HASH */
291 		nla_total_size(sizeof(u32)) * ETHTOOL_A_FLOW_MAX +
292 	      0;
293 
294 	return len;
295 }
296 
297 static int
298 rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
299 	       const struct ethnl_reply_data *reply_base)
300 {
301 	const struct rss_reply_data *data = RSS_REPDATA(reply_base);
302 	struct rss_req_info *request = RSS_REQINFO(req_base);
303 
304 	if (request->rss_context &&
305 	    nla_put_u32(skb, ETHTOOL_A_RSS_CONTEXT, request->rss_context))
306 		return -EMSGSIZE;
307 
308 	if ((data->indir_size &&
309 	     nla_put(skb, ETHTOOL_A_RSS_INDIR,
310 		     sizeof(u32) * data->indir_size, data->indir_table)))
311 		return -EMSGSIZE;
312 
313 	if (!data->no_key_fields &&
314 	    ((data->hfunc &&
315 	      nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) ||
316 	     (data->input_xfrm &&
317 	      nla_put_u32(skb, ETHTOOL_A_RSS_INPUT_XFRM, data->input_xfrm)) ||
318 	     (data->hkey_size &&
319 	      nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))))
320 		return -EMSGSIZE;
321 
322 	if (data->has_flow_hash) {
323 		struct nlattr *nest;
324 		int i;
325 
326 		nest = nla_nest_start(skb, ETHTOOL_A_RSS_FLOW_HASH);
327 		if (!nest)
328 			return -EMSGSIZE;
329 
330 		for (i = 1; i < __ETHTOOL_A_FLOW_CNT; i++) {
331 			if (data->flow_hash[i] >= 0 &&
332 			    nla_put_uint(skb, i, data->flow_hash[i])) {
333 				nla_nest_cancel(skb, nest);
334 				return -EMSGSIZE;
335 			}
336 		}
337 
338 		nla_nest_end(skb, nest);
339 	}
340 
341 	return 0;
342 }
343 
344 static void rss_cleanup_data(struct ethnl_reply_data *reply_base)
345 {
346 	const struct rss_reply_data *data = RSS_REPDATA(reply_base);
347 
348 	rss_get_data_free(data);
349 }
350 
351 struct rss_nl_dump_ctx {
352 	unsigned long		ifindex;
353 	unsigned long		ctx_idx;
354 
355 	/* User wants to only dump contexts from given ifindex */
356 	unsigned int		match_ifindex;
357 	unsigned int		start_ctx;
358 };
359 
360 static struct rss_nl_dump_ctx *rss_dump_ctx(struct netlink_callback *cb)
361 {
362 	NL_ASSERT_CTX_FITS(struct rss_nl_dump_ctx);
363 
364 	return (struct rss_nl_dump_ctx *)cb->ctx;
365 }
366 
367 int ethnl_rss_dump_start(struct netlink_callback *cb)
368 {
369 	const struct genl_info *info = genl_info_dump(cb);
370 	struct rss_nl_dump_ctx *ctx = rss_dump_ctx(cb);
371 	struct ethnl_req_info req_info = {};
372 	struct nlattr **tb = info->attrs;
373 	int ret;
374 
375 	/* Filtering by context not supported */
376 	if (tb[ETHTOOL_A_RSS_CONTEXT]) {
377 		NL_SET_BAD_ATTR(info->extack, tb[ETHTOOL_A_RSS_CONTEXT]);
378 		return -EINVAL;
379 	}
380 	if (tb[ETHTOOL_A_RSS_START_CONTEXT]) {
381 		ctx->start_ctx = nla_get_u32(tb[ETHTOOL_A_RSS_START_CONTEXT]);
382 		ctx->ctx_idx = ctx->start_ctx;
383 	}
384 
385 	ret = ethnl_parse_header_dev_get(&req_info,
386 					 tb[ETHTOOL_A_RSS_HEADER],
387 					 sock_net(cb->skb->sk), cb->extack,
388 					 false);
389 	if (req_info.dev) {
390 		ctx->match_ifindex = req_info.dev->ifindex;
391 		ctx->ifindex = ctx->match_ifindex;
392 		ethnl_parse_header_dev_put(&req_info);
393 		req_info.dev = NULL;
394 	}
395 
396 	return ret;
397 }
398 
399 static int
400 rss_dump_one_ctx(struct sk_buff *skb, struct netlink_callback *cb,
401 		 struct net_device *dev, u32 rss_context)
402 {
403 	const struct genl_info *info = genl_info_dump(cb);
404 	struct rss_reply_data data = {};
405 	struct rss_req_info req = {};
406 	void *ehdr;
407 	int ret;
408 
409 	req.rss_context = rss_context;
410 
411 	ehdr = ethnl_dump_put(skb, cb, ETHTOOL_MSG_RSS_GET_REPLY);
412 	if (!ehdr)
413 		return -EMSGSIZE;
414 
415 	ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_RSS_HEADER);
416 	if (ret < 0)
417 		goto err_cancel;
418 
419 	ret = rss_prepare(&req, dev, &data, info);
420 	if (ret)
421 		goto err_cancel;
422 
423 	ret = rss_fill_reply(skb, &req.base, &data.base);
424 	if (ret)
425 		goto err_cleanup;
426 	genlmsg_end(skb, ehdr);
427 
428 	rss_cleanup_data(&data.base);
429 	return 0;
430 
431 err_cleanup:
432 	rss_cleanup_data(&data.base);
433 err_cancel:
434 	genlmsg_cancel(skb, ehdr);
435 	return ret;
436 }
437 
438 static int
439 rss_dump_one_dev(struct sk_buff *skb, struct netlink_callback *cb,
440 		 struct net_device *dev)
441 {
442 	struct rss_nl_dump_ctx *ctx = rss_dump_ctx(cb);
443 	int ret;
444 
445 	if (!dev->ethtool_ops->get_rxfh)
446 		return 0;
447 
448 	if (!ctx->ctx_idx) {
449 		ret = rss_dump_one_ctx(skb, cb, dev, 0);
450 		if (ret)
451 			return ret;
452 		ctx->ctx_idx++;
453 	}
454 
455 	for (; xa_find(&dev->ethtool->rss_ctx, &ctx->ctx_idx,
456 		       ULONG_MAX, XA_PRESENT); ctx->ctx_idx++) {
457 		ret = rss_dump_one_ctx(skb, cb, dev, ctx->ctx_idx);
458 		if (ret)
459 			return ret;
460 	}
461 	ctx->ctx_idx = ctx->start_ctx;
462 
463 	return 0;
464 }
465 
466 int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
467 {
468 	struct rss_nl_dump_ctx *ctx = rss_dump_ctx(cb);
469 	struct net *net = sock_net(skb->sk);
470 	struct net_device *dev;
471 	int ret = 0;
472 
473 	rtnl_lock();
474 	for_each_netdev_dump(net, dev, ctx->ifindex) {
475 		if (ctx->match_ifindex && ctx->match_ifindex != ctx->ifindex)
476 			break;
477 
478 		netdev_lock_ops(dev);
479 		ret = rss_dump_one_dev(skb, cb, dev);
480 		netdev_unlock_ops(dev);
481 		if (ret)
482 			break;
483 	}
484 	rtnl_unlock();
485 
486 	return ret;
487 }
488 
489 /* RSS_NTF */
490 
491 static void ethnl_rss_delete_notify(struct net_device *dev, u32 rss_context)
492 {
493 	struct sk_buff *ntf;
494 	size_t ntf_size;
495 	void *hdr;
496 
497 	ntf_size = ethnl_reply_header_size() +
498 		nla_total_size(sizeof(u32));	/* _RSS_CONTEXT */
499 
500 	ntf = genlmsg_new(ntf_size, GFP_KERNEL);
501 	if (!ntf)
502 		goto out_warn;
503 
504 	hdr = ethnl_bcastmsg_put(ntf, ETHTOOL_MSG_RSS_DELETE_NTF);
505 	if (!hdr)
506 		goto out_free_ntf;
507 
508 	if (ethnl_fill_reply_header(ntf, dev, ETHTOOL_A_RSS_HEADER) ||
509 	    nla_put_u32(ntf, ETHTOOL_A_RSS_CONTEXT, rss_context))
510 		goto out_free_ntf;
511 
512 	genlmsg_end(ntf, hdr);
513 	if (ethnl_multicast(ntf, dev))
514 		goto out_warn;
515 
516 	return;
517 
518 out_free_ntf:
519 	nlmsg_free(ntf);
520 out_warn:
521 	pr_warn_once("Failed to send a RSS delete notification");
522 }
523 
524 void ethtool_rss_notify(struct net_device *dev, u32 type, u32 rss_context)
525 {
526 	struct rss_req_info req_info = {
527 		.rss_context = rss_context,
528 	};
529 
530 	if (type == ETHTOOL_MSG_RSS_DELETE_NTF)
531 		ethnl_rss_delete_notify(dev, rss_context);
532 	else
533 		ethnl_notify(dev, type, &req_info.base);
534 }
535 
536 /* RSS_SET */
537 
538 #define RFH_MASK (RXH_L2DA | RXH_VLAN | RXH_IP_SRC | RXH_IP_DST | \
539 		  RXH_L3_PROTO | RXH_L4_B_0_1 | RXH_L4_B_2_3 |	  \
540 		  RXH_GTP_TEID | RXH_DISCARD)
541 #define RFH_MASKv6 (RFH_MASK | RXH_IP6_FL)
542 
543 static const struct nla_policy ethnl_rss_flows_policy[] = {
544 	[ETHTOOL_A_FLOW_ETHER]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
545 	[ETHTOOL_A_FLOW_IP4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
546 	[ETHTOOL_A_FLOW_IP6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
547 	[ETHTOOL_A_FLOW_TCP4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
548 	[ETHTOOL_A_FLOW_UDP4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
549 	[ETHTOOL_A_FLOW_SCTP4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
550 	[ETHTOOL_A_FLOW_AH_ESP4]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
551 	[ETHTOOL_A_FLOW_TCP6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
552 	[ETHTOOL_A_FLOW_UDP6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
553 	[ETHTOOL_A_FLOW_SCTP6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
554 	[ETHTOOL_A_FLOW_AH_ESP6]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
555 	[ETHTOOL_A_FLOW_AH4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
556 	[ETHTOOL_A_FLOW_ESP4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
557 	[ETHTOOL_A_FLOW_AH6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
558 	[ETHTOOL_A_FLOW_ESP6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
559 	[ETHTOOL_A_FLOW_GTPU4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
560 	[ETHTOOL_A_FLOW_GTPU6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
561 	[ETHTOOL_A_FLOW_GTPC4]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
562 	[ETHTOOL_A_FLOW_GTPC6]		= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
563 	[ETHTOOL_A_FLOW_GTPC_TEID4]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
564 	[ETHTOOL_A_FLOW_GTPC_TEID6]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
565 	[ETHTOOL_A_FLOW_GTPU_EH4]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
566 	[ETHTOOL_A_FLOW_GTPU_EH6]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
567 	[ETHTOOL_A_FLOW_GTPU_UL4]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
568 	[ETHTOOL_A_FLOW_GTPU_UL6]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
569 	[ETHTOOL_A_FLOW_GTPU_DL4]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASK),
570 	[ETHTOOL_A_FLOW_GTPU_DL6]	= NLA_POLICY_MASK(NLA_UINT, RFH_MASKv6),
571 };
572 
573 const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_FLOW_HASH + 1] = {
574 	[ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
575 	[ETHTOOL_A_RSS_CONTEXT] = { .type = NLA_U32, },
576 	[ETHTOOL_A_RSS_HFUNC] = NLA_POLICY_MIN(NLA_U32, 1),
577 	[ETHTOOL_A_RSS_INDIR] = { .type = NLA_BINARY, },
578 	[ETHTOOL_A_RSS_HKEY] = NLA_POLICY_MIN(NLA_BINARY, 1),
579 	[ETHTOOL_A_RSS_INPUT_XFRM] =
580 		NLA_POLICY_MAX(NLA_U32, RXH_XFRM_SYM_OR_XOR),
581 	[ETHTOOL_A_RSS_FLOW_HASH] = NLA_POLICY_NESTED(ethnl_rss_flows_policy),
582 };
583 
584 static int
585 ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
586 {
587 	const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
588 	struct rss_req_info *request = RSS_REQINFO(req_info);
589 	struct nlattr **tb = info->attrs;
590 	struct nlattr *bad_attr = NULL;
591 	u32 input_xfrm;
592 
593 	if (request->rss_context && !ops->create_rxfh_context)
594 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_CONTEXT];
595 
596 	if (request->rss_context && !ops->rxfh_per_ctx_key) {
597 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HFUNC];
598 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HKEY];
599 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
600 	}
601 
602 	input_xfrm = nla_get_u32_default(tb[ETHTOOL_A_RSS_INPUT_XFRM], 0);
603 	if (input_xfrm & ~ops->supported_input_xfrm)
604 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
605 
606 	if (tb[ETHTOOL_A_RSS_FLOW_HASH] && !ops->set_rxfh_fields)
607 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_FLOW_HASH];
608 	if (request->rss_context &&
609 	    tb[ETHTOOL_A_RSS_FLOW_HASH] && !ops->rxfh_per_ctx_fields)
610 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_FLOW_HASH];
611 
612 	if (bad_attr) {
613 		NL_SET_BAD_ATTR(info->extack, bad_attr);
614 		return -EOPNOTSUPP;
615 	}
616 
617 	return 1;
618 }
619 
620 static int
621 rss_set_prep_indir(struct net_device *dev, struct genl_info *info,
622 		   struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh,
623 		   bool *reset, bool *mod)
624 {
625 	struct netlink_ext_ack *extack = info->extack;
626 	struct nlattr **tb = info->attrs;
627 	size_t alloc_size;
628 	int num_rx_rings;
629 	u32 user_size;
630 	int i, err;
631 
632 	if (!tb[ETHTOOL_A_RSS_INDIR])
633 		return 0;
634 	if (!data->indir_size)
635 		return -EOPNOTSUPP;
636 
637 	err = ethtool_get_rx_ring_count(dev);
638 	if (err < 0)
639 		return err;
640 	num_rx_rings = err;
641 
642 	if (nla_len(tb[ETHTOOL_A_RSS_INDIR]) % 4) {
643 		NL_SET_BAD_ATTR(info->extack, tb[ETHTOOL_A_RSS_INDIR]);
644 		return -EINVAL;
645 	}
646 	user_size = nla_len(tb[ETHTOOL_A_RSS_INDIR]) / 4;
647 	if (!user_size) {
648 		if (rxfh->rss_context) {
649 			NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_RSS_INDIR],
650 					    "can't reset table for a context");
651 			return -EINVAL;
652 		}
653 		*reset = true;
654 	} else if (data->indir_size % user_size) {
655 		NL_SET_ERR_MSG_ATTR_FMT(extack, tb[ETHTOOL_A_RSS_INDIR],
656 					"size (%d) mismatch with device indir table (%d)",
657 					user_size, data->indir_size);
658 		return -EINVAL;
659 	}
660 
661 	rxfh->indir_size = data->indir_size;
662 	alloc_size = array_size(data->indir_size, sizeof(rxfh->indir[0]));
663 	rxfh->indir = kzalloc(alloc_size, GFP_KERNEL);
664 	if (!rxfh->indir)
665 		return -ENOMEM;
666 
667 	nla_memcpy(rxfh->indir, tb[ETHTOOL_A_RSS_INDIR], alloc_size);
668 	for (i = 0; i < user_size; i++) {
669 		if (rxfh->indir[i] < num_rx_rings)
670 			continue;
671 
672 		NL_SET_ERR_MSG_ATTR_FMT(extack, tb[ETHTOOL_A_RSS_INDIR],
673 					"entry %d: queue out of range (%d)",
674 					i, rxfh->indir[i]);
675 		err = -EINVAL;
676 		goto err_free;
677 	}
678 
679 	if (user_size) {
680 		/* Replicate the user-provided table to fill the device table */
681 		for (i = user_size; i < data->indir_size; i++)
682 			rxfh->indir[i] = rxfh->indir[i % user_size];
683 	} else {
684 		for (i = 0; i < data->indir_size; i++)
685 			rxfh->indir[i] =
686 				ethtool_rxfh_indir_default(i, num_rx_rings);
687 	}
688 
689 	*mod |= memcmp(rxfh->indir, data->indir_table, data->indir_size);
690 
691 	return user_size;
692 
693 err_free:
694 	kfree(rxfh->indir);
695 	rxfh->indir = NULL;
696 	return err;
697 }
698 
699 static int
700 rss_set_prep_hkey(struct net_device *dev, struct genl_info *info,
701 		  struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh,
702 		  bool *mod)
703 {
704 	struct nlattr **tb = info->attrs;
705 
706 	if (!tb[ETHTOOL_A_RSS_HKEY])
707 		return 0;
708 
709 	if (nla_len(tb[ETHTOOL_A_RSS_HKEY]) != data->hkey_size) {
710 		NL_SET_BAD_ATTR(info->extack, tb[ETHTOOL_A_RSS_HKEY]);
711 		return -EINVAL;
712 	}
713 
714 	rxfh->key_size = data->hkey_size;
715 	rxfh->key = kmemdup(data->hkey, data->hkey_size, GFP_KERNEL);
716 	if (!rxfh->key)
717 		return -ENOMEM;
718 
719 	ethnl_update_binary(rxfh->key, rxfh->key_size, tb[ETHTOOL_A_RSS_HKEY],
720 			    mod);
721 	return 0;
722 }
723 
724 static int
725 rss_check_rxfh_fields_sym(struct net_device *dev, struct genl_info *info,
726 			  struct rss_reply_data *data, bool xfrm_sym)
727 {
728 	struct nlattr **tb = info->attrs;
729 	int i;
730 
731 	if (!xfrm_sym)
732 		return 0;
733 	if (!data->has_flow_hash) {
734 		NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_RSS_INPUT_XFRM],
735 				    "hash field config not reported");
736 		return -EINVAL;
737 	}
738 
739 	for (i = 1; i < __ETHTOOL_A_FLOW_CNT; i++)
740 		if (data->flow_hash[i] >= 0 &&
741 		    !ethtool_rxfh_config_is_sym(data->flow_hash[i])) {
742 			NL_SET_ERR_MSG_ATTR(info->extack,
743 					    tb[ETHTOOL_A_RSS_INPUT_XFRM],
744 					    "hash field config is not symmetric");
745 			return -EINVAL;
746 		}
747 
748 	return 0;
749 }
750 
751 static int
752 ethnl_set_rss_fields(struct net_device *dev, struct genl_info *info,
753 		     u32 rss_context, struct rss_reply_data *data,
754 		     bool xfrm_sym, bool *mod)
755 {
756 	struct nlattr *flow_nest = info->attrs[ETHTOOL_A_RSS_FLOW_HASH];
757 	struct nlattr *flows[ETHTOOL_A_FLOW_MAX + 1];
758 	const struct ethtool_ops *ops;
759 	int i, ret;
760 
761 	ops = dev->ethtool_ops;
762 
763 	ret = rss_check_rxfh_fields_sym(dev, info, data, xfrm_sym);
764 	if (ret)
765 		return ret;
766 
767 	if (!flow_nest)
768 		return 0;
769 
770 	ret = nla_parse_nested(flows, ARRAY_SIZE(ethnl_rss_flows_policy) - 1,
771 			       flow_nest, ethnl_rss_flows_policy, info->extack);
772 	if (ret < 0)
773 		return ret;
774 
775 	for (i = 1; i < __ETHTOOL_A_FLOW_CNT; i++) {
776 		struct ethtool_rxfh_fields fields = {
777 			.flow_type	= ethtool_rxfh_ft_nl2ioctl[i],
778 			.rss_context	= rss_context,
779 		};
780 
781 		if (!flows[i])
782 			continue;
783 
784 		fields.data = nla_get_u32(flows[i]);
785 		if (data->has_flow_hash && data->flow_hash[i] == fields.data)
786 			continue;
787 
788 		if (xfrm_sym && !ethtool_rxfh_config_is_sym(fields.data)) {
789 			NL_SET_ERR_MSG_ATTR(info->extack, flows[i],
790 					    "conflict with xfrm-input");
791 			return -EINVAL;
792 		}
793 
794 		ret = ops->set_rxfh_fields(dev, &fields, info->extack);
795 		if (ret)
796 			return ret;
797 
798 		*mod = true;
799 	}
800 
801 	return 0;
802 }
803 
804 static void
805 rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
806 		   struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh)
807 {
808 	int i;
809 
810 	if (rxfh->indir) {
811 		for (i = 0; i < data->indir_size; i++)
812 			ethtool_rxfh_context_indir(ctx)[i] = rxfh->indir[i];
813 		ctx->indir_configured = !!nla_len(tb[ETHTOOL_A_RSS_INDIR]);
814 	}
815 	if (rxfh->key) {
816 		memcpy(ethtool_rxfh_context_key(ctx), rxfh->key,
817 		       data->hkey_size);
818 		ctx->key_configured = !!rxfh->key_size;
819 	}
820 	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE)
821 		ctx->hfunc = rxfh->hfunc;
822 	if (rxfh->input_xfrm != RXH_XFRM_NO_CHANGE)
823 		ctx->input_xfrm = rxfh->input_xfrm;
824 }
825 
826 static int
827 ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
828 {
829 	struct rss_req_info *request = RSS_REQINFO(req_info);
830 	bool indir_reset = false, indir_mod, xfrm_sym;
831 	struct ethtool_rxfh_context *ctx = NULL;
832 	struct net_device *dev = req_info->dev;
833 	bool mod = false, fields_mod = false;
834 	struct ethtool_rxfh_param rxfh = {};
835 	struct nlattr **tb = info->attrs;
836 	struct rss_reply_data data = {};
837 	const struct ethtool_ops *ops;
838 	u32 indir_user_size;
839 	int ret;
840 
841 	ops = dev->ethtool_ops;
842 	data.base.dev = dev;
843 
844 	ret = rss_prepare(request, dev, &data, info);
845 	if (ret)
846 		return ret;
847 
848 	rxfh.rss_context = request->rss_context;
849 
850 	ret = rss_set_prep_indir(dev, info, &data, &rxfh, &indir_reset, &mod);
851 	if (ret < 0)
852 		goto exit_clean_data;
853 	indir_user_size = ret;
854 	indir_mod = !!tb[ETHTOOL_A_RSS_INDIR];
855 
856 	rxfh.hfunc = data.hfunc;
857 	ethnl_update_u8(&rxfh.hfunc, tb[ETHTOOL_A_RSS_HFUNC], &mod);
858 	if (rxfh.hfunc == data.hfunc)
859 		rxfh.hfunc = ETH_RSS_HASH_NO_CHANGE;
860 
861 	ret = rss_set_prep_hkey(dev, info, &data, &rxfh, &mod);
862 	if (ret)
863 		goto exit_free_indir;
864 
865 	rxfh.input_xfrm = data.input_xfrm;
866 	ethnl_update_u8(&rxfh.input_xfrm, tb[ETHTOOL_A_RSS_INPUT_XFRM], &mod);
867 	xfrm_sym = rxfh.input_xfrm || data.input_xfrm;
868 	if (rxfh.input_xfrm == data.input_xfrm)
869 		rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
870 
871 	mutex_lock(&dev->ethtool->rss_lock);
872 	if (request->rss_context) {
873 		ctx = xa_load(&dev->ethtool->rss_ctx, request->rss_context);
874 		if (!ctx) {
875 			ret = -ENOENT;
876 			goto exit_unlock;
877 		}
878 	}
879 
880 	ret = ethnl_set_rss_fields(dev, info, request->rss_context,
881 				   &data, xfrm_sym, &fields_mod);
882 	if (ret)
883 		goto exit_unlock;
884 
885 	if (!mod)
886 		ret = 0; /* nothing to tell the driver */
887 	else if (!ops->set_rxfh)
888 		ret = -EOPNOTSUPP;
889 	else if (!rxfh.rss_context)
890 		ret = ops->set_rxfh(dev, &rxfh, info->extack);
891 	else
892 		ret = ops->modify_rxfh_context(dev, ctx, &rxfh, info->extack);
893 	if (ret)
894 		goto exit_unlock;
895 
896 	if (ctx) {
897 		rss_set_ctx_update(ctx, tb, &data, &rxfh);
898 		if (indir_user_size)
899 			ctx->indir_user_size = indir_user_size;
900 	} else if (indir_reset) {
901 		dev->ethtool->rss_indir_user_size = 0;
902 	} else if (indir_mod) {
903 		dev->ethtool->rss_indir_user_size = indir_user_size;
904 	}
905 
906 exit_unlock:
907 	mutex_unlock(&dev->ethtool->rss_lock);
908 	kfree(rxfh.key);
909 exit_free_indir:
910 	kfree(rxfh.indir);
911 exit_clean_data:
912 	rss_cleanup_data(&data.base);
913 
914 	return ret ?: mod || fields_mod;
915 }
916 
917 const struct ethnl_request_ops ethnl_rss_request_ops = {
918 	.request_cmd		= ETHTOOL_MSG_RSS_GET,
919 	.reply_cmd		= ETHTOOL_MSG_RSS_GET_REPLY,
920 	.hdr_attr		= ETHTOOL_A_RSS_HEADER,
921 	.req_info_size		= sizeof(struct rss_req_info),
922 	.reply_data_size	= sizeof(struct rss_reply_data),
923 
924 	.parse_request		= rss_parse_request,
925 	.prepare_data		= rss_prepare_data,
926 	.reply_size		= rss_reply_size,
927 	.fill_reply		= rss_fill_reply,
928 	.cleanup_data		= rss_cleanup_data,
929 
930 	.set_validate		= ethnl_rss_set_validate,
931 	.set			= ethnl_rss_set,
932 	.set_ntf_cmd		= ETHTOOL_MSG_RSS_NTF,
933 };
934 
935 /* RSS_CREATE */
936 
937 const struct nla_policy ethnl_rss_create_policy[ETHTOOL_A_RSS_INPUT_XFRM + 1] = {
938 	[ETHTOOL_A_RSS_HEADER]	= NLA_POLICY_NESTED(ethnl_header_policy),
939 	[ETHTOOL_A_RSS_CONTEXT]	= NLA_POLICY_MIN(NLA_U32, 1),
940 	[ETHTOOL_A_RSS_HFUNC]	= NLA_POLICY_MIN(NLA_U32, 1),
941 	[ETHTOOL_A_RSS_INDIR]	= NLA_POLICY_MIN(NLA_BINARY, 1),
942 	[ETHTOOL_A_RSS_HKEY]	= NLA_POLICY_MIN(NLA_BINARY, 1),
943 	[ETHTOOL_A_RSS_INPUT_XFRM] =
944 		NLA_POLICY_MAX(NLA_U32, RXH_XFRM_SYM_OR_XOR),
945 };
946 
947 static int
948 ethnl_rss_create_validate(struct net_device *dev, struct genl_info *info)
949 {
950 	const struct ethtool_ops *ops = dev->ethtool_ops;
951 	struct nlattr **tb = info->attrs;
952 	struct nlattr *bad_attr = NULL;
953 	u32 rss_context, input_xfrm;
954 
955 	if (!ops->create_rxfh_context)
956 		return -EOPNOTSUPP;
957 
958 	rss_context = nla_get_u32_default(tb[ETHTOOL_A_RSS_CONTEXT], 0);
959 	if (ops->rxfh_max_num_contexts &&
960 	    ops->rxfh_max_num_contexts <= rss_context) {
961 		NL_SET_BAD_ATTR(info->extack, tb[ETHTOOL_A_RSS_CONTEXT]);
962 		return -ERANGE;
963 	}
964 
965 	if (!ops->rxfh_per_ctx_key) {
966 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HFUNC];
967 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HKEY];
968 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
969 	}
970 
971 	input_xfrm = nla_get_u32_default(tb[ETHTOOL_A_RSS_INPUT_XFRM], 0);
972 	if (input_xfrm & ~ops->supported_input_xfrm)
973 		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
974 
975 	if (bad_attr) {
976 		NL_SET_BAD_ATTR(info->extack, bad_attr);
977 		return -EOPNOTSUPP;
978 	}
979 
980 	return 0;
981 }
982 
983 static void
984 ethnl_rss_create_send_ntf(struct sk_buff *rsp, struct net_device *dev)
985 {
986 	struct nlmsghdr *nlh = (void *)rsp->data;
987 	struct genlmsghdr *genl_hdr;
988 
989 	/* Convert the reply into a notification */
990 	nlh->nlmsg_pid = 0;
991 	nlh->nlmsg_seq = ethnl_bcast_seq_next();
992 
993 	genl_hdr = nlmsg_data(nlh);
994 	genl_hdr->cmd =	ETHTOOL_MSG_RSS_CREATE_NTF;
995 
996 	ethnl_multicast(rsp, dev);
997 }
998 
999 int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
1000 {
1001 	bool indir_dflt = false, mod = false, ntf_fail = false;
1002 	struct ethtool_rxfh_param rxfh = {};
1003 	struct ethtool_rxfh_context *ctx;
1004 	struct nlattr **tb = info->attrs;
1005 	struct rss_reply_data data = {};
1006 	const struct ethtool_ops *ops;
1007 	struct rss_req_info req = {};
1008 	struct net_device *dev;
1009 	u32 indir_user_size;
1010 	struct sk_buff *rsp;
1011 	void *hdr;
1012 	u32 limit;
1013 	int ret;
1014 
1015 	rsp = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1016 	if (!rsp)
1017 		return -ENOMEM;
1018 
1019 	ret = ethnl_parse_header_dev_get(&req.base, tb[ETHTOOL_A_RSS_HEADER],
1020 					 genl_info_net(info), info->extack,
1021 					 true);
1022 	if (ret < 0)
1023 		goto exit_free_rsp;
1024 
1025 	dev = req.base.dev;
1026 	ops = dev->ethtool_ops;
1027 
1028 	req.rss_context = nla_get_u32_default(tb[ETHTOOL_A_RSS_CONTEXT], 0);
1029 
1030 	ret = ethnl_rss_create_validate(dev, info);
1031 	if (ret)
1032 		goto exit_free_dev;
1033 
1034 	rtnl_lock();
1035 	netdev_lock_ops(dev);
1036 
1037 	ret = ethnl_ops_begin(dev);
1038 	if (ret < 0)
1039 		goto exit_dev_unlock;
1040 
1041 	ret = rss_get_data_alloc(dev, &data);
1042 	if (ret)
1043 		goto exit_ops;
1044 
1045 	ret = rss_set_prep_indir(dev, info, &data, &rxfh, &indir_dflt, &mod);
1046 	if (ret < 0)
1047 		goto exit_clean_data;
1048 	indir_user_size = ret;
1049 
1050 	ethnl_update_u8(&rxfh.hfunc, tb[ETHTOOL_A_RSS_HFUNC], &mod);
1051 
1052 	ret = rss_set_prep_hkey(dev, info, &data, &rxfh, &mod);
1053 	if (ret)
1054 		goto exit_free_indir;
1055 
1056 	rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
1057 	ethnl_update_u8(&rxfh.input_xfrm, tb[ETHTOOL_A_RSS_INPUT_XFRM], &mod);
1058 
1059 	ctx = ethtool_rxfh_ctx_alloc(ops, data.indir_size, data.hkey_size);
1060 	if (!ctx) {
1061 		ret = -ENOMEM;
1062 		goto exit_free_hkey;
1063 	}
1064 
1065 	mutex_lock(&dev->ethtool->rss_lock);
1066 	if (!req.rss_context) {
1067 		limit = ops->rxfh_max_num_contexts ?: U32_MAX;
1068 		ret = xa_alloc(&dev->ethtool->rss_ctx, &req.rss_context, ctx,
1069 			       XA_LIMIT(1, limit - 1), GFP_KERNEL_ACCOUNT);
1070 	} else {
1071 		ret = xa_insert(&dev->ethtool->rss_ctx,
1072 				req.rss_context, ctx, GFP_KERNEL_ACCOUNT);
1073 	}
1074 	if (ret < 0) {
1075 		NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_RSS_CONTEXT],
1076 				    "error allocating context ID");
1077 		goto err_unlock_free_ctx;
1078 	}
1079 	rxfh.rss_context = req.rss_context;
1080 
1081 	ret = ops->create_rxfh_context(dev, ctx, &rxfh, info->extack);
1082 	if (ret)
1083 		goto err_ctx_id_free;
1084 
1085 	/* Make sure driver populates defaults */
1086 	WARN_ON_ONCE(!rxfh.key && ops->rxfh_per_ctx_key &&
1087 		     !memchr_inv(ethtool_rxfh_context_key(ctx), 0,
1088 				 ctx->key_size));
1089 
1090 	/* Store the config from rxfh to Xarray.. */
1091 	rss_set_ctx_update(ctx, tb, &data, &rxfh);
1092 	ctx->indir_user_size = indir_user_size;
1093 	/* .. copy from Xarray to data. */
1094 	__rss_prepare_ctx(dev, &data, ctx);
1095 
1096 	hdr = ethnl_unicast_put(rsp, info->snd_portid, info->snd_seq,
1097 				ETHTOOL_MSG_RSS_CREATE_ACT_REPLY);
1098 	ntf_fail = ethnl_fill_reply_header(rsp, dev, ETHTOOL_A_RSS_HEADER);
1099 	ntf_fail |= rss_fill_reply(rsp, &req.base, &data.base);
1100 	if (WARN_ON(!hdr || ntf_fail)) {
1101 		ret = -EMSGSIZE;
1102 		goto exit_unlock;
1103 	}
1104 
1105 	genlmsg_end(rsp, hdr);
1106 
1107 	/* Use the same skb for the response and the notification,
1108 	 * genlmsg_reply() will copy the skb if it has elevated user count.
1109 	 */
1110 	skb_get(rsp);
1111 	ret = genlmsg_reply(rsp, info);
1112 	ethnl_rss_create_send_ntf(rsp, dev);
1113 	rsp = NULL;
1114 
1115 exit_unlock:
1116 	mutex_unlock(&dev->ethtool->rss_lock);
1117 exit_free_hkey:
1118 	kfree(rxfh.key);
1119 exit_free_indir:
1120 	kfree(rxfh.indir);
1121 exit_clean_data:
1122 	rss_get_data_free(&data);
1123 exit_ops:
1124 	ethnl_ops_complete(dev);
1125 exit_dev_unlock:
1126 	netdev_unlock_ops(dev);
1127 	rtnl_unlock();
1128 exit_free_dev:
1129 	ethnl_parse_header_dev_put(&req.base);
1130 exit_free_rsp:
1131 	nlmsg_free(rsp);
1132 	return ret;
1133 
1134 err_ctx_id_free:
1135 	xa_erase(&dev->ethtool->rss_ctx, req.rss_context);
1136 err_unlock_free_ctx:
1137 	kfree(ctx);
1138 	goto exit_unlock;
1139 }
1140 
1141 /* RSS_DELETE */
1142 
1143 const struct nla_policy ethnl_rss_delete_policy[ETHTOOL_A_RSS_CONTEXT + 1] = {
1144 	[ETHTOOL_A_RSS_HEADER]	= NLA_POLICY_NESTED(ethnl_header_policy),
1145 	[ETHTOOL_A_RSS_CONTEXT]	= NLA_POLICY_MIN(NLA_U32, 1),
1146 };
1147 
1148 int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info)
1149 {
1150 	struct ethtool_rxfh_context *ctx;
1151 	struct nlattr **tb = info->attrs;
1152 	struct ethnl_req_info req = {};
1153 	const struct ethtool_ops *ops;
1154 	struct net_device *dev;
1155 	u32 rss_context;
1156 	int ret;
1157 
1158 	if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_RSS_CONTEXT))
1159 		return -EINVAL;
1160 	rss_context = nla_get_u32(tb[ETHTOOL_A_RSS_CONTEXT]);
1161 
1162 	ret = ethnl_parse_header_dev_get(&req, tb[ETHTOOL_A_RSS_HEADER],
1163 					 genl_info_net(info), info->extack,
1164 					 true);
1165 	if (ret < 0)
1166 		return ret;
1167 
1168 	dev = req.dev;
1169 	ops = dev->ethtool_ops;
1170 
1171 	if (!ops->create_rxfh_context)
1172 		goto exit_free_dev;
1173 
1174 	rtnl_lock();
1175 	netdev_lock_ops(dev);
1176 
1177 	ret = ethnl_ops_begin(dev);
1178 	if (ret < 0)
1179 		goto exit_dev_unlock;
1180 
1181 	mutex_lock(&dev->ethtool->rss_lock);
1182 	ret = ethtool_check_rss_ctx_busy(dev, rss_context);
1183 	if (ret)
1184 		goto exit_unlock;
1185 
1186 	ctx = xa_load(&dev->ethtool->rss_ctx, rss_context);
1187 	if (!ctx) {
1188 		ret = -ENOENT;
1189 		goto exit_unlock;
1190 	}
1191 
1192 	ret = ops->remove_rxfh_context(dev, ctx, rss_context, info->extack);
1193 	if (ret)
1194 		goto exit_unlock;
1195 
1196 	WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rss_context) != ctx);
1197 	kfree(ctx);
1198 
1199 	ethnl_rss_delete_notify(dev, rss_context);
1200 
1201 exit_unlock:
1202 	mutex_unlock(&dev->ethtool->rss_lock);
1203 	ethnl_ops_complete(dev);
1204 exit_dev_unlock:
1205 	netdev_unlock_ops(dev);
1206 	rtnl_unlock();
1207 exit_free_dev:
1208 	ethnl_parse_header_dev_put(&req);
1209 	return ret;
1210 }
1211