xref: /linux-6.15/drivers/net/netdevsim/dev.c (revision 8fb4bc6f)
1*8fb4bc6fSJiri Pirko /*
2*8fb4bc6fSJiri Pirko  * Copyright (c) 2018 Cumulus Networks. All rights reserved.
3*8fb4bc6fSJiri Pirko  * Copyright (c) 2018 David Ahern <[email protected]>
4*8fb4bc6fSJiri Pirko  * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
5*8fb4bc6fSJiri Pirko  *
6*8fb4bc6fSJiri Pirko  * This software is licensed under the GNU General License Version 2,
7*8fb4bc6fSJiri Pirko  * June 1991 as shown in the file COPYING in the top-level directory of this
8*8fb4bc6fSJiri Pirko  * source tree.
9*8fb4bc6fSJiri Pirko  *
10*8fb4bc6fSJiri Pirko  * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
11*8fb4bc6fSJiri Pirko  * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
12*8fb4bc6fSJiri Pirko  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13*8fb4bc6fSJiri Pirko  * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
14*8fb4bc6fSJiri Pirko  * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
15*8fb4bc6fSJiri Pirko  * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16*8fb4bc6fSJiri Pirko  */
17*8fb4bc6fSJiri Pirko 
18*8fb4bc6fSJiri Pirko #include <linux/device.h>
19*8fb4bc6fSJiri Pirko #include <linux/rtnetlink.h>
20*8fb4bc6fSJiri Pirko #include <net/devlink.h>
21*8fb4bc6fSJiri Pirko 
22*8fb4bc6fSJiri Pirko #include "netdevsim.h"
23*8fb4bc6fSJiri Pirko 
24*8fb4bc6fSJiri Pirko struct nsim_dev {
25*8fb4bc6fSJiri Pirko 	struct nsim_fib_data *fib_data;
26*8fb4bc6fSJiri Pirko };
27*8fb4bc6fSJiri Pirko 
28*8fb4bc6fSJiri Pirko static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
29*8fb4bc6fSJiri Pirko {
30*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = priv;
31*8fb4bc6fSJiri Pirko 
32*8fb4bc6fSJiri Pirko 	return nsim_fib_get_val(nsim_dev->fib_data,
33*8fb4bc6fSJiri Pirko 				NSIM_RESOURCE_IPV4_FIB, false);
34*8fb4bc6fSJiri Pirko }
35*8fb4bc6fSJiri Pirko 
36*8fb4bc6fSJiri Pirko static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
37*8fb4bc6fSJiri Pirko {
38*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = priv;
39*8fb4bc6fSJiri Pirko 
40*8fb4bc6fSJiri Pirko 	return nsim_fib_get_val(nsim_dev->fib_data,
41*8fb4bc6fSJiri Pirko 				NSIM_RESOURCE_IPV4_FIB_RULES, false);
42*8fb4bc6fSJiri Pirko }
43*8fb4bc6fSJiri Pirko 
44*8fb4bc6fSJiri Pirko static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
45*8fb4bc6fSJiri Pirko {
46*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = priv;
47*8fb4bc6fSJiri Pirko 
48*8fb4bc6fSJiri Pirko 	return nsim_fib_get_val(nsim_dev->fib_data,
49*8fb4bc6fSJiri Pirko 				NSIM_RESOURCE_IPV6_FIB, false);
50*8fb4bc6fSJiri Pirko }
51*8fb4bc6fSJiri Pirko 
52*8fb4bc6fSJiri Pirko static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
53*8fb4bc6fSJiri Pirko {
54*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = priv;
55*8fb4bc6fSJiri Pirko 
56*8fb4bc6fSJiri Pirko 	return nsim_fib_get_val(nsim_dev->fib_data,
57*8fb4bc6fSJiri Pirko 				NSIM_RESOURCE_IPV6_FIB_RULES, false);
58*8fb4bc6fSJiri Pirko }
59*8fb4bc6fSJiri Pirko 
60*8fb4bc6fSJiri Pirko static int nsim_dev_resources_register(struct devlink *devlink)
61*8fb4bc6fSJiri Pirko {
62*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
63*8fb4bc6fSJiri Pirko 	struct devlink_resource_size_params params = {
64*8fb4bc6fSJiri Pirko 		.size_max = (u64)-1,
65*8fb4bc6fSJiri Pirko 		.size_granularity = 1,
66*8fb4bc6fSJiri Pirko 		.unit = DEVLINK_RESOURCE_UNIT_ENTRY
67*8fb4bc6fSJiri Pirko 	};
68*8fb4bc6fSJiri Pirko 	int err;
69*8fb4bc6fSJiri Pirko 	u64 n;
70*8fb4bc6fSJiri Pirko 
71*8fb4bc6fSJiri Pirko 	/* Resources for IPv4 */
72*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "IPv4", (u64)-1,
73*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV4,
74*8fb4bc6fSJiri Pirko 					DEVLINK_RESOURCE_ID_PARENT_TOP,
75*8fb4bc6fSJiri Pirko 					&params);
76*8fb4bc6fSJiri Pirko 	if (err) {
77*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv4 top resource\n");
78*8fb4bc6fSJiri Pirko 		goto out;
79*8fb4bc6fSJiri Pirko 	}
80*8fb4bc6fSJiri Pirko 
81*8fb4bc6fSJiri Pirko 	n = nsim_fib_get_val(nsim_dev->fib_data,
82*8fb4bc6fSJiri Pirko 			     NSIM_RESOURCE_IPV4_FIB, true);
83*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "fib", n,
84*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV4_FIB,
85*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV4, &params);
86*8fb4bc6fSJiri Pirko 	if (err) {
87*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv4 FIB resource\n");
88*8fb4bc6fSJiri Pirko 		return err;
89*8fb4bc6fSJiri Pirko 	}
90*8fb4bc6fSJiri Pirko 
91*8fb4bc6fSJiri Pirko 	n = nsim_fib_get_val(nsim_dev->fib_data,
92*8fb4bc6fSJiri Pirko 			     NSIM_RESOURCE_IPV4_FIB_RULES, true);
93*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "fib-rules", n,
94*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV4_FIB_RULES,
95*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV4, &params);
96*8fb4bc6fSJiri Pirko 	if (err) {
97*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv4 FIB rules resource\n");
98*8fb4bc6fSJiri Pirko 		return err;
99*8fb4bc6fSJiri Pirko 	}
100*8fb4bc6fSJiri Pirko 
101*8fb4bc6fSJiri Pirko 	/* Resources for IPv6 */
102*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "IPv6", (u64)-1,
103*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV6,
104*8fb4bc6fSJiri Pirko 					DEVLINK_RESOURCE_ID_PARENT_TOP,
105*8fb4bc6fSJiri Pirko 					&params);
106*8fb4bc6fSJiri Pirko 	if (err) {
107*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv6 top resource\n");
108*8fb4bc6fSJiri Pirko 		goto out;
109*8fb4bc6fSJiri Pirko 	}
110*8fb4bc6fSJiri Pirko 
111*8fb4bc6fSJiri Pirko 	n = nsim_fib_get_val(nsim_dev->fib_data,
112*8fb4bc6fSJiri Pirko 			     NSIM_RESOURCE_IPV6_FIB, true);
113*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "fib", n,
114*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV6_FIB,
115*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV6, &params);
116*8fb4bc6fSJiri Pirko 	if (err) {
117*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv6 FIB resource\n");
118*8fb4bc6fSJiri Pirko 		return err;
119*8fb4bc6fSJiri Pirko 	}
120*8fb4bc6fSJiri Pirko 
121*8fb4bc6fSJiri Pirko 	n = nsim_fib_get_val(nsim_dev->fib_data,
122*8fb4bc6fSJiri Pirko 			     NSIM_RESOURCE_IPV6_FIB_RULES, true);
123*8fb4bc6fSJiri Pirko 	err = devlink_resource_register(devlink, "fib-rules", n,
124*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV6_FIB_RULES,
125*8fb4bc6fSJiri Pirko 					NSIM_RESOURCE_IPV6, &params);
126*8fb4bc6fSJiri Pirko 	if (err) {
127*8fb4bc6fSJiri Pirko 		pr_err("Failed to register IPv6 FIB rules resource\n");
128*8fb4bc6fSJiri Pirko 		return err;
129*8fb4bc6fSJiri Pirko 	}
130*8fb4bc6fSJiri Pirko 
131*8fb4bc6fSJiri Pirko 	devlink_resource_occ_get_register(devlink,
132*8fb4bc6fSJiri Pirko 					  NSIM_RESOURCE_IPV4_FIB,
133*8fb4bc6fSJiri Pirko 					  nsim_dev_ipv4_fib_resource_occ_get,
134*8fb4bc6fSJiri Pirko 					  nsim_dev);
135*8fb4bc6fSJiri Pirko 	devlink_resource_occ_get_register(devlink,
136*8fb4bc6fSJiri Pirko 					  NSIM_RESOURCE_IPV4_FIB_RULES,
137*8fb4bc6fSJiri Pirko 					  nsim_dev_ipv4_fib_rules_res_occ_get,
138*8fb4bc6fSJiri Pirko 					  nsim_dev);
139*8fb4bc6fSJiri Pirko 	devlink_resource_occ_get_register(devlink,
140*8fb4bc6fSJiri Pirko 					  NSIM_RESOURCE_IPV6_FIB,
141*8fb4bc6fSJiri Pirko 					  nsim_dev_ipv6_fib_resource_occ_get,
142*8fb4bc6fSJiri Pirko 					  nsim_dev);
143*8fb4bc6fSJiri Pirko 	devlink_resource_occ_get_register(devlink,
144*8fb4bc6fSJiri Pirko 					  NSIM_RESOURCE_IPV6_FIB_RULES,
145*8fb4bc6fSJiri Pirko 					  nsim_dev_ipv6_fib_rules_res_occ_get,
146*8fb4bc6fSJiri Pirko 					  nsim_dev);
147*8fb4bc6fSJiri Pirko out:
148*8fb4bc6fSJiri Pirko 	return err;
149*8fb4bc6fSJiri Pirko }
150*8fb4bc6fSJiri Pirko 
151*8fb4bc6fSJiri Pirko static int nsim_dev_reload(struct devlink *devlink,
152*8fb4bc6fSJiri Pirko 			   struct netlink_ext_ack *extack)
153*8fb4bc6fSJiri Pirko {
154*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
155*8fb4bc6fSJiri Pirko 	enum nsim_resource_id res_ids[] = {
156*8fb4bc6fSJiri Pirko 		NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
157*8fb4bc6fSJiri Pirko 		NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
158*8fb4bc6fSJiri Pirko 	};
159*8fb4bc6fSJiri Pirko 	int i;
160*8fb4bc6fSJiri Pirko 
161*8fb4bc6fSJiri Pirko 	for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
162*8fb4bc6fSJiri Pirko 		int err;
163*8fb4bc6fSJiri Pirko 		u64 val;
164*8fb4bc6fSJiri Pirko 
165*8fb4bc6fSJiri Pirko 		err = devlink_resource_size_get(devlink, res_ids[i], &val);
166*8fb4bc6fSJiri Pirko 		if (!err) {
167*8fb4bc6fSJiri Pirko 			err = nsim_fib_set_max(nsim_dev->fib_data,
168*8fb4bc6fSJiri Pirko 					       res_ids[i], val, extack);
169*8fb4bc6fSJiri Pirko 			if (err)
170*8fb4bc6fSJiri Pirko 				return err;
171*8fb4bc6fSJiri Pirko 		}
172*8fb4bc6fSJiri Pirko 	}
173*8fb4bc6fSJiri Pirko 
174*8fb4bc6fSJiri Pirko 	return 0;
175*8fb4bc6fSJiri Pirko }
176*8fb4bc6fSJiri Pirko 
177*8fb4bc6fSJiri Pirko static const struct devlink_ops nsim_dev_devlink_ops = {
178*8fb4bc6fSJiri Pirko 	.reload = nsim_dev_reload,
179*8fb4bc6fSJiri Pirko };
180*8fb4bc6fSJiri Pirko 
181*8fb4bc6fSJiri Pirko static int __nsim_dev_init(struct netdevsim *ns)
182*8fb4bc6fSJiri Pirko {
183*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev;
184*8fb4bc6fSJiri Pirko 	struct devlink *devlink;
185*8fb4bc6fSJiri Pirko 	int err;
186*8fb4bc6fSJiri Pirko 
187*8fb4bc6fSJiri Pirko 	devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
188*8fb4bc6fSJiri Pirko 	if (!devlink)
189*8fb4bc6fSJiri Pirko 		return -ENOMEM;
190*8fb4bc6fSJiri Pirko 	nsim_dev = devlink_priv(devlink);
191*8fb4bc6fSJiri Pirko 
192*8fb4bc6fSJiri Pirko 	nsim_dev->fib_data = nsim_fib_create();
193*8fb4bc6fSJiri Pirko 	if (IS_ERR(nsim_dev->fib_data)) {
194*8fb4bc6fSJiri Pirko 		err = PTR_ERR(nsim_dev->fib_data);
195*8fb4bc6fSJiri Pirko 		goto err_devlink_free;
196*8fb4bc6fSJiri Pirko 	}
197*8fb4bc6fSJiri Pirko 
198*8fb4bc6fSJiri Pirko 	err = nsim_dev_resources_register(devlink);
199*8fb4bc6fSJiri Pirko 	if (err)
200*8fb4bc6fSJiri Pirko 		goto err_fib_destroy;
201*8fb4bc6fSJiri Pirko 
202*8fb4bc6fSJiri Pirko 	err = devlink_register(devlink, &ns->dev);
203*8fb4bc6fSJiri Pirko 	if (err)
204*8fb4bc6fSJiri Pirko 		goto err_resources_unregister;
205*8fb4bc6fSJiri Pirko 
206*8fb4bc6fSJiri Pirko 	ns->devlink = devlink;
207*8fb4bc6fSJiri Pirko 
208*8fb4bc6fSJiri Pirko 	return 0;
209*8fb4bc6fSJiri Pirko 
210*8fb4bc6fSJiri Pirko err_resources_unregister:
211*8fb4bc6fSJiri Pirko 	devlink_resources_unregister(devlink, NULL);
212*8fb4bc6fSJiri Pirko err_fib_destroy:
213*8fb4bc6fSJiri Pirko 	nsim_fib_destroy(nsim_dev->fib_data);
214*8fb4bc6fSJiri Pirko err_devlink_free:
215*8fb4bc6fSJiri Pirko 	devlink_free(devlink);
216*8fb4bc6fSJiri Pirko 
217*8fb4bc6fSJiri Pirko 	return err;
218*8fb4bc6fSJiri Pirko }
219*8fb4bc6fSJiri Pirko 
220*8fb4bc6fSJiri Pirko int nsim_dev_init(struct netdevsim *ns)
221*8fb4bc6fSJiri Pirko {
222*8fb4bc6fSJiri Pirko 	int err;
223*8fb4bc6fSJiri Pirko 
224*8fb4bc6fSJiri Pirko 	dev_hold(ns->netdev);
225*8fb4bc6fSJiri Pirko 	rtnl_unlock();
226*8fb4bc6fSJiri Pirko 	err = __nsim_dev_init(ns);
227*8fb4bc6fSJiri Pirko 	rtnl_lock();
228*8fb4bc6fSJiri Pirko 	dev_put(ns->netdev);
229*8fb4bc6fSJiri Pirko 	return err;
230*8fb4bc6fSJiri Pirko }
231*8fb4bc6fSJiri Pirko 
232*8fb4bc6fSJiri Pirko void nsim_dev_exit(struct netdevsim *ns)
233*8fb4bc6fSJiri Pirko {
234*8fb4bc6fSJiri Pirko 	struct devlink *devlink = ns->devlink;
235*8fb4bc6fSJiri Pirko 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
236*8fb4bc6fSJiri Pirko 
237*8fb4bc6fSJiri Pirko 	devlink_unregister(devlink);
238*8fb4bc6fSJiri Pirko 	devlink_resources_unregister(devlink, NULL);
239*8fb4bc6fSJiri Pirko 	nsim_fib_destroy(nsim_dev->fib_data);
240*8fb4bc6fSJiri Pirko 	devlink_free(devlink);
241*8fb4bc6fSJiri Pirko }
242