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