/*
 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Development of this code funded by Astaro AG (http://www.astaro.com/)
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/rbtree.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>

static DEFINE_SPINLOCK(nft_rbtree_lock);

struct nft_rbtree {
	struct rb_root		root;
};

struct nft_rbtree_elem {
	struct rb_node		node;
	u16			flags;
	struct nft_data		key;
	struct nft_data		data[];
};

static bool nft_rbtree_lookup(const struct nft_set *set,
			      const struct nft_data *key,
			      struct nft_data *data)
{
	const struct nft_rbtree *priv = nft_set_priv(set);
	const struct nft_rbtree_elem *rbe, *interval = NULL;
	const struct rb_node *parent = priv->root.rb_node;
	int d;

	spin_lock_bh(&nft_rbtree_lock);
	while (parent != NULL) {
		rbe = rb_entry(parent, struct nft_rbtree_elem, node);

		d = nft_data_cmp(&rbe->key, key, set->klen);
		if (d < 0) {
			parent = parent->rb_left;
			interval = rbe;
		} else if (d > 0)
			parent = parent->rb_right;
		else {
found:
			if (rbe->flags & NFT_SET_ELEM_INTERVAL_END)
				goto out;
			if (set->flags & NFT_SET_MAP)
				nft_data_copy(data, rbe->data);

			spin_unlock_bh(&nft_rbtree_lock);
			return true;
		}
	}

	if (set->flags & NFT_SET_INTERVAL && interval != NULL) {
		rbe = interval;
		goto found;
	}
out:
	spin_unlock_bh(&nft_rbtree_lock);
	return false;
}

static void nft_rbtree_elem_destroy(const struct nft_set *set,
				    struct nft_rbtree_elem *rbe)
{
	nft_data_uninit(&rbe->key, NFT_DATA_VALUE);
	if (set->flags & NFT_SET_MAP &&
	    !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
		nft_data_uninit(rbe->data, set->dtype);

	kfree(rbe);
}

static int __nft_rbtree_insert(const struct nft_set *set,
			       struct nft_rbtree_elem *new)
{
	struct nft_rbtree *priv = nft_set_priv(set);
	struct nft_rbtree_elem *rbe;
	struct rb_node *parent, **p;
	int d;

	parent = NULL;
	p = &priv->root.rb_node;
	while (*p != NULL) {
		parent = *p;
		rbe = rb_entry(parent, struct nft_rbtree_elem, node);
		d = nft_data_cmp(&rbe->key, &new->key, set->klen);
		if (d < 0)
			p = &parent->rb_left;
		else if (d > 0)
			p = &parent->rb_right;
		else
			return -EEXIST;
	}
	rb_link_node(&new->node, parent, p);
	rb_insert_color(&new->node, &priv->root);
	return 0;
}

static int nft_rbtree_insert(const struct nft_set *set,
			     const struct nft_set_elem *elem)
{
	struct nft_rbtree_elem *rbe;
	unsigned int size;
	int err;

	size = sizeof(*rbe);
	if (set->flags & NFT_SET_MAP &&
	    !(elem->flags & NFT_SET_ELEM_INTERVAL_END))
		size += sizeof(rbe->data[0]);

	rbe = kzalloc(size, GFP_KERNEL);
	if (rbe == NULL)
		return -ENOMEM;

	rbe->flags = elem->flags;
	nft_data_copy(&rbe->key, &elem->key);
	if (set->flags & NFT_SET_MAP &&
	    !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
		nft_data_copy(rbe->data, &elem->data);

	spin_lock_bh(&nft_rbtree_lock);
	err = __nft_rbtree_insert(set, rbe);
	if (err < 0)
		kfree(rbe);

	spin_unlock_bh(&nft_rbtree_lock);
	return err;
}

static void nft_rbtree_remove(const struct nft_set *set,
			      const struct nft_set_elem *elem)
{
	struct nft_rbtree *priv = nft_set_priv(set);
	struct nft_rbtree_elem *rbe = elem->cookie;

	spin_lock_bh(&nft_rbtree_lock);
	rb_erase(&rbe->node, &priv->root);
	spin_unlock_bh(&nft_rbtree_lock);
	kfree(rbe);
}

static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
{
	const struct nft_rbtree *priv = nft_set_priv(set);
	const struct rb_node *parent = priv->root.rb_node;
	struct nft_rbtree_elem *rbe;
	int d;

	spin_lock_bh(&nft_rbtree_lock);
	while (parent != NULL) {
		rbe = rb_entry(parent, struct nft_rbtree_elem, node);

		d = nft_data_cmp(&rbe->key, &elem->key, set->klen);
		if (d < 0)
			parent = parent->rb_left;
		else if (d > 0)
			parent = parent->rb_right;
		else {
			elem->cookie = rbe;
			if (set->flags & NFT_SET_MAP &&
			    !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
				nft_data_copy(&elem->data, rbe->data);
			elem->flags = rbe->flags;
			spin_unlock_bh(&nft_rbtree_lock);
			return 0;
		}
	}
	spin_unlock_bh(&nft_rbtree_lock);
	return -ENOENT;
}

static void nft_rbtree_walk(const struct nft_ctx *ctx,
			    const struct nft_set *set,
			    struct nft_set_iter *iter)
{
	const struct nft_rbtree *priv = nft_set_priv(set);
	const struct nft_rbtree_elem *rbe;
	struct nft_set_elem elem;
	struct rb_node *node;

	spin_lock_bh(&nft_rbtree_lock);
	for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
		if (iter->count < iter->skip)
			goto cont;

		rbe = rb_entry(node, struct nft_rbtree_elem, node);
		nft_data_copy(&elem.key, &rbe->key);
		if (set->flags & NFT_SET_MAP &&
		    !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
			nft_data_copy(&elem.data, rbe->data);
		elem.flags = rbe->flags;

		iter->err = iter->fn(ctx, set, iter, &elem);
		if (iter->err < 0) {
			spin_unlock_bh(&nft_rbtree_lock);
			return;
		}
cont:
		iter->count++;
	}
	spin_unlock_bh(&nft_rbtree_lock);
}

static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[])
{
	return sizeof(struct nft_rbtree);
}

static int nft_rbtree_init(const struct nft_set *set,
			   const struct nft_set_desc *desc,
			   const struct nlattr * const nla[])
{
	struct nft_rbtree *priv = nft_set_priv(set);

	priv->root = RB_ROOT;
	return 0;
}

static void nft_rbtree_destroy(const struct nft_set *set)
{
	struct nft_rbtree *priv = nft_set_priv(set);
	struct nft_rbtree_elem *rbe;
	struct rb_node *node;

	spin_lock_bh(&nft_rbtree_lock);
	while ((node = priv->root.rb_node) != NULL) {
		rb_erase(node, &priv->root);
		rbe = rb_entry(node, struct nft_rbtree_elem, node);
		nft_rbtree_elem_destroy(set, rbe);
	}
	spin_unlock_bh(&nft_rbtree_lock);
}

static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,
				struct nft_set_estimate *est)
{
	unsigned int nsize;

	nsize = sizeof(struct nft_rbtree_elem);
	if (features & NFT_SET_MAP)
		nsize += FIELD_SIZEOF(struct nft_rbtree_elem, data[0]);

	if (desc->size)
		est->size = sizeof(struct nft_rbtree) + desc->size * nsize;
	else
		est->size = nsize;

	est->class = NFT_SET_CLASS_O_LOG_N;

	return true;
}

static struct nft_set_ops nft_rbtree_ops __read_mostly = {
	.privsize	= nft_rbtree_privsize,
	.estimate	= nft_rbtree_estimate,
	.init		= nft_rbtree_init,
	.destroy	= nft_rbtree_destroy,
	.insert		= nft_rbtree_insert,
	.remove		= nft_rbtree_remove,
	.get		= nft_rbtree_get,
	.lookup		= nft_rbtree_lookup,
	.walk		= nft_rbtree_walk,
	.features	= NFT_SET_INTERVAL | NFT_SET_MAP,
	.owner		= THIS_MODULE,
};

static int __init nft_rbtree_module_init(void)
{
	return nft_register_set(&nft_rbtree_ops);
}

static void __exit nft_rbtree_module_exit(void)
{
	nft_unregister_set(&nft_rbtree_ops);
}

module_init(nft_rbtree_module_init);
module_exit(nft_rbtree_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_ALIAS_NFT_SET();
