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,
151 struct netlink_ext_ack *extack)
153 enum nsim_resource_id res_ids[] = {
154 NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
155 NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
157 struct net *net = nsim_devlink_net(devlink);
160 for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
164 err = devlink_resource_size_get(devlink, res_ids[i], &val);
166 err = nsim_fib_set_max(net, res_ids[i], val, extack);
175 static void nsim_devlink_net_reset(struct net *net)
177 enum nsim_resource_id res_ids[] = {
178 NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
179 NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
183 for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
184 if (nsim_fib_set_max(net, res_ids[i], (u64)-1, NULL)) {
185 pr_err("Failed to reset limit for resource %u\n",
191 static const struct devlink_ops nsim_devlink_ops = {
192 .reload = nsim_devlink_reload,
195 /* once devlink / namespace issues are sorted out
196 * this needs to be net in which a devlink instance
197 * is to be created. e.g., dev_net(ns->netdev)
199 static struct net *nsim_to_net(struct netdevsim *ns)
204 void nsim_devlink_teardown(struct netdevsim *ns)
207 struct net *net = nsim_to_net(ns);
208 bool *reg_devlink = net_generic(net, nsim_devlink_id);
210 devlink_resources_unregister(ns->devlink, NULL);
211 devlink_unregister(ns->devlink);
212 devlink_free(ns->devlink);
215 nsim_devlink_net_reset(net);
220 int nsim_devlink_setup(struct netdevsim *ns)
222 struct net *net = nsim_to_net(ns);
223 bool *reg_devlink = net_generic(net, nsim_devlink_id);
224 struct devlink *devlink;
227 /* only one device per namespace controls devlink */
233 devlink = devlink_alloc(&nsim_devlink_ops, 0);
237 err = devlink_register(devlink, &ns->dev);
239 goto err_devlink_free;
241 err = devlink_resources_register(devlink);
243 goto err_dl_unregister;
245 ns->devlink = devlink;
247 *reg_devlink = false;
252 devlink_unregister(devlink);
254 devlink_free(devlink);
259 /* Initialize per network namespace state */
260 static int __net_init nsim_devlink_netns_init(struct net *net)
262 bool *reg_devlink = net_generic(net, nsim_devlink_id);
269 static struct pernet_operations nsim_devlink_net_ops = {
270 .init = nsim_devlink_netns_init,
271 .id = &nsim_devlink_id,
272 .size = sizeof(bool),
275 void nsim_devlink_exit(void)
277 unregister_pernet_subsys(&nsim_devlink_net_ops);
281 int nsim_devlink_init(void)
285 err = nsim_fib_init();
289 err = register_pernet_subsys(&nsim_devlink_net_ops);