2 * Copyright (c) 2018 Cumulus Networks. All rights reserved.
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
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.
17 #include <linux/device.h>
18 #include <net/devlink.h>
19 #include <net/netns/generic.h>
21 #include "netdevsim.h"
23 static unsigned int nsim_devlink_id;
25 /* place holder until devlink and namespaces is sorted out */
26 static struct net *nsim_devlink_net(struct devlink *devlink)
33 static u64 nsim_ipv4_fib_resource_occ_get(void *priv)
35 struct net *net = priv;
37 return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
40 static u64 nsim_ipv4_fib_rules_res_occ_get(void *priv)
42 struct net *net = priv;
44 return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
49 static u64 nsim_ipv6_fib_resource_occ_get(void *priv)
51 struct net *net = priv;
53 return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
56 static u64 nsim_ipv6_fib_rules_res_occ_get(void *priv)
58 struct net *net = priv;
60 return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
63 static int devlink_resources_register(struct devlink *devlink)
65 struct devlink_resource_size_params params = {
67 .size_granularity = 1,
68 .unit = DEVLINK_RESOURCE_UNIT_ENTRY
70 struct net *net = nsim_devlink_net(devlink);
74 /* Resources for IPv4 */
75 err = devlink_resource_register(devlink, "IPv4", (u64)-1,
77 DEVLINK_RESOURCE_ID_PARENT_TOP,
80 pr_err("Failed to register IPv4 top resource\n");
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, ¶ms);
89 pr_err("Failed to register IPv4 FIB resource\n");
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, ¶ms);
98 pr_err("Failed to register IPv4 FIB rules resource\n");
102 /* Resources for IPv6 */
103 err = devlink_resource_register(devlink, "IPv6", (u64)-1,
105 DEVLINK_RESOURCE_ID_PARENT_TOP,
108 pr_err("Failed to register IPv6 top resource\n");
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, ¶ms);
117 pr_err("Failed to register IPv6 FIB resource\n");
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, ¶ms);
126 pr_err("Failed to register IPv6 FIB rules resource\n");
130 devlink_resource_occ_get_register(devlink,
131 NSIM_RESOURCE_IPV4_FIB,
132 nsim_ipv4_fib_resource_occ_get,
134 devlink_resource_occ_get_register(devlink,
135 NSIM_RESOURCE_IPV4_FIB_RULES,
136 nsim_ipv4_fib_rules_res_occ_get,
138 devlink_resource_occ_get_register(devlink,
139 NSIM_RESOURCE_IPV6_FIB,
140 nsim_ipv6_fib_resource_occ_get,
142 devlink_resource_occ_get_register(devlink,
143 NSIM_RESOURCE_IPV6_FIB_RULES,
144 nsim_ipv6_fib_rules_res_occ_get,
150 static int nsim_devlink_reload(struct devlink *devlink)
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
156 struct net *net = nsim_devlink_net(devlink);
159 for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
163 err = devlink_resource_size_get(devlink, res_ids[i], &val);
165 err = nsim_fib_set_max(net, res_ids[i], val);
174 static void nsim_devlink_net_reset(struct net *net)
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
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",
190 static const struct devlink_ops nsim_devlink_ops = {
191 .reload = nsim_devlink_reload,
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)
198 static struct net *nsim_to_net(struct netdevsim *ns)
203 void nsim_devlink_teardown(struct netdevsim *ns)
206 struct net *net = nsim_to_net(ns);
207 bool *reg_devlink = net_generic(net, nsim_devlink_id);
209 devlink_unregister(ns->devlink);
210 devlink_free(ns->devlink);
213 nsim_devlink_net_reset(net);
218 int nsim_devlink_setup(struct netdevsim *ns)
220 struct net *net = nsim_to_net(ns);
221 bool *reg_devlink = net_generic(net, nsim_devlink_id);
222 struct devlink *devlink;
225 /* only one device per namespace controls devlink */
231 devlink = devlink_alloc(&nsim_devlink_ops, 0);
235 err = devlink_register(devlink, &ns->dev);
237 goto err_devlink_free;
239 err = devlink_resources_register(devlink);
241 goto err_dl_unregister;
243 ns->devlink = devlink;
245 *reg_devlink = false;
250 devlink_unregister(devlink);
252 devlink_free(devlink);
257 /* Initialize per network namespace state */
258 static int __net_init nsim_devlink_netns_init(struct net *net)
260 bool *reg_devlink = net_generic(net, nsim_devlink_id);
267 static struct pernet_operations nsim_devlink_net_ops = {
268 .init = nsim_devlink_netns_init,
269 .id = &nsim_devlink_id,
270 .size = sizeof(bool),
273 void nsim_devlink_exit(void)
275 unregister_pernet_subsys(&nsim_devlink_net_ops);
279 int nsim_devlink_init(void)
283 err = nsim_fib_init();
287 err = register_pernet_subsys(&nsim_devlink_net_ops);