]> Git Repo - linux.git/blob - drivers/net/netdevsim/devlink.c
devlink: convert occ_get op to separate registration
[linux.git] / drivers / net / netdevsim / devlink.c
1 /*
2  * Copyright (c) 2018 Cumulus Networks. All rights reserved.
3  * Copyright (c) 2018 David Ahern <[email protected]>
4  *
5  * This software is licensed under the GNU General License Version 2,
6  * June 1991 as shown in the file COPYING in the top-level directory of this
7  * source tree.
8  *
9  * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
10  * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
11  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
13  * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
14  * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
15  */
16
17 #include <linux/device.h>
18 #include <net/devlink.h>
19 #include <net/netns/generic.h>
20
21 #include "netdevsim.h"
22
23 static unsigned int nsim_devlink_id;
24
25 /* place holder until devlink and namespaces is sorted out */
26 static struct net *nsim_devlink_net(struct devlink *devlink)
27 {
28         return &init_net;
29 }
30
31 /* IPv4
32  */
33 static u64 nsim_ipv4_fib_resource_occ_get(void *priv)
34 {
35         struct net *net = priv;
36
37         return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
38 }
39
40 static u64 nsim_ipv4_fib_rules_res_occ_get(void *priv)
41 {
42         struct net *net = priv;
43
44         return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
45 }
46
47 /* IPv6
48  */
49 static u64 nsim_ipv6_fib_resource_occ_get(void *priv)
50 {
51         struct net *net = priv;
52
53         return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
54 }
55
56 static u64 nsim_ipv6_fib_rules_res_occ_get(void *priv)
57 {
58         struct net *net = priv;
59
60         return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
61 }
62
63 static int devlink_resources_register(struct devlink *devlink)
64 {
65         struct devlink_resource_size_params params = {
66                 .size_max = (u64)-1,
67                 .size_granularity = 1,
68                 .unit = DEVLINK_RESOURCE_UNIT_ENTRY
69         };
70         struct net *net = nsim_devlink_net(devlink);
71         int err;
72         u64 n;
73
74         /* Resources for IPv4 */
75         err = devlink_resource_register(devlink, "IPv4", (u64)-1,
76                                         NSIM_RESOURCE_IPV4,
77                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
78                                         &params);
79         if (err) {
80                 pr_err("Failed to register IPv4 top resource\n");
81                 goto out;
82         }
83
84         n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
85         err = devlink_resource_register(devlink, "fib", n,
86                                         NSIM_RESOURCE_IPV4_FIB,
87                                         NSIM_RESOURCE_IPV4, &params);
88         if (err) {
89                 pr_err("Failed to register IPv4 FIB resource\n");
90                 return err;
91         }
92
93         n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
94         err = devlink_resource_register(devlink, "fib-rules", n,
95                                         NSIM_RESOURCE_IPV4_FIB_RULES,
96                                         NSIM_RESOURCE_IPV4, &params);
97         if (err) {
98                 pr_err("Failed to register IPv4 FIB rules resource\n");
99                 return err;
100         }
101
102         /* Resources for IPv6 */
103         err = devlink_resource_register(devlink, "IPv6", (u64)-1,
104                                         NSIM_RESOURCE_IPV6,
105                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
106                                         &params);
107         if (err) {
108                 pr_err("Failed to register IPv6 top resource\n");
109                 goto out;
110         }
111
112         n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
113         err = devlink_resource_register(devlink, "fib", n,
114                                         NSIM_RESOURCE_IPV6_FIB,
115                                         NSIM_RESOURCE_IPV6, &params);
116         if (err) {
117                 pr_err("Failed to register IPv6 FIB resource\n");
118                 return err;
119         }
120
121         n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
122         err = devlink_resource_register(devlink, "fib-rules", n,
123                                         NSIM_RESOURCE_IPV6_FIB_RULES,
124                                         NSIM_RESOURCE_IPV6, &params);
125         if (err) {
126                 pr_err("Failed to register IPv6 FIB rules resource\n");
127                 return err;
128         }
129
130         devlink_resource_occ_get_register(devlink,
131                                           NSIM_RESOURCE_IPV4_FIB,
132                                           nsim_ipv4_fib_resource_occ_get,
133                                           net);
134         devlink_resource_occ_get_register(devlink,
135                                           NSIM_RESOURCE_IPV4_FIB_RULES,
136                                           nsim_ipv4_fib_rules_res_occ_get,
137                                           net);
138         devlink_resource_occ_get_register(devlink,
139                                           NSIM_RESOURCE_IPV6_FIB,
140                                           nsim_ipv6_fib_resource_occ_get,
141                                           net);
142         devlink_resource_occ_get_register(devlink,
143                                           NSIM_RESOURCE_IPV6_FIB_RULES,
144                                           nsim_ipv6_fib_rules_res_occ_get,
145                                           net);
146 out:
147         return err;
148 }
149
150 static int nsim_devlink_reload(struct devlink *devlink)
151 {
152         enum nsim_resource_id res_ids[] = {
153                 NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
154                 NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
155         };
156         struct net *net = nsim_devlink_net(devlink);
157         int i;
158
159         for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
160                 int err;
161                 u64 val;
162
163                 err = devlink_resource_size_get(devlink, res_ids[i], &val);
164                 if (!err) {
165                         err = nsim_fib_set_max(net, res_ids[i], val);
166                         if (err)
167                                 return err;
168                 }
169         }
170
171         return 0;
172 }
173
174 static void nsim_devlink_net_reset(struct net *net)
175 {
176         enum nsim_resource_id res_ids[] = {
177                 NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
178                 NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
179         };
180         int i;
181
182         for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
183                 if (nsim_fib_set_max(net, res_ids[i], (u64)-1)) {
184                         pr_err("Failed to reset limit for resource %u\n",
185                                res_ids[i]);
186                 }
187         }
188 }
189
190 static const struct devlink_ops nsim_devlink_ops = {
191         .reload = nsim_devlink_reload,
192 };
193
194 /* once devlink / namespace issues are sorted out
195  * this needs to be net in which a devlink instance
196  * is to be created. e.g., dev_net(ns->netdev)
197  */
198 static struct net *nsim_to_net(struct netdevsim *ns)
199 {
200         return &init_net;
201 }
202
203 void nsim_devlink_teardown(struct netdevsim *ns)
204 {
205         if (ns->devlink) {
206                 struct net *net = nsim_to_net(ns);
207                 bool *reg_devlink = net_generic(net, nsim_devlink_id);
208
209                 devlink_unregister(ns->devlink);
210                 devlink_free(ns->devlink);
211                 ns->devlink = NULL;
212
213                 nsim_devlink_net_reset(net);
214                 *reg_devlink = true;
215         }
216 }
217
218 int nsim_devlink_setup(struct netdevsim *ns)
219 {
220         struct net *net = nsim_to_net(ns);
221         bool *reg_devlink = net_generic(net, nsim_devlink_id);
222         struct devlink *devlink;
223         int err;
224
225         /* only one device per namespace controls devlink */
226         if (!*reg_devlink) {
227                 ns->devlink = NULL;
228                 return 0;
229         }
230
231         devlink = devlink_alloc(&nsim_devlink_ops, 0);
232         if (!devlink)
233                 return -ENOMEM;
234
235         err = devlink_register(devlink, &ns->dev);
236         if (err)
237                 goto err_devlink_free;
238
239         err = devlink_resources_register(devlink);
240         if (err)
241                 goto err_dl_unregister;
242
243         ns->devlink = devlink;
244
245         *reg_devlink = false;
246
247         return 0;
248
249 err_dl_unregister:
250         devlink_unregister(devlink);
251 err_devlink_free:
252         devlink_free(devlink);
253
254         return err;
255 }
256
257 /* Initialize per network namespace state */
258 static int __net_init nsim_devlink_netns_init(struct net *net)
259 {
260         bool *reg_devlink = net_generic(net, nsim_devlink_id);
261
262         *reg_devlink = true;
263
264         return 0;
265 }
266
267 static struct pernet_operations nsim_devlink_net_ops = {
268         .init = nsim_devlink_netns_init,
269         .id   = &nsim_devlink_id,
270         .size = sizeof(bool),
271 };
272
273 void nsim_devlink_exit(void)
274 {
275         unregister_pernet_subsys(&nsim_devlink_net_ops);
276         nsim_fib_exit();
277 }
278
279 int nsim_devlink_init(void)
280 {
281         int err;
282
283         err = nsim_fib_init();
284         if (err)
285                 goto err_out;
286
287         err = register_pernet_subsys(&nsim_devlink_net_ops);
288         if (err)
289                 nsim_fib_exit();
290
291 err_out:
292         return err;
293 }
This page took 0.054261 seconds and 4 git commands to generate.