Commit 39661e2c authored by David S. Miller's avatar David S. Miller

Merge branch 'tc_action-ns'

Cong Wang says:

====================
net_sched: add network namespace support for tc actions

This patchset adds network namespace support for tc actions.

v2:
* pull the first patch into net-next
* reduce code duplication by introducing more helper functions
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 555d5b70 ddf97ccd
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <net/sch_generic.h> #include <net/sch_generic.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
struct tcf_common { struct tcf_common {
struct hlist_node tcfc_head; struct hlist_node tcfc_head;
...@@ -65,11 +67,6 @@ static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask) ...@@ -65,11 +67,6 @@ static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask)
return 0; return 0;
} }
static inline void tcf_hashinfo_destroy(struct tcf_hashinfo *hf)
{
kfree(hf->htab);
}
/* Update lastuse only if needed, to avoid dirtying a cache line. /* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice. * We use a temp variable to avoid fetching jiffies twice.
*/ */
...@@ -92,31 +89,65 @@ struct tc_action { ...@@ -92,31 +89,65 @@ struct tc_action {
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */ __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order; __u32 order;
struct list_head list; struct list_head list;
struct tcf_hashinfo *hinfo;
}; };
struct tc_action_ops { struct tc_action_ops {
struct list_head head; struct list_head head;
struct tcf_hashinfo *hinfo;
char kind[IFNAMSIZ]; char kind[IFNAMSIZ];
__u32 type; /* TBD to match kind */ __u32 type; /* TBD to match kind */
struct module *owner; struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *); int (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int); int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void (*cleanup)(struct tc_action *, int bind); void (*cleanup)(struct tc_action *, int bind);
int (*lookup)(struct tc_action *, u32); int (*lookup)(struct net *, struct tc_action *, u32);
int (*init)(struct net *net, struct nlattr *nla, int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *act, int ovr, struct nlattr *est, struct tc_action *act, int ovr,
int bind); int bind);
int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *); int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, struct tc_action *);
}; };
int tcf_hash_search(struct tc_action *a, u32 index); struct tc_action_net {
u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo); struct tcf_hashinfo *hinfo;
int tcf_hash_check(u32 index, struct tc_action *a, int bind); const struct tc_action_ops *ops;
int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, };
int size, int bind, bool cpustats);
static inline
int tc_action_net_init(struct tc_action_net *tn, const struct tc_action_ops *ops,
unsigned int mask)
{
int err = 0;
tn->hinfo = kmalloc(sizeof(*tn->hinfo), GFP_KERNEL);
if (!tn->hinfo)
return -ENOMEM;
tn->ops = ops;
err = tcf_hashinfo_init(tn->hinfo, mask);
if (err)
kfree(tn->hinfo);
return err;
}
void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
struct tcf_hashinfo *hinfo);
static inline void tc_action_net_exit(struct tc_action_net *tn)
{
tcf_hashinfo_destroy(tn->ops, tn->hinfo);
}
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a);
int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index);
u32 tcf_hash_new_index(struct tc_action_net *tn);
int tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a,
int bind);
int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action *a, int size, int bind, bool cpustats);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est); void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
void tcf_hash_insert(struct tc_action *a); void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
int __tcf_hash_release(struct tc_action *a, bool bind, bool strict); int __tcf_hash_release(struct tc_action *a, bool bind, bool strict);
...@@ -125,8 +156,8 @@ static inline int tcf_hash_release(struct tc_action *a, bool bind) ...@@ -125,8 +156,8 @@ static inline int tcf_hash_release(struct tc_action *a, bool bind)
return __tcf_hash_release(a, bind, false); return __tcf_hash_release(a, bind, false);
} }
int tcf_register_action(struct tc_action_ops *a, unsigned int mask); int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
int tcf_unregister_action(struct tc_action_ops *a); int tcf_unregister_action(struct tc_action_ops *a, struct pernet_operations *ops);
int tcf_action_destroy(struct list_head *actions, int bind); int tcf_action_destroy(struct list_head *actions, int bind);
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions, int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
struct tcf_result *res); struct tcf_result *res);
......
...@@ -36,10 +36,9 @@ static void free_tcf(struct rcu_head *head) ...@@ -36,10 +36,9 @@ static void free_tcf(struct rcu_head *head)
kfree(p); kfree(p);
} }
static void tcf_hash_destroy(struct tc_action *a) static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a)
{ {
struct tcf_common *p = a->priv; struct tcf_common *p = a->priv;
struct tcf_hashinfo *hinfo = a->ops->hinfo;
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
hlist_del(&p->tcfc_head); hlist_del(&p->tcfc_head);
...@@ -68,8 +67,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) ...@@ -68,8 +67,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
if (a->ops->cleanup) if (a->ops->cleanup)
a->ops->cleanup(a, bind); a->ops->cleanup(a, bind);
tcf_hash_destroy(a); tcf_hash_destroy(a->hinfo, a);
ret = 1; ret = ACT_P_DELETED;
} }
} }
...@@ -77,10 +76,9 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) ...@@ -77,10 +76,9 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
} }
EXPORT_SYMBOL(__tcf_hash_release); EXPORT_SYMBOL(__tcf_hash_release);
static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
struct tc_action *a) struct netlink_callback *cb, struct tc_action *a)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo;
struct hlist_head *head; struct hlist_head *head;
struct tcf_common *p; struct tcf_common *p;
int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
...@@ -126,9 +124,9 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, ...@@ -126,9 +124,9 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
goto done; goto done;
} }
static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
struct tc_action *a)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo;
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *n; struct hlist_node *n;
struct tcf_common *p; struct tcf_common *p;
...@@ -163,18 +161,24 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) ...@@ -163,18 +161,24 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
return ret; return ret;
} }
static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
int type, struct tc_action *a) struct netlink_callback *cb, int type,
struct tc_action *a)
{ {
struct tcf_hashinfo *hinfo = tn->hinfo;
a->hinfo = hinfo;
if (type == RTM_DELACTION) { if (type == RTM_DELACTION) {
return tcf_del_walker(skb, a); return tcf_del_walker(hinfo, skb, a);
} else if (type == RTM_GETACTION) { } else if (type == RTM_GETACTION) {
return tcf_dump_walker(skb, cb, a); return tcf_dump_walker(hinfo, skb, cb, a);
} else { } else {
WARN(1, "tcf_generic_walker: unknown action %d\n", type); WARN(1, "tcf_generic_walker: unknown action %d\n", type);
return -EINVAL; return -EINVAL;
} }
} }
EXPORT_SYMBOL(tcf_generic_walker);
static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
{ {
...@@ -191,8 +195,9 @@ static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) ...@@ -191,8 +195,9 @@ static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
return p; return p;
} }
u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo) u32 tcf_hash_new_index(struct tc_action_net *tn)
{ {
struct tcf_hashinfo *hinfo = tn->hinfo;
u32 val = hinfo->index; u32 val = hinfo->index;
do { do {
...@@ -205,28 +210,31 @@ u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo) ...@@ -205,28 +210,31 @@ u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo)
} }
EXPORT_SYMBOL(tcf_hash_new_index); EXPORT_SYMBOL(tcf_hash_new_index);
int tcf_hash_search(struct tc_action *a, u32 index) int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
struct tcf_common *p = tcf_hash_lookup(index, hinfo); struct tcf_common *p = tcf_hash_lookup(index, hinfo);
if (p) { if (p) {
a->priv = p; a->priv = p;
a->hinfo = hinfo;
return 1; return 1;
} }
return 0; return 0;
} }
EXPORT_SYMBOL(tcf_hash_search); EXPORT_SYMBOL(tcf_hash_search);
int tcf_hash_check(u32 index, struct tc_action *a, int bind) int tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a,
int bind)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
struct tcf_common *p = NULL; struct tcf_common *p = NULL;
if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) { if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) {
if (bind) if (bind)
p->tcfc_bindcnt++; p->tcfc_bindcnt++;
p->tcfc_refcnt++; p->tcfc_refcnt++;
a->priv = p; a->priv = p;
a->hinfo = hinfo;
return 1; return 1;
} }
return 0; return 0;
...@@ -243,11 +251,11 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) ...@@ -243,11 +251,11 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
} }
EXPORT_SYMBOL(tcf_hash_cleanup); EXPORT_SYMBOL(tcf_hash_cleanup);
int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
int size, int bind, bool cpustats) struct tc_action *a, int size, int bind, bool cpustats)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo;
struct tcf_common *p = kzalloc(size, GFP_KERNEL); struct tcf_common *p = kzalloc(size, GFP_KERNEL);
struct tcf_hashinfo *hinfo = tn->hinfo;
int err = -ENOMEM; int err = -ENOMEM;
if (unlikely(!p)) if (unlikely(!p))
...@@ -272,7 +280,7 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, ...@@ -272,7 +280,7 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
} }
spin_lock_init(&p->tcfc_lock); spin_lock_init(&p->tcfc_lock);
INIT_HLIST_NODE(&p->tcfc_head); INIT_HLIST_NODE(&p->tcfc_head);
p->tcfc_index = index ? index : tcf_hash_new_index(hinfo); p->tcfc_index = index ? index : tcf_hash_new_index(tn);
p->tcfc_tm.install = jiffies; p->tcfc_tm.install = jiffies;
p->tcfc_tm.lastuse = jiffies; p->tcfc_tm.lastuse = jiffies;
if (est) { if (est) {
...@@ -286,14 +294,15 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, ...@@ -286,14 +294,15 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
} }
a->priv = (void *) p; a->priv = (void *) p;
a->hinfo = hinfo;
return 0; return 0;
} }
EXPORT_SYMBOL(tcf_hash_create); EXPORT_SYMBOL(tcf_hash_create);
void tcf_hash_insert(struct tc_action *a) void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a)
{ {
struct tcf_common *p = a->priv; struct tcf_common *p = a->priv;
struct tcf_hashinfo *hinfo = a->ops->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
...@@ -302,59 +311,78 @@ void tcf_hash_insert(struct tc_action *a) ...@@ -302,59 +311,78 @@ void tcf_hash_insert(struct tc_action *a)
} }
EXPORT_SYMBOL(tcf_hash_insert); EXPORT_SYMBOL(tcf_hash_insert);
void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
struct tcf_hashinfo *hinfo)
{
struct tc_action a = {
.ops = ops,
.hinfo = hinfo,
};
int i;
for (i = 0; i < hinfo->hmask + 1; i++) {
struct tcf_common *p;
struct hlist_node *n;
hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) {
int ret;
a.priv = p;
ret = __tcf_hash_release(&a, false, true);
if (ret == ACT_P_DELETED)
module_put(ops->owner);
else if (ret < 0)
return;
}
}
kfree(hinfo->htab);
}
EXPORT_SYMBOL(tcf_hashinfo_destroy);
static LIST_HEAD(act_base); static LIST_HEAD(act_base);
static DEFINE_RWLOCK(act_mod_lock); static DEFINE_RWLOCK(act_mod_lock);
int tcf_register_action(struct tc_action_ops *act, unsigned int mask) int tcf_register_action(struct tc_action_ops *act,
struct pernet_operations *ops)
{ {
struct tc_action_ops *a; struct tc_action_ops *a;
int err; int ret;
/* Must supply act, dump and init */ if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
if (!act->act || !act->dump || !act->init)
return -EINVAL; return -EINVAL;
/* Supply defaults */
if (!act->lookup)
act->lookup = tcf_hash_search;
if (!act->walk)
act->walk = tcf_generic_walker;
act->hinfo = kmalloc(sizeof(struct tcf_hashinfo), GFP_KERNEL);
if (!act->hinfo)
return -ENOMEM;
err = tcf_hashinfo_init(act->hinfo, mask);
if (err) {
kfree(act->hinfo);
return err;
}
write_lock(&act_mod_lock); write_lock(&act_mod_lock);
list_for_each_entry(a, &act_base, head) { list_for_each_entry(a, &act_base, head) {
if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) { if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
write_unlock(&act_mod_lock); write_unlock(&act_mod_lock);
tcf_hashinfo_destroy(act->hinfo);
kfree(act->hinfo);
return -EEXIST; return -EEXIST;
} }
} }
list_add_tail(&act->head, &act_base); list_add_tail(&act->head, &act_base);
write_unlock(&act_mod_lock); write_unlock(&act_mod_lock);
ret = register_pernet_subsys(ops);
if (ret) {
tcf_unregister_action(act, ops);
return ret;
}
return 0; return 0;
} }
EXPORT_SYMBOL(tcf_register_action); EXPORT_SYMBOL(tcf_register_action);
int tcf_unregister_action(struct tc_action_ops *act) int tcf_unregister_action(struct tc_action_ops *act,
struct pernet_operations *ops)
{ {
struct tc_action_ops *a; struct tc_action_ops *a;
int err = -ENOENT; int err = -ENOENT;
unregister_pernet_subsys(ops);
write_lock(&act_mod_lock); write_lock(&act_mod_lock);
list_for_each_entry(a, &act_base, head) { list_for_each_entry(a, &act_base, head) {
if (a == act) { if (a == act) {
list_del(&act->head); list_del(&act->head);
tcf_hashinfo_destroy(act->hinfo);
kfree(act->hinfo);
err = 0; err = 0;
break; break;
} }
...@@ -721,8 +749,8 @@ static struct tc_action *create_a(int i) ...@@ -721,8 +749,8 @@ static struct tc_action *create_a(int i)
return act; return act;
} }
static struct tc_action * static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid) struct nlmsghdr *n, u32 portid)
{ {
struct nlattr *tb[TCA_ACT_MAX + 1]; struct nlattr *tb[TCA_ACT_MAX + 1];
struct tc_action *a; struct tc_action *a;
...@@ -749,7 +777,7 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid) ...@@ -749,7 +777,7 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
if (a->ops == NULL) /* could happen in batch of actions */ if (a->ops == NULL) /* could happen in batch of actions */
goto err_free; goto err_free;
err = -ENOENT; err = -ENOENT;
if (a->ops->lookup(a, index) == 0) if (a->ops->lookup(net, a, index) == 0)
goto err_mod; goto err_mod;
module_put(a->ops->owner); module_put(a->ops->owner);
...@@ -819,7 +847,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -819,7 +847,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
if (nest == NULL) if (nest == NULL)
goto out_module_put; goto out_module_put;
err = a.ops->walk(skb, &dcb, RTM_DELACTION, &a); err = a.ops->walk(net, skb, &dcb, RTM_DELACTION, &a);
if (err < 0) if (err < 0)
goto out_module_put; goto out_module_put;
if (err == 0) if (err == 0)
...@@ -897,7 +925,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, ...@@ -897,7 +925,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
} }
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
act = tcf_action_get_1(tb[i], n, portid); act = tcf_action_get_1(net, tb[i], n, portid);
if (IS_ERR(act)) { if (IS_ERR(act)) {
ret = PTR_ERR(act); ret = PTR_ERR(act);
goto err; goto err;
...@@ -1044,6 +1072,7 @@ find_dump_kind(const struct nlmsghdr *n) ...@@ -1044,6 +1072,7 @@ find_dump_kind(const struct nlmsghdr *n)
static int static int
tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct net *net = sock_net(skb->sk);
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct nlattr *nest; struct nlattr *nest;
...@@ -1078,7 +1107,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1078,7 +1107,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
if (nest == NULL) if (nest == NULL)
goto out_module_put; goto out_module_put;
ret = a_o->walk(skb, cb, RTM_GETACTION, &a); ret = a_o->walk(net, skb, cb, RTM_GETACTION, &a);
if (ret < 0) if (ret < 0)
goto out_module_put; goto out_module_put;
......
...@@ -33,6 +33,8 @@ struct tcf_bpf_cfg { ...@@ -33,6 +33,8 @@ struct tcf_bpf_cfg {
bool is_ebpf; bool is_ebpf;
}; };
static int bpf_net_id;
static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
struct tcf_result *res) struct tcf_result *res)
{ {
...@@ -275,6 +277,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -275,6 +277,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *act, struct nlattr *est, struct tc_action *act,
int replace, int bind) int replace, int bind)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
struct tcf_bpf_cfg cfg, old; struct tcf_bpf_cfg cfg, old;
struct tc_act_bpf *parm; struct tc_act_bpf *parm;
...@@ -294,8 +297,8 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -294,8 +297,8 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_ACT_BPF_PARMS]); parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
if (!tcf_hash_check(parm->index, act, bind)) { if (!tcf_hash_check(tn, parm->index, act, bind)) {
ret = tcf_hash_create(parm->index, est, act, ret = tcf_hash_create(tn, parm->index, est, act,
sizeof(*prog), bind, true); sizeof(*prog), bind, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -344,7 +347,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -344,7 +347,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
rcu_assign_pointer(prog->filter, cfg.filter); rcu_assign_pointer(prog->filter, cfg.filter);
if (res == ACT_P_CREATED) { if (res == ACT_P_CREATED) {
tcf_hash_insert(act); tcf_hash_insert(tn, act);
} else { } else {
/* make sure the program being replaced is no longer executing */ /* make sure the program being replaced is no longer executing */
synchronize_rcu(); synchronize_rcu();
...@@ -367,6 +370,22 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind) ...@@ -367,6 +370,22 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind)
tcf_bpf_cfg_cleanup(&tmp); tcf_bpf_cfg_cleanup(&tmp);
} }
static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_bpf_ops __read_mostly = { static struct tc_action_ops act_bpf_ops __read_mostly = {
.kind = "bpf", .kind = "bpf",
.type = TCA_ACT_BPF, .type = TCA_ACT_BPF,
...@@ -375,16 +394,39 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { ...@@ -375,16 +394,39 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
.dump = tcf_bpf_dump, .dump = tcf_bpf_dump,
.cleanup = tcf_bpf_cleanup, .cleanup = tcf_bpf_cleanup,
.init = tcf_bpf_init, .init = tcf_bpf_init,
.walk = tcf_bpf_walker,
.lookup = tcf_bpf_search,
};
static __net_init int bpf_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
return tc_action_net_init(tn, &act_bpf_ops, BPF_TAB_MASK);
}
static void __net_exit bpf_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations bpf_net_ops = {
.init = bpf_init_net,
.exit = bpf_exit_net,
.id = &bpf_net_id,
.size = sizeof(struct tc_action_net),
}; };
static int __init bpf_init_module(void) static int __init bpf_init_module(void)
{ {
return tcf_register_action(&act_bpf_ops, BPF_TAB_MASK); return tcf_register_action(&act_bpf_ops, &bpf_net_ops);
} }
static void __exit bpf_cleanup_module(void) static void __exit bpf_cleanup_module(void)
{ {
tcf_unregister_action(&act_bpf_ops); tcf_unregister_action(&act_bpf_ops, &bpf_net_ops);
} }
module_init(bpf_init_module); module_init(bpf_init_module);
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#define CONNMARK_TAB_MASK 3 #define CONNMARK_TAB_MASK 3
static int connmark_net_id;
static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
...@@ -97,6 +99,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -97,6 +99,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1]; struct nlattr *tb[TCA_CONNMARK_MAX + 1];
struct tcf_connmark_info *ci; struct tcf_connmark_info *ci;
struct tc_connmark *parm; struct tc_connmark *parm;
...@@ -111,9 +114,9 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -111,9 +114,9 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_CONNMARK_PARMS]); parm = nla_data(tb[TCA_CONNMARK_PARMS]);
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*ci), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*ci), bind, false);
if (ret) if (ret)
return ret; return ret;
...@@ -122,7 +125,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -122,7 +125,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
ci->net = net; ci->net = net;
ci->zone = parm->zone; ci->zone = parm->zone;
tcf_hash_insert(a); tcf_hash_insert(tn, a);
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
ci = to_connmark(a); ci = to_connmark(a);
...@@ -169,6 +172,22 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -169,6 +172,22 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_connmark_ops = { static struct tc_action_ops act_connmark_ops = {
.kind = "connmark", .kind = "connmark",
.type = TCA_ACT_CONNMARK, .type = TCA_ACT_CONNMARK,
...@@ -176,16 +195,39 @@ static struct tc_action_ops act_connmark_ops = { ...@@ -176,16 +195,39 @@ static struct tc_action_ops act_connmark_ops = {
.act = tcf_connmark, .act = tcf_connmark,
.dump = tcf_connmark_dump, .dump = tcf_connmark_dump,
.init = tcf_connmark_init, .init = tcf_connmark_init,
.walk = tcf_connmark_walker,
.lookup = tcf_connmark_search,
};
static __net_init int connmark_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
return tc_action_net_init(tn, &act_connmark_ops, CONNMARK_TAB_MASK);
}
static void __net_exit connmark_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations connmark_net_ops = {
.init = connmark_init_net,
.exit = connmark_exit_net,
.id = &connmark_net_id,
.size = sizeof(struct tc_action_net),
}; };
static int __init connmark_init_module(void) static int __init connmark_init_module(void)
{ {
return tcf_register_action(&act_connmark_ops, CONNMARK_TAB_MASK); return tcf_register_action(&act_connmark_ops, &connmark_net_ops);
} }
static void __exit connmark_cleanup_module(void) static void __exit connmark_cleanup_module(void)
{ {
tcf_unregister_action(&act_connmark_ops); tcf_unregister_action(&act_connmark_ops, &connmark_net_ops);
} }
module_init(connmark_init_module); module_init(connmark_init_module);
......
...@@ -42,9 +42,13 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { ...@@ -42,9 +42,13 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
}; };
static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est, static int csum_net_id;
struct tc_action *a, int ovr, int bind)
static int tcf_csum_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, int ovr,
int bind)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id);
struct nlattr *tb[TCA_CSUM_MAX + 1]; struct nlattr *tb[TCA_CSUM_MAX + 1];
struct tc_csum *parm; struct tc_csum *parm;
struct tcf_csum *p; struct tcf_csum *p;
...@@ -61,9 +65,9 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est, ...@@ -61,9 +65,9 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_CSUM_PARMS]); parm = nla_data(tb[TCA_CSUM_PARMS]);
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*p), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*p), bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
...@@ -82,7 +86,7 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est, ...@@ -82,7 +86,7 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
spin_unlock_bh(&p->tcf_lock); spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -555,6 +559,22 @@ static int tcf_csum_dump(struct sk_buff *skb, ...@@ -555,6 +559,22 @@ static int tcf_csum_dump(struct sk_buff *skb,
return -1; return -1;
} }
static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_csum_ops = { static struct tc_action_ops act_csum_ops = {
.kind = "csum", .kind = "csum",
.type = TCA_ACT_CSUM, .type = TCA_ACT_CSUM,
...@@ -562,6 +582,29 @@ static struct tc_action_ops act_csum_ops = { ...@@ -562,6 +582,29 @@ static struct tc_action_ops act_csum_ops = {
.act = tcf_csum, .act = tcf_csum,
.dump = tcf_csum_dump, .dump = tcf_csum_dump,
.init = tcf_csum_init, .init = tcf_csum_init,
.walk = tcf_csum_walker,
.lookup = tcf_csum_search,
};
static __net_init int csum_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
return tc_action_net_init(tn, &act_csum_ops, CSUM_TAB_MASK);
}
static void __net_exit csum_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations csum_net_ops = {
.init = csum_init_net,
.exit = csum_exit_net,
.id = &csum_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_DESCRIPTION("Checksum updating actions"); MODULE_DESCRIPTION("Checksum updating actions");
...@@ -569,12 +612,12 @@ MODULE_LICENSE("GPL"); ...@@ -569,12 +612,12 @@ MODULE_LICENSE("GPL");
static int __init csum_init_module(void) static int __init csum_init_module(void)
{ {
return tcf_register_action(&act_csum_ops, CSUM_TAB_MASK); return tcf_register_action(&act_csum_ops, &csum_net_ops);
} }
static void __exit csum_cleanup_module(void) static void __exit csum_cleanup_module(void)
{ {
tcf_unregister_action(&act_csum_ops); tcf_unregister_action(&act_csum_ops, &csum_net_ops);
} }
module_init(csum_init_module); module_init(csum_init_module);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#define GACT_TAB_MASK 15 #define GACT_TAB_MASK 15
static int gact_net_id;
#ifdef CONFIG_GACT_PROB #ifdef CONFIG_GACT_PROB
static int gact_net_rand(struct tcf_gact *gact) static int gact_net_rand(struct tcf_gact *gact)
{ {
...@@ -57,6 +59,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -57,6 +59,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id);
struct nlattr *tb[TCA_GACT_MAX + 1]; struct nlattr *tb[TCA_GACT_MAX + 1];
struct tc_gact *parm; struct tc_gact *parm;
struct tcf_gact *gact; struct tcf_gact *gact;
...@@ -88,9 +91,9 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -88,9 +91,9 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
} }
#endif #endif
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*gact), ret = tcf_hash_create(tn, parm->index, est, a,
bind, true); sizeof(*gact), bind, true);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
...@@ -118,7 +121,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -118,7 +121,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
} }
#endif #endif
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -183,6 +186,22 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ...@@ -183,6 +186,22 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
return -1; return -1;
} }
static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_gact_ops = { static struct tc_action_ops act_gact_ops = {
.kind = "gact", .kind = "gact",
.type = TCA_ACT_GACT, .type = TCA_ACT_GACT,
...@@ -190,6 +209,29 @@ static struct tc_action_ops act_gact_ops = { ...@@ -190,6 +209,29 @@ static struct tc_action_ops act_gact_ops = {
.act = tcf_gact, .act = tcf_gact,
.dump = tcf_gact_dump, .dump = tcf_gact_dump,
.init = tcf_gact_init, .init = tcf_gact_init,
.walk = tcf_gact_walker,
.lookup = tcf_gact_search,
};
static __net_init int gact_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
return tc_action_net_init(tn, &act_gact_ops, GACT_TAB_MASK);
}
static void __net_exit gact_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations gact_net_ops = {
.init = gact_init_net,
.exit = gact_exit_net,
.id = &gact_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
...@@ -203,12 +245,13 @@ static int __init gact_init_module(void) ...@@ -203,12 +245,13 @@ static int __init gact_init_module(void)
#else #else
pr_info("GACT probability NOT on\n"); pr_info("GACT probability NOT on\n");
#endif #endif
return tcf_register_action(&act_gact_ops, GACT_TAB_MASK);
return tcf_register_action(&act_gact_ops, &gact_net_ops);
} }
static void __exit gact_cleanup_module(void) static void __exit gact_cleanup_module(void)
{ {
tcf_unregister_action(&act_gact_ops); tcf_unregister_action(&act_gact_ops, &gact_net_ops);
} }
module_init(gact_init_module); module_init(gact_init_module);
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#define IPT_TAB_MASK 15 #define IPT_TAB_MASK 15
static int ipt_net_id;
static int xt_net_id;
static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook) static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook)
{ {
struct xt_tgchk_param par; struct xt_tgchk_param par;
...@@ -83,8 +87,9 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { ...@@ -83,8 +87,9 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
[TCA_IPT_TARG] = { .len = sizeof(struct xt_entry_target) }, [TCA_IPT_TARG] = { .len = sizeof(struct xt_entry_target) },
}; };
static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
struct tc_action *a, int ovr, int bind) struct nlattr *est, struct tc_action *a, int ovr,
int bind)
{ {
struct nlattr *tb[TCA_IPT_MAX + 1]; struct nlattr *tb[TCA_IPT_MAX + 1];
struct tcf_ipt *ipt; struct tcf_ipt *ipt;
...@@ -113,8 +118,9 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -113,8 +118,9 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
if (tb[TCA_IPT_INDEX] != NULL) if (tb[TCA_IPT_INDEX] != NULL)
index = nla_get_u32(tb[TCA_IPT_INDEX]); index = nla_get_u32(tb[TCA_IPT_INDEX]);
if (!tcf_hash_check(index, a, bind) ) { if (!tcf_hash_check(tn, index, a, bind)) {
ret = tcf_hash_create(index, est, a, sizeof(*ipt), bind, false); ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind,
false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
...@@ -157,7 +163,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -157,7 +163,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
ipt->tcfi_hook = hook; ipt->tcfi_hook = hook;
spin_unlock_bh(&ipt->tcf_lock); spin_unlock_bh(&ipt->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
err3: err3:
...@@ -170,6 +176,24 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -170,6 +176,24 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
return err; return err;
} }
static int tcf_ipt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, int ovr,
int bind)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
return __tcf_ipt_init(tn, nla, est, a, ovr, bind);
}
static int tcf_xt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, int ovr,
int bind)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
return __tcf_ipt_init(tn, nla, est, a, ovr, bind);
}
static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
...@@ -260,6 +284,22 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ...@@ -260,6 +284,22 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
return -1; return -1;
} }
static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_ipt_ops = { static struct tc_action_ops act_ipt_ops = {
.kind = "ipt", .kind = "ipt",
.type = TCA_ACT_IPT, .type = TCA_ACT_IPT,
...@@ -268,8 +308,47 @@ static struct tc_action_ops act_ipt_ops = { ...@@ -268,8 +308,47 @@ static struct tc_action_ops act_ipt_ops = {
.dump = tcf_ipt_dump, .dump = tcf_ipt_dump,
.cleanup = tcf_ipt_release, .cleanup = tcf_ipt_release,
.init = tcf_ipt_init, .init = tcf_ipt_init,
.walk = tcf_ipt_walker,
.lookup = tcf_ipt_search,
};
static __net_init int ipt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
return tc_action_net_init(tn, &act_ipt_ops, IPT_TAB_MASK);
}
static void __net_exit ipt_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations ipt_net_ops = {
.init = ipt_init_net,
.exit = ipt_exit_net,
.id = &ipt_net_id,
.size = sizeof(struct tc_action_net),
}; };
static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_xt_ops = { static struct tc_action_ops act_xt_ops = {
.kind = "xt", .kind = "xt",
.type = TCA_ACT_XT, .type = TCA_ACT_XT,
...@@ -277,7 +356,30 @@ static struct tc_action_ops act_xt_ops = { ...@@ -277,7 +356,30 @@ static struct tc_action_ops act_xt_ops = {
.act = tcf_ipt, .act = tcf_ipt,
.dump = tcf_ipt_dump, .dump = tcf_ipt_dump,
.cleanup = tcf_ipt_release, .cleanup = tcf_ipt_release,
.init = tcf_ipt_init, .init = tcf_xt_init,
.walk = tcf_xt_walker,
.lookup = tcf_xt_search,
};
static __net_init int xt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
return tc_action_net_init(tn, &act_xt_ops, IPT_TAB_MASK);
}
static void __net_exit xt_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations xt_net_ops = {
.init = xt_init_net,
.exit = xt_exit_net,
.id = &xt_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Jamal Hadi Salim(2002-13)"); MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
...@@ -289,12 +391,13 @@ static int __init ipt_init_module(void) ...@@ -289,12 +391,13 @@ static int __init ipt_init_module(void)
{ {
int ret1, ret2; int ret1, ret2;
ret1 = tcf_register_action(&act_xt_ops, IPT_TAB_MASK); ret1 = tcf_register_action(&act_xt_ops, &xt_net_ops);
if (ret1 < 0) if (ret1 < 0)
printk("Failed to load xt action\n"); pr_err("Failed to load xt action\n");
ret2 = tcf_register_action(&act_ipt_ops, IPT_TAB_MASK);
ret2 = tcf_register_action(&act_ipt_ops, &ipt_net_ops);
if (ret2 < 0) if (ret2 < 0)
printk("Failed to load ipt action\n"); pr_err("Failed to load ipt action\n");
if (ret1 < 0 && ret2 < 0) { if (ret1 < 0 && ret2 < 0) {
return ret1; return ret1;
...@@ -304,8 +407,8 @@ static int __init ipt_init_module(void) ...@@ -304,8 +407,8 @@ static int __init ipt_init_module(void)
static void __exit ipt_cleanup_module(void) static void __exit ipt_cleanup_module(void)
{ {
tcf_unregister_action(&act_xt_ops); tcf_unregister_action(&act_ipt_ops, &ipt_net_ops);
tcf_unregister_action(&act_ipt_ops); tcf_unregister_action(&act_xt_ops, &xt_net_ops);
} }
module_init(ipt_init_module); module_init(ipt_init_module);
......
...@@ -50,10 +50,13 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { ...@@ -50,10 +50,13 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
[TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) }, [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
}; };
static int mirred_net_id;
static int tcf_mirred_init(struct net *net, struct nlattr *nla, static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, int ovr, struct nlattr *est, struct tc_action *a, int ovr,
int bind) int bind)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id);
struct nlattr *tb[TCA_MIRRED_MAX + 1]; struct nlattr *tb[TCA_MIRRED_MAX + 1];
struct tc_mirred *parm; struct tc_mirred *parm;
struct tcf_mirred *m; struct tcf_mirred *m;
...@@ -96,11 +99,11 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -96,11 +99,11 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
dev = NULL; dev = NULL;
} }
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
if (dev == NULL) if (dev == NULL)
return -EINVAL; return -EINVAL;
ret = tcf_hash_create(parm->index, est, a, sizeof(*m), ret = tcf_hash_create(tn, parm->index, est, a,
bind, true); sizeof(*m), bind, true);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
...@@ -130,7 +133,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -130,7 +133,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
spin_lock_bh(&mirred_list_lock); spin_lock_bh(&mirred_list_lock);
list_add(&m->tcfm_list, &mirred_list); list_add(&m->tcfm_list, &mirred_list);
spin_unlock_bh(&mirred_list_lock); spin_unlock_bh(&mirred_list_lock);
tcf_hash_insert(a); tcf_hash_insert(tn, a);
} }
return ret; return ret;
...@@ -221,6 +224,22 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i ...@@ -221,6 +224,22 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i
return -1; return -1;
} }
static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
return tcf_hash_search(tn, a, index);
}
static int mirred_device_event(struct notifier_block *unused, static int mirred_device_event(struct notifier_block *unused,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
...@@ -257,6 +276,29 @@ static struct tc_action_ops act_mirred_ops = { ...@@ -257,6 +276,29 @@ static struct tc_action_ops act_mirred_ops = {
.dump = tcf_mirred_dump, .dump = tcf_mirred_dump,
.cleanup = tcf_mirred_release, .cleanup = tcf_mirred_release,
.init = tcf_mirred_init, .init = tcf_mirred_init,
.walk = tcf_mirred_walker,
.lookup = tcf_mirred_search,
};
static __net_init int mirred_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
return tc_action_net_init(tn, &act_mirred_ops, MIRRED_TAB_MASK);
}
static void __net_exit mirred_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations mirred_net_ops = {
.init = mirred_init_net,
.exit = mirred_exit_net,
.id = &mirred_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Jamal Hadi Salim(2002)"); MODULE_AUTHOR("Jamal Hadi Salim(2002)");
...@@ -270,12 +312,12 @@ static int __init mirred_init_module(void) ...@@ -270,12 +312,12 @@ static int __init mirred_init_module(void)
return err; return err;
pr_info("Mirror/redirect action on\n"); pr_info("Mirror/redirect action on\n");
return tcf_register_action(&act_mirred_ops, MIRRED_TAB_MASK); return tcf_register_action(&act_mirred_ops, &mirred_net_ops);
} }
static void __exit mirred_cleanup_module(void) static void __exit mirred_cleanup_module(void)
{ {
tcf_unregister_action(&act_mirred_ops); tcf_unregister_action(&act_mirred_ops, &mirred_net_ops);
unregister_netdevice_notifier(&mirred_device_notifier); unregister_netdevice_notifier(&mirred_device_notifier);
} }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#define NAT_TAB_MASK 15 #define NAT_TAB_MASK 15
static int nat_net_id;
static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
[TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
}; };
...@@ -38,6 +40,7 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { ...@@ -38,6 +40,7 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind) struct tc_action *a, int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id);
struct nlattr *tb[TCA_NAT_MAX + 1]; struct nlattr *tb[TCA_NAT_MAX + 1];
struct tc_nat *parm; struct tc_nat *parm;
int ret = 0, err; int ret = 0, err;
...@@ -54,9 +57,9 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -54,9 +57,9 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_NAT_PARMS]); parm = nla_data(tb[TCA_NAT_PARMS]);
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*p), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*p), bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
...@@ -79,7 +82,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -79,7 +82,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
spin_unlock_bh(&p->tcf_lock); spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -274,6 +277,22 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -274,6 +277,22 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_nat_ops = { static struct tc_action_ops act_nat_ops = {
.kind = "nat", .kind = "nat",
.type = TCA_ACT_NAT, .type = TCA_ACT_NAT,
...@@ -281,6 +300,29 @@ static struct tc_action_ops act_nat_ops = { ...@@ -281,6 +300,29 @@ static struct tc_action_ops act_nat_ops = {
.act = tcf_nat, .act = tcf_nat,
.dump = tcf_nat_dump, .dump = tcf_nat_dump,
.init = tcf_nat_init, .init = tcf_nat_init,
.walk = tcf_nat_walker,
.lookup = tcf_nat_search,
};
static __net_init int nat_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
return tc_action_net_init(tn, &act_nat_ops, NAT_TAB_MASK);
}
static void __net_exit nat_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations nat_net_ops = {
.init = nat_init_net,
.exit = nat_exit_net,
.id = &nat_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_DESCRIPTION("Stateless NAT actions"); MODULE_DESCRIPTION("Stateless NAT actions");
...@@ -288,12 +330,12 @@ MODULE_LICENSE("GPL"); ...@@ -288,12 +330,12 @@ MODULE_LICENSE("GPL");
static int __init nat_init_module(void) static int __init nat_init_module(void)
{ {
return tcf_register_action(&act_nat_ops, NAT_TAB_MASK); return tcf_register_action(&act_nat_ops, &nat_net_ops);
} }
static void __exit nat_cleanup_module(void) static void __exit nat_cleanup_module(void)
{ {
tcf_unregister_action(&act_nat_ops); tcf_unregister_action(&act_nat_ops, &nat_net_ops);
} }
module_init(nat_init_module); module_init(nat_init_module);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#define PEDIT_TAB_MASK 15 #define PEDIT_TAB_MASK 15
static int pedit_net_id;
static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
[TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) },
}; };
...@@ -33,6 +35,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -33,6 +35,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id);
struct nlattr *tb[TCA_PEDIT_MAX + 1]; struct nlattr *tb[TCA_PEDIT_MAX + 1];
struct tc_pedit *parm; struct tc_pedit *parm;
int ret = 0, err; int ret = 0, err;
...@@ -54,11 +57,11 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -54,11 +57,11 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize) if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize)
return -EINVAL; return -EINVAL;
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
if (!parm->nkeys) if (!parm->nkeys)
return -EINVAL; return -EINVAL;
ret = tcf_hash_create(parm->index, est, a, sizeof(*p), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*p), bind, false);
if (ret) if (ret)
return ret; return ret;
p = to_pedit(a); p = to_pedit(a);
...@@ -93,7 +96,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -93,7 +96,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
memcpy(p->tcfp_keys, parm->keys, ksize); memcpy(p->tcfp_keys, parm->keys, ksize);
spin_unlock_bh(&p->tcf_lock); spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -211,6 +214,22 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -211,6 +214,22 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_pedit_ops = { static struct tc_action_ops act_pedit_ops = {
.kind = "pedit", .kind = "pedit",
.type = TCA_ACT_PEDIT, .type = TCA_ACT_PEDIT,
...@@ -219,6 +238,29 @@ static struct tc_action_ops act_pedit_ops = { ...@@ -219,6 +238,29 @@ static struct tc_action_ops act_pedit_ops = {
.dump = tcf_pedit_dump, .dump = tcf_pedit_dump,
.cleanup = tcf_pedit_cleanup, .cleanup = tcf_pedit_cleanup,
.init = tcf_pedit_init, .init = tcf_pedit_init,
.walk = tcf_pedit_walker,
.lookup = tcf_pedit_search,
};
static __net_init int pedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
return tc_action_net_init(tn, &act_pedit_ops, PEDIT_TAB_MASK);
}
static void __net_exit pedit_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations pedit_net_ops = {
.init = pedit_init_net,
.exit = pedit_exit_net,
.id = &pedit_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
...@@ -227,12 +269,12 @@ MODULE_LICENSE("GPL"); ...@@ -227,12 +269,12 @@ MODULE_LICENSE("GPL");
static int __init pedit_init_module(void) static int __init pedit_init_module(void)
{ {
return tcf_register_action(&act_pedit_ops, PEDIT_TAB_MASK); return tcf_register_action(&act_pedit_ops, &pedit_net_ops);
} }
static void __exit pedit_cleanup_module(void) static void __exit pedit_cleanup_module(void)
{ {
tcf_unregister_action(&act_pedit_ops); tcf_unregister_action(&act_pedit_ops, &pedit_net_ops);
} }
module_init(pedit_init_module); module_init(pedit_init_module);
......
...@@ -55,10 +55,14 @@ struct tc_police_compat { ...@@ -55,10 +55,14 @@ struct tc_police_compat {
/* Each policer is serialized by its individual spinlock */ /* Each policer is serialized by its individual spinlock */
static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, static int police_net_id;
int type, struct tc_action *a)
static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{ {
struct tcf_hashinfo *hinfo = a->ops->hinfo; struct tc_action_net *tn = net_generic(net, police_net_id);
struct tcf_hashinfo *hinfo = tn->hinfo;
struct hlist_head *head; struct hlist_head *head;
struct tcf_common *p; struct tcf_common *p;
int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
...@@ -121,7 +125,8 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla, ...@@ -121,7 +125,8 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
struct tc_police *parm; struct tc_police *parm;
struct tcf_police *police; struct tcf_police *police;
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
struct tcf_hashinfo *hinfo = a->ops->hinfo; struct tc_action_net *tn = net_generic(net, police_net_id);
struct tcf_hashinfo *hinfo = tn->hinfo;
int size; int size;
if (nla == NULL) if (nla == NULL)
...@@ -139,7 +144,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla, ...@@ -139,7 +144,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_POLICE_TBF]); parm = nla_data(tb[TCA_POLICE_TBF]);
if (parm->index) { if (parm->index) {
if (tcf_hash_search(a, parm->index)) { if (tcf_hash_search(tn, a, parm->index)) {
police = to_police(a->priv); police = to_police(a->priv);
if (bind) { if (bind) {
police->tcf_bindcnt += 1; police->tcf_bindcnt += 1;
...@@ -233,7 +238,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla, ...@@ -233,7 +238,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
police->tcfp_t_c = ktime_get_ns(); police->tcfp_t_c = ktime_get_ns();
police->tcf_index = parm->index ? parm->index : police->tcf_index = parm->index ? parm->index :
tcf_hash_new_index(hinfo); tcf_hash_new_index(tn);
h = tcf_hash(police->tcf_index, POL_TAB_MASK); h = tcf_hash(police->tcf_index, POL_TAB_MASK);
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
hlist_add_head(&police->tcf_head, &hinfo->htab[h]); hlist_add_head(&police->tcf_head, &hinfo->htab[h]);
...@@ -342,6 +347,13 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -342,6 +347,13 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
return -1; return -1;
} }
static int tcf_police_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
return tcf_hash_search(tn, a, index);
}
MODULE_AUTHOR("Alexey Kuznetsov"); MODULE_AUTHOR("Alexey Kuznetsov");
MODULE_DESCRIPTION("Policing actions"); MODULE_DESCRIPTION("Policing actions");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -353,19 +365,41 @@ static struct tc_action_ops act_police_ops = { ...@@ -353,19 +365,41 @@ static struct tc_action_ops act_police_ops = {
.act = tcf_act_police, .act = tcf_act_police,
.dump = tcf_act_police_dump, .dump = tcf_act_police_dump,
.init = tcf_act_police_locate, .init = tcf_act_police_locate,
.walk = tcf_act_police_walker .walk = tcf_act_police_walker,
.lookup = tcf_police_search,
};
static __net_init int police_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
return tc_action_net_init(tn, &act_police_ops, POL_TAB_MASK);
}
static void __net_exit police_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations police_net_ops = {
.init = police_init_net,
.exit = police_exit_net,
.id = &police_net_id,
.size = sizeof(struct tc_action_net),
}; };
static int __init static int __init
police_init_module(void) police_init_module(void)
{ {
return tcf_register_action(&act_police_ops, POL_TAB_MASK); return tcf_register_action(&act_police_ops, &police_net_ops);
} }
static void __exit static void __exit
police_cleanup_module(void) police_cleanup_module(void)
{ {
tcf_unregister_action(&act_police_ops); tcf_unregister_action(&act_police_ops, &police_net_ops);
} }
module_init(police_init_module); module_init(police_init_module);
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#define SIMP_TAB_MASK 7 #define SIMP_TAB_MASK 7
static int simp_net_id;
#define SIMP_MAX_DATA 32 #define SIMP_MAX_DATA 32
static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
...@@ -80,6 +82,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -80,6 +82,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id);
struct nlattr *tb[TCA_DEF_MAX + 1]; struct nlattr *tb[TCA_DEF_MAX + 1];
struct tc_defact *parm; struct tc_defact *parm;
struct tcf_defact *d; struct tcf_defact *d;
...@@ -102,9 +105,9 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -102,9 +105,9 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_DEF_PARMS]); parm = nla_data(tb[TCA_DEF_PARMS]);
defdata = nla_data(tb[TCA_DEF_DATA]); defdata = nla_data(tb[TCA_DEF_DATA]);
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*d), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*d), bind, false);
if (ret) if (ret)
return ret; return ret;
...@@ -129,7 +132,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -129,7 +132,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
} }
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -161,6 +164,22 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -161,6 +164,22 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_simp_ops = { static struct tc_action_ops act_simp_ops = {
.kind = "simple", .kind = "simple",
.type = TCA_ACT_SIMP, .type = TCA_ACT_SIMP,
...@@ -169,6 +188,29 @@ static struct tc_action_ops act_simp_ops = { ...@@ -169,6 +188,29 @@ static struct tc_action_ops act_simp_ops = {
.dump = tcf_simp_dump, .dump = tcf_simp_dump,
.cleanup = tcf_simp_release, .cleanup = tcf_simp_release,
.init = tcf_simp_init, .init = tcf_simp_init,
.walk = tcf_simp_walker,
.lookup = tcf_simp_search,
};
static __net_init int simp_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
return tc_action_net_init(tn, &act_simp_ops, SIMP_TAB_MASK);
}
static void __net_exit simp_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations simp_net_ops = {
.init = simp_init_net,
.exit = simp_exit_net,
.id = &simp_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Jamal Hadi Salim(2005)"); MODULE_AUTHOR("Jamal Hadi Salim(2005)");
...@@ -177,8 +219,7 @@ MODULE_LICENSE("GPL"); ...@@ -177,8 +219,7 @@ MODULE_LICENSE("GPL");
static int __init simp_init_module(void) static int __init simp_init_module(void)
{ {
int ret; int ret = tcf_register_action(&act_simp_ops, &simp_net_ops);
ret = tcf_register_action(&act_simp_ops, SIMP_TAB_MASK);
if (!ret) if (!ret)
pr_info("Simple TC action Loaded\n"); pr_info("Simple TC action Loaded\n");
return ret; return ret;
...@@ -186,7 +227,7 @@ static int __init simp_init_module(void) ...@@ -186,7 +227,7 @@ static int __init simp_init_module(void)
static void __exit simp_cleanup_module(void) static void __exit simp_cleanup_module(void)
{ {
tcf_unregister_action(&act_simp_ops); tcf_unregister_action(&act_simp_ops, &simp_net_ops);
} }
module_init(simp_init_module); module_init(simp_init_module);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#define SKBEDIT_TAB_MASK 15 #define SKBEDIT_TAB_MASK 15
static int skbedit_net_id;
static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
...@@ -61,6 +63,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -61,6 +63,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
struct tc_skbedit *parm; struct tc_skbedit *parm;
struct tcf_skbedit *d; struct tcf_skbedit *d;
...@@ -98,9 +101,9 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -98,9 +101,9 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_SKBEDIT_PARMS]); parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*d), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*d), bind, false);
if (ret) if (ret)
return ret; return ret;
...@@ -130,7 +133,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -130,7 +133,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&d->tcf_lock); spin_unlock_bh(&d->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -173,6 +176,22 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -173,6 +176,22 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_skbedit_ops = { static struct tc_action_ops act_skbedit_ops = {
.kind = "skbedit", .kind = "skbedit",
.type = TCA_ACT_SKBEDIT, .type = TCA_ACT_SKBEDIT,
...@@ -180,6 +199,29 @@ static struct tc_action_ops act_skbedit_ops = { ...@@ -180,6 +199,29 @@ static struct tc_action_ops act_skbedit_ops = {
.act = tcf_skbedit, .act = tcf_skbedit,
.dump = tcf_skbedit_dump, .dump = tcf_skbedit_dump,
.init = tcf_skbedit_init, .init = tcf_skbedit_init,
.walk = tcf_skbedit_walker,
.lookup = tcf_skbedit_search,
};
static __net_init int skbedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
return tc_action_net_init(tn, &act_skbedit_ops, SKBEDIT_TAB_MASK);
}
static void __net_exit skbedit_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations skbedit_net_ops = {
.init = skbedit_init_net,
.exit = skbedit_exit_net,
.id = &skbedit_net_id,
.size = sizeof(struct tc_action_net),
}; };
MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>"); MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
...@@ -188,12 +230,12 @@ MODULE_LICENSE("GPL"); ...@@ -188,12 +230,12 @@ MODULE_LICENSE("GPL");
static int __init skbedit_init_module(void) static int __init skbedit_init_module(void)
{ {
return tcf_register_action(&act_skbedit_ops, SKBEDIT_TAB_MASK); return tcf_register_action(&act_skbedit_ops, &skbedit_net_ops);
} }
static void __exit skbedit_cleanup_module(void) static void __exit skbedit_cleanup_module(void)
{ {
tcf_unregister_action(&act_skbedit_ops); tcf_unregister_action(&act_skbedit_ops, &skbedit_net_ops);
} }
module_init(skbedit_init_module); module_init(skbedit_init_module);
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#define VLAN_TAB_MASK 15 #define VLAN_TAB_MASK 15
static int vlan_net_id;
static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
...@@ -68,6 +70,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -68,6 +70,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, struct nlattr *est, struct tc_action *a,
int ovr, int bind) int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id);
struct nlattr *tb[TCA_VLAN_MAX + 1]; struct nlattr *tb[TCA_VLAN_MAX + 1];
struct tc_vlan *parm; struct tc_vlan *parm;
struct tcf_vlan *v; struct tcf_vlan *v;
...@@ -115,9 +118,9 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -115,9 +118,9 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
} }
action = parm->v_action; action = parm->v_action;
if (!tcf_hash_check(parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(parm->index, est, a, sizeof(*v), ret = tcf_hash_create(tn, parm->index, est, a,
bind, false); sizeof(*v), bind, false);
if (ret) if (ret)
return ret; return ret;
...@@ -143,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -143,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&v->tcf_lock); spin_unlock_bh(&v->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(a); tcf_hash_insert(tn, a);
return ret; return ret;
} }
...@@ -181,6 +184,22 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -181,6 +184,22 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type,
struct tc_action *a)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
return tcf_generic_walker(tn, skb, cb, type, a);
}
static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
return tcf_hash_search(tn, a, index);
}
static struct tc_action_ops act_vlan_ops = { static struct tc_action_ops act_vlan_ops = {
.kind = "vlan", .kind = "vlan",
.type = TCA_ACT_VLAN, .type = TCA_ACT_VLAN,
...@@ -188,16 +207,39 @@ static struct tc_action_ops act_vlan_ops = { ...@@ -188,16 +207,39 @@ static struct tc_action_ops act_vlan_ops = {
.act = tcf_vlan, .act = tcf_vlan,
.dump = tcf_vlan_dump, .dump = tcf_vlan_dump,
.init = tcf_vlan_init, .init = tcf_vlan_init,
.walk = tcf_vlan_walker,
.lookup = tcf_vlan_search,
};
static __net_init int vlan_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
return tc_action_net_init(tn, &act_vlan_ops, VLAN_TAB_MASK);
}
static void __net_exit vlan_exit_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
tc_action_net_exit(tn);
}
static struct pernet_operations vlan_net_ops = {
.init = vlan_init_net,
.exit = vlan_exit_net,
.id = &vlan_net_id,
.size = sizeof(struct tc_action_net),
}; };
static int __init vlan_init_module(void) static int __init vlan_init_module(void)
{ {
return tcf_register_action(&act_vlan_ops, VLAN_TAB_MASK); return tcf_register_action(&act_vlan_ops, &vlan_net_ops);
} }
static void __exit vlan_cleanup_module(void) static void __exit vlan_cleanup_module(void)
{ {
tcf_unregister_action(&act_vlan_ops); tcf_unregister_action(&act_vlan_ops, &vlan_net_ops);
} }
module_init(vlan_init_module); module_init(vlan_init_module);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment