diff options
Diffstat (limited to 'drivers/net/netdevsim/fib.c')
-rw-r--r-- | drivers/net/netdevsim/fib.c | 144 |
1 files changed, 90 insertions, 54 deletions
diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c index f61d094746c0..7de17e42d77a 100644 --- a/drivers/net/netdevsim/fib.c +++ b/drivers/net/netdevsim/fib.c @@ -18,7 +18,7 @@ #include <net/ip_fib.h> #include <net/ip6_fib.h> #include <net/fib_rules.h> -#include <net/netns/generic.h> +#include <net/net_namespace.h> #include "netdevsim.h" @@ -33,15 +33,14 @@ struct nsim_per_fib_data { }; struct nsim_fib_data { + struct notifier_block fib_nb; struct nsim_per_fib_data ipv4; struct nsim_per_fib_data ipv6; }; -static unsigned int nsim_fib_net_id; - -u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max) +u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, + enum nsim_resource_id res_id, bool max) { - struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id); struct nsim_fib_entry *entry; switch (res_id) { @@ -64,10 +63,10 @@ u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max) return max ? entry->max : entry->num; } -int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val, +int nsim_fib_set_max(struct nsim_fib_data *fib_data, + enum nsim_resource_id res_id, u64 val, struct netlink_ext_ack *extack) { - struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id); struct nsim_fib_entry *entry; int err = 0; @@ -120,9 +119,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add, return err; } -static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add) +static int nsim_fib_rule_event(struct nsim_fib_data *data, + struct fib_notifier_info *info, bool add) { - struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id); struct netlink_ext_ack *extack = info->extack; int err = 0; @@ -157,9 +156,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add, return err; } -static int nsim_fib_event(struct fib_notifier_info *info, bool add) +static int nsim_fib_event(struct nsim_fib_data *data, + struct fib_notifier_info *info, bool add) { - struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id); struct netlink_ext_ack *extack = info->extack; int err = 0; @@ -178,18 +177,25 @@ static int nsim_fib_event(struct fib_notifier_info *info, bool add) static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event, void *ptr) { + struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data, + fib_nb); struct fib_notifier_info *info = ptr; int err = 0; + if (!net_eq(info->net, &init_net)) + return NOTIFY_DONE; + switch (event) { case FIB_EVENT_RULE_ADD: /* fall through */ case FIB_EVENT_RULE_DEL: - err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD); + err = nsim_fib_rule_event(data, info, + event == FIB_EVENT_RULE_ADD); break; case FIB_EVENT_ENTRY_ADD: /* fall through */ case FIB_EVENT_ENTRY_DEL: - err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD); + err = nsim_fib_event(data, info, + event == FIB_EVENT_ENTRY_ADD); break; } @@ -199,68 +205,98 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event, /* inconsistent dump, trying again */ static void nsim_fib_dump_inconsistent(struct notifier_block *nb) { - struct nsim_fib_data *data; - struct net *net; + struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data, + fib_nb); - rcu_read_lock(); - for_each_net_rcu(net) { - data = net_generic(net, nsim_fib_net_id); + data->ipv4.fib.num = 0ULL; + data->ipv4.rules.num = 0ULL; + data->ipv6.fib.num = 0ULL; + data->ipv6.rules.num = 0ULL; +} - data->ipv4.fib.num = 0ULL; - data->ipv4.rules.num = 0ULL; +static u64 nsim_fib_ipv4_resource_occ_get(void *priv) +{ + struct nsim_fib_data *data = priv; - data->ipv6.fib.num = 0ULL; - data->ipv6.rules.num = 0ULL; - } - rcu_read_unlock(); + return nsim_fib_get_val(data, NSIM_RESOURCE_IPV4_FIB, false); } -static struct notifier_block nsim_fib_nb = { - .notifier_call = nsim_fib_event_nb, -}; - -/* Initialize per network namespace state */ -static int __net_init nsim_fib_netns_init(struct net *net) +static u64 nsim_fib_ipv4_rules_res_occ_get(void *priv) { - struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id); + struct nsim_fib_data *data = priv; - data->ipv4.fib.max = (u64)-1; - data->ipv4.rules.max = (u64)-1; + return nsim_fib_get_val(data, NSIM_RESOURCE_IPV4_FIB_RULES, false); +} - data->ipv6.fib.max = (u64)-1; - data->ipv6.rules.max = (u64)-1; +static u64 nsim_fib_ipv6_resource_occ_get(void *priv) +{ + struct nsim_fib_data *data = priv; - return 0; + return nsim_fib_get_val(data, NSIM_RESOURCE_IPV6_FIB, false); } -static struct pernet_operations nsim_fib_net_ops = { - .init = nsim_fib_netns_init, - .id = &nsim_fib_net_id, - .size = sizeof(struct nsim_fib_data), -}; - -void nsim_fib_exit(void) +static u64 nsim_fib_ipv6_rules_res_occ_get(void *priv) { - unregister_pernet_subsys(&nsim_fib_net_ops); - unregister_fib_notifier(&nsim_fib_nb); + struct nsim_fib_data *data = priv; + + return nsim_fib_get_val(data, NSIM_RESOURCE_IPV6_FIB_RULES, false); } -int nsim_fib_init(void) +struct nsim_fib_data *nsim_fib_create(struct devlink *devlink) { + struct nsim_fib_data *data; int err; - err = register_pernet_subsys(&nsim_fib_net_ops); - if (err < 0) { - pr_err("Failed to register pernet subsystem\n"); - goto err_out; - } + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); - err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent); - if (err < 0) { + data->ipv4.fib.max = (u64)-1; + data->ipv4.rules.max = (u64)-1; + + data->ipv6.fib.max = (u64)-1; + data->ipv6.rules.max = (u64)-1; + + data->fib_nb.notifier_call = nsim_fib_event_nb; + err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent); + if (err) { pr_err("Failed to register fib notifier\n"); goto err_out; } + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV4_FIB, + nsim_fib_ipv4_resource_occ_get, + data); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV4_FIB_RULES, + nsim_fib_ipv4_rules_res_occ_get, + data); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV6_FIB, + nsim_fib_ipv6_resource_occ_get, + data); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV6_FIB_RULES, + nsim_fib_ipv6_rules_res_occ_get, + data); + return data; + err_out: - return err; + kfree(data); + return ERR_PTR(err); +} + +void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *data) +{ + devlink_resource_occ_get_unregister(devlink, + NSIM_RESOURCE_IPV6_FIB_RULES); + devlink_resource_occ_get_unregister(devlink, + NSIM_RESOURCE_IPV6_FIB); + devlink_resource_occ_get_unregister(devlink, + NSIM_RESOURCE_IPV4_FIB_RULES); + devlink_resource_occ_get_unregister(devlink, + NSIM_RESOURCE_IPV4_FIB); + unregister_fib_notifier(&data->fib_nb); + kfree(data); } |