/*
 * Copyright (c) 2018 Cumulus Networks. All rights reserved.
 * Copyright (c) 2018 David Ahern <dsa@cumulusnetworks.com>
 *
 * This software is licensed under the GNU General License Version 2,
 * June 1991 as shown in the file COPYING in the top-level directory of this
 * source tree.
 *
 * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
 * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
 * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 */

#include <net/fib_notifier.h>
#include <net/ip_fib.h>
#include <net/ip6_fib.h>
#include <net/fib_rules.h>
#include <net/netns/generic.h>

#include "netdevsim.h"

struct nsim_fib_entry {
	u64 max;
	u64 num;
};

struct nsim_per_fib_data {
	struct nsim_fib_entry fib;
	struct nsim_fib_entry rules;
};

struct nsim_fib_data {
	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)
{
	struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
	struct nsim_fib_entry *entry;

	switch (res_id) {
	case NSIM_RESOURCE_IPV4_FIB:
		entry = &fib_data->ipv4.fib;
		break;
	case NSIM_RESOURCE_IPV4_FIB_RULES:
		entry = &fib_data->ipv4.rules;
		break;
	case NSIM_RESOURCE_IPV6_FIB:
		entry = &fib_data->ipv6.fib;
		break;
	case NSIM_RESOURCE_IPV6_FIB_RULES:
		entry = &fib_data->ipv6.rules;
		break;
	default:
		return 0;
	}

	return max ? entry->max : entry->num;
}

int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val)
{
	struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
	struct nsim_fib_entry *entry;
	int err = 0;

	switch (res_id) {
	case NSIM_RESOURCE_IPV4_FIB:
		entry = &fib_data->ipv4.fib;
		break;
	case NSIM_RESOURCE_IPV4_FIB_RULES:
		entry = &fib_data->ipv4.rules;
		break;
	case NSIM_RESOURCE_IPV6_FIB:
		entry = &fib_data->ipv6.fib;
		break;
	case NSIM_RESOURCE_IPV6_FIB_RULES:
		entry = &fib_data->ipv6.rules;
		break;
	default:
		return 0;
	}

	/* not allowing a new max to be less than curren occupancy
	 * --> no means of evicting entries
	 */
	if (val < entry->num)
		err = -EINVAL;
	else
		entry->max = val;

	return err;
}

static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
				 struct netlink_ext_ack *extack)
{
	int err = 0;

	if (add) {
		if (entry->num < entry->max) {
			entry->num++;
		} else {
			err = -ENOSPC;
			NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported fib rule entries");
		}
	} else {
		entry->num--;
	}

	return err;
}

static int nsim_fib_rule_event(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;

	switch (info->family) {
	case AF_INET:
		err = nsim_fib_rule_account(&data->ipv4.rules, add, extack);
		break;
	case AF_INET6:
		err = nsim_fib_rule_account(&data->ipv6.rules, add, extack);
		break;
	}

	return err;
}

static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
			    struct netlink_ext_ack *extack)
{
	int err = 0;

	if (add) {
		if (entry->num < entry->max) {
			entry->num++;
		} else {
			err = -ENOSPC;
			NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported fib entries");
		}
	} else {
		entry->num--;
	}

	return err;
}

static int nsim_fib_event(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;

	switch (info->family) {
	case AF_INET:
		err = nsim_fib_account(&data->ipv4.fib, add, extack);
		break;
	case AF_INET6:
		err = nsim_fib_account(&data->ipv6.fib, add, extack);
		break;
	}

	return err;
}

static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
			     void *ptr)
{
	struct fib_notifier_info *info = ptr;
	int err = 0;

	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);
		break;

	case FIB_EVENT_ENTRY_ADD:  /* fall through */
	case FIB_EVENT_ENTRY_DEL:
		err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
		break;
	}

	return notifier_from_errno(err);
}

/* inconsistent dump, trying again */
static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
{
	struct nsim_fib_data *data;
	struct net *net;

	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;
	}
	rcu_read_unlock();
}

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)
{
	struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);

	data->ipv4.fib.max = (u64)-1;
	data->ipv4.rules.max = (u64)-1;

	data->ipv6.fib.max = (u64)-1;
	data->ipv6.rules.max = (u64)-1;

	return 0;
}

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)
{
	unregister_pernet_subsys(&nsim_fib_net_ops);
	unregister_fib_notifier(&nsim_fib_nb);
}

int nsim_fib_init(void)
{
	int err;

	err = register_pernet_subsys(&nsim_fib_net_ops);
	if (err < 0) {
		pr_err("Failed to register pernet subsystem\n");
		goto err_out;
	}

	err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
	if (err < 0) {
		pr_err("Failed to register fib notifier\n");
		goto err_out;
	}

err_out:
	return err;
}
