diff options
Diffstat (limited to 'drivers/net/netdevsim/fib.c')
-rw-r--r-- | drivers/net/netdevsim/fib.c | 102 |
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 | ||
34 | struct nsim_fib_data { | 35 | struct 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 | ||
40 | u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, | 40 | static unsigned int nsim_fib_net_id; |
41 | enum nsim_resource_id res_id, bool max) | 41 | |
42 | u64 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 | ||
65 | int nsim_fib_set_max(struct nsim_fib_data *fib_data, | 67 | int 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 | ||
121 | static int nsim_fib_rule_event(struct nsim_fib_data *data, | 123 | static 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 | ||
158 | static int nsim_fib_event(struct nsim_fib_data *data, | 160 | static 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, | |||
176 | static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event, | 178 | static 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 */ |
202 | static void nsim_fib_dump_inconsistent(struct notifier_block *nb) | 200 | static 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 | ||
213 | struct nsim_fib_data *nsim_fib_create(void) | 218 | static 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) | 223 | static 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; | 236 | static 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 | ||
237 | err_out: | 242 | void 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 | ||
242 | void nsim_fib_destroy(struct nsim_fib_data *data) | 248 | int 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 | |||
264 | err_out: | ||
265 | return err; | ||
246 | } | 266 | } |