aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netdevsim/fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netdevsim/fib.c')
-rw-r--r--drivers/net/netdevsim/fib.c102
1 files changed, 61 insertions, 41 deletions
diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c
index 8c57ba747772..f61d094746c0 100644
--- a/drivers/net/netdevsim/fib.c
+++ b/drivers/net/netdevsim/fib.c
@@ -18,6 +18,7 @@
18#include <net/ip_fib.h> 18#include <net/ip_fib.h>
19#include <net/ip6_fib.h> 19#include <net/ip6_fib.h>
20#include <net/fib_rules.h> 20#include <net/fib_rules.h>
21#include <net/netns/generic.h>
21 22
22#include "netdevsim.h" 23#include "netdevsim.h"
23 24
@@ -32,14 +33,15 @@ struct nsim_per_fib_data {
32}; 33};
33 34
34struct nsim_fib_data { 35struct nsim_fib_data {
35 struct notifier_block fib_nb;
36 struct nsim_per_fib_data ipv4; 36 struct nsim_per_fib_data ipv4;
37 struct nsim_per_fib_data ipv6; 37 struct nsim_per_fib_data ipv6;
38}; 38};
39 39
40u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, 40static unsigned int nsim_fib_net_id;
41 enum nsim_resource_id res_id, bool max) 41
42u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max)
42{ 43{
44 struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
43 struct nsim_fib_entry *entry; 45 struct nsim_fib_entry *entry;
44 46
45 switch (res_id) { 47 switch (res_id) {
@@ -62,10 +64,10 @@ u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
62 return max ? entry->max : entry->num; 64 return max ? entry->max : entry->num;
63} 65}
64 66
65int nsim_fib_set_max(struct nsim_fib_data *fib_data, 67int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
66 enum nsim_resource_id res_id, u64 val,
67 struct netlink_ext_ack *extack) 68 struct netlink_ext_ack *extack)
68{ 69{
70 struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
69 struct nsim_fib_entry *entry; 71 struct nsim_fib_entry *entry;
70 int err = 0; 72 int err = 0;
71 73
@@ -118,9 +120,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
118 return err; 120 return err;
119} 121}
120 122
121static int nsim_fib_rule_event(struct nsim_fib_data *data, 123static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add)
122 struct fib_notifier_info *info, bool add)
123{ 124{
125 struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
124 struct netlink_ext_ack *extack = info->extack; 126 struct netlink_ext_ack *extack = info->extack;
125 int err = 0; 127 int err = 0;
126 128
@@ -155,9 +157,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
155 return err; 157 return err;
156} 158}
157 159
158static int nsim_fib_event(struct nsim_fib_data *data, 160static int nsim_fib_event(struct fib_notifier_info *info, bool add)
159 struct fib_notifier_info *info, bool add)
160{ 161{
162 struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
161 struct netlink_ext_ack *extack = info->extack; 163 struct netlink_ext_ack *extack = info->extack;
162 int err = 0; 164 int err = 0;
163 165
@@ -176,22 +178,18 @@ static int nsim_fib_event(struct nsim_fib_data *data,
176static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event, 178static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
177 void *ptr) 179 void *ptr)
178{ 180{
179 struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
180 fib_nb);
181 struct fib_notifier_info *info = ptr; 181 struct fib_notifier_info *info = ptr;
182 int err = 0; 182 int err = 0;
183 183
184 switch (event) { 184 switch (event) {
185 case FIB_EVENT_RULE_ADD: /* fall through */ 185 case FIB_EVENT_RULE_ADD: /* fall through */
186 case FIB_EVENT_RULE_DEL: 186 case FIB_EVENT_RULE_DEL:
187 err = nsim_fib_rule_event(data, info, 187 err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD);
188 event == FIB_EVENT_RULE_ADD);
189 break; 188 break;
190 189
191 case FIB_EVENT_ENTRY_ADD: /* fall through */ 190 case FIB_EVENT_ENTRY_ADD: /* fall through */
192 case FIB_EVENT_ENTRY_DEL: 191 case FIB_EVENT_ENTRY_DEL:
193 err = nsim_fib_event(data, info, 192 err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
194 event == FIB_EVENT_ENTRY_ADD);
195 break; 193 break;
196 } 194 }
197 195
@@ -201,23 +199,30 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
201/* inconsistent dump, trying again */ 199/* inconsistent dump, trying again */
202static void nsim_fib_dump_inconsistent(struct notifier_block *nb) 200static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
203{ 201{
204 struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data, 202 struct nsim_fib_data *data;
205 fib_nb); 203 struct net *net;
204
205 rcu_read_lock();
206 for_each_net_rcu(net) {
207 data = net_generic(net, nsim_fib_net_id);
208
209 data->ipv4.fib.num = 0ULL;
210 data->ipv4.rules.num = 0ULL;
206 211
207 data->ipv4.fib.num = 0ULL; 212 data->ipv6.fib.num = 0ULL;
208 data->ipv4.rules.num = 0ULL; 213 data->ipv6.rules.num = 0ULL;
209 data->ipv6.fib.num = 0ULL; 214 }
210 data->ipv6.rules.num = 0ULL; 215 rcu_read_unlock();
211} 216}
212 217
213struct nsim_fib_data *nsim_fib_create(void) 218static struct notifier_block nsim_fib_nb = {
214{ 219 .notifier_call = nsim_fib_event_nb,
215 struct nsim_fib_data *data; 220};
216 int err;
217 221
218 data = kzalloc(sizeof(*data), GFP_KERNEL); 222/* Initialize per network namespace state */
219 if (!data) 223static int __net_init nsim_fib_netns_init(struct net *net)
220 return ERR_PTR(-ENOMEM); 224{
225 struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);
221 226
222 data->ipv4.fib.max = (u64)-1; 227 data->ipv4.fib.max = (u64)-1;
223 data->ipv4.rules.max = (u64)-1; 228 data->ipv4.rules.max = (u64)-1;
@@ -225,22 +230,37 @@ struct nsim_fib_data *nsim_fib_create(void)
225 data->ipv6.fib.max = (u64)-1; 230 data->ipv6.fib.max = (u64)-1;
226 data->ipv6.rules.max = (u64)-1; 231 data->ipv6.rules.max = (u64)-1;
227 232
228 data->fib_nb.notifier_call = nsim_fib_event_nb; 233 return 0;
229 err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent); 234}
230 if (err) {
231 pr_err("Failed to register fib notifier\n");
232 goto err_out;
233 }
234 235
235 return data; 236static struct pernet_operations nsim_fib_net_ops = {
237 .init = nsim_fib_netns_init,
238 .id = &nsim_fib_net_id,
239 .size = sizeof(struct nsim_fib_data),
240};
236 241
237err_out: 242void nsim_fib_exit(void)
238 kfree(data); 243{
239 return ERR_PTR(err); 244 unregister_pernet_subsys(&nsim_fib_net_ops);
245 unregister_fib_notifier(&nsim_fib_nb);
240} 246}
241 247
242void nsim_fib_destroy(struct nsim_fib_data *data) 248int nsim_fib_init(void)
243{ 249{
244 unregister_fib_notifier(&data->fib_nb); 250 int err;
245 kfree(data); 251
252 err = register_pernet_subsys(&nsim_fib_net_ops);
253 if (err < 0) {
254 pr_err("Failed to register pernet subsystem\n");
255 goto err_out;
256 }
257
258 err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
259 if (err < 0) {
260 pr_err("Failed to register fib notifier\n");
261 goto err_out;
262 }
263
264err_out:
265 return err;
246} 266}