Commit c43212bb authored by David S. Miller's avatar David S. Miller

Merge branch 'refactor-tc_action-structs'

Cong Wang says:

====================
net_sched: refactor tc action structures

These two patches factor out the struct tcf_common.

v2: fix a compile warning
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b93dd49c ec0595cc
...@@ -10,34 +10,6 @@ ...@@ -10,34 +10,6 @@
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/netns/generic.h> #include <net/netns/generic.h>
struct tcf_common {
struct hlist_node tcfc_head;
u32 tcfc_index;
int tcfc_refcnt;
int tcfc_bindcnt;
u32 tcfc_capab;
int tcfc_action;
struct tcf_t tcfc_tm;
struct gnet_stats_basic_packed tcfc_bstats;
struct gnet_stats_queue tcfc_qstats;
struct gnet_stats_rate_est64 tcfc_rate_est;
spinlock_t tcfc_lock;
struct rcu_head tcfc_rcu;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
};
#define tcf_head common.tcfc_head
#define tcf_index common.tcfc_index
#define tcf_refcnt common.tcfc_refcnt
#define tcf_bindcnt common.tcfc_bindcnt
#define tcf_capab common.tcfc_capab
#define tcf_action common.tcfc_action
#define tcf_tm common.tcfc_tm
#define tcf_bstats common.tcfc_bstats
#define tcf_qstats common.tcfc_qstats
#define tcf_rate_est common.tcfc_rate_est
#define tcf_lock common.tcfc_lock
#define tcf_rcu common.tcfc_rcu
struct tcf_hashinfo { struct tcf_hashinfo {
struct hlist_head *htab; struct hlist_head *htab;
...@@ -46,6 +18,44 @@ struct tcf_hashinfo { ...@@ -46,6 +18,44 @@ struct tcf_hashinfo {
u32 index; u32 index;
}; };
struct tc_action_ops;
struct tc_action {
const struct tc_action_ops *ops;
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order;
struct list_head list;
struct tcf_hashinfo *hinfo;
struct hlist_node tcfa_head;
u32 tcfa_index;
int tcfa_refcnt;
int tcfa_bindcnt;
u32 tcfa_capab;
int tcfa_action;
struct tcf_t tcfa_tm;
struct gnet_stats_basic_packed tcfa_bstats;
struct gnet_stats_queue tcfa_qstats;
struct gnet_stats_rate_est64 tcfa_rate_est;
spinlock_t tcfa_lock;
struct rcu_head tcfa_rcu;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
};
#define tcf_act common.tcfa_act
#define tcf_head common.tcfa_head
#define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt
#define tcf_bindcnt common.tcfa_bindcnt
#define tcf_capab common.tcfa_capab
#define tcf_action common.tcfa_action
#define tcf_tm common.tcfa_tm
#define tcf_bstats common.tcfa_bstats
#define tcf_qstats common.tcfa_qstats
#define tcf_rate_est common.tcfa_rate_est
#define tcf_lock common.tcfa_lock
#define tcf_rcu common.tcfa_rcu
static inline unsigned int tcf_hash(u32 index, unsigned int hmask) static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
{ {
return index & hmask; return index & hmask;
...@@ -88,15 +98,6 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm) ...@@ -88,15 +98,6 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm)
dtm->expires = jiffies_to_clock_t(stm->expires); dtm->expires = jiffies_to_clock_t(stm->expires);
} }
struct tc_action {
void *priv;
const struct tc_action_ops *ops;
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order;
struct list_head list;
struct tcf_hashinfo *hinfo;
};
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
#define ACT_P_CREATED 1 #define ACT_P_CREATED 1
...@@ -106,17 +107,18 @@ struct tc_action_ops { ...@@ -106,17 +107,18 @@ struct tc_action_ops {
struct list_head head; struct list_head head;
char kind[IFNAMSIZ]; char kind[IFNAMSIZ];
__u32 type; /* TBD to match kind */ __u32 type; /* TBD to match kind */
size_t size;
struct module *owner; struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *, int (*act)(struct sk_buff *, const struct tc_action *,
struct tcf_result *); 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 net *, 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 net *, struct sk_buff *, int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, struct tc_action *); struct netlink_callback *, int, const struct tc_action_ops *);
void (*stats_update)(struct tc_action *, u64, u32, u64); void (*stats_update)(struct tc_action *, u64, u32, u64);
}; };
...@@ -152,13 +154,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn) ...@@ -152,13 +154,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn)
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a); const struct tc_action_ops *ops);
int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index); 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); u32 tcf_hash_new_index(struct tc_action_net *tn);
bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind); int bind);
int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action *a, int size, int bind, bool cpustats); struct tc_action **a, const struct tc_action_ops *ops, 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_net *tn, struct tc_action *a); void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_bpf { struct tcf_bpf {
struct tcf_common common; struct tc_action common;
struct bpf_prog __rcu *filter; struct bpf_prog __rcu *filter;
union { union {
u32 bpf_fd; u32 bpf_fd;
...@@ -23,7 +23,6 @@ struct tcf_bpf { ...@@ -23,7 +23,6 @@ struct tcf_bpf {
struct sock_filter *bpf_ops; struct sock_filter *bpf_ops;
const char *bpf_name; const char *bpf_name;
}; };
#define to_bpf(a) \ #define to_bpf(a) ((struct tcf_bpf *)a)
container_of(a->priv, struct tcf_bpf, common)
#endif /* __NET_TC_BPF_H */ #endif /* __NET_TC_BPF_H */
...@@ -4,12 +4,11 @@ ...@@ -4,12 +4,11 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_connmark_info { struct tcf_connmark_info {
struct tcf_common common; struct tc_action common;
struct net *net; struct net *net;
u16 zone; u16 zone;
}; };
#define to_connmark(a) \ #define to_connmark(a) ((struct tcf_connmark_info *)a)
container_of(a->priv, struct tcf_connmark_info, common)
#endif /* __NET_TC_CONNMARK_H */ #endif /* __NET_TC_CONNMARK_H */
...@@ -5,11 +5,10 @@ ...@@ -5,11 +5,10 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_csum { struct tcf_csum {
struct tcf_common common; struct tc_action common;
u32 update_flags; u32 update_flags;
}; };
#define to_tcf_csum(a) \ #define to_tcf_csum(a) ((struct tcf_csum *)a)
container_of(a->priv,struct tcf_csum,common)
#endif /* __NET_TC_CSUM_H */ #endif /* __NET_TC_CSUM_H */
...@@ -4,11 +4,10 @@ ...@@ -4,11 +4,10 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_defact { struct tcf_defact {
struct tcf_common common; struct tc_action common;
u32 tcfd_datalen; u32 tcfd_datalen;
void *tcfd_defdata; void *tcfd_defdata;
}; };
#define to_defact(a) \ #define to_defact(a) ((struct tcf_defact *)a)
container_of(a->priv, struct tcf_defact, common)
#endif /* __NET_TC_DEF_H */ #endif /* __NET_TC_DEF_H */
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <linux/tc_act/tc_gact.h> #include <linux/tc_act/tc_gact.h>
struct tcf_gact { struct tcf_gact {
struct tcf_common common; struct tc_action common;
#ifdef CONFIG_GACT_PROB #ifdef CONFIG_GACT_PROB
u16 tcfg_ptype; u16 tcfg_ptype;
u16 tcfg_pval; u16 tcfg_pval;
...@@ -13,8 +13,7 @@ struct tcf_gact { ...@@ -13,8 +13,7 @@ struct tcf_gact {
atomic_t packets; atomic_t packets;
#endif #endif
}; };
#define to_gact(a) \ #define to_gact(a) ((struct tcf_gact *)a)
container_of(a->priv, struct tcf_gact, common)
static inline bool is_tcf_gact_shot(const struct tc_action *a) static inline bool is_tcf_gact_shot(const struct tc_action *a)
{ {
...@@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a) ...@@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a)
if (a->ops && a->ops->type != TCA_ACT_GACT) if (a->ops && a->ops->type != TCA_ACT_GACT)
return false; return false;
gact = a->priv; gact = to_gact(a);
if (gact->tcf_action == TC_ACT_SHOT) if (gact->tcf_action == TC_ACT_SHOT)
return true; return true;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#define IFE_METAHDRLEN 2 #define IFE_METAHDRLEN 2
struct tcf_ife_info { struct tcf_ife_info {
struct tcf_common common; struct tc_action common;
u8 eth_dst[ETH_ALEN]; u8 eth_dst[ETH_ALEN];
u8 eth_src[ETH_ALEN]; u8 eth_src[ETH_ALEN];
u16 eth_type; u16 eth_type;
...@@ -16,8 +16,7 @@ struct tcf_ife_info { ...@@ -16,8 +16,7 @@ struct tcf_ife_info {
/* list of metaids allowed */ /* list of metaids allowed */
struct list_head metalist; struct list_head metalist;
}; };
#define to_ife(a) \ #define to_ife(a) ((struct tcf_ife_info *)a)
container_of(a->priv, struct tcf_ife_info, common)
struct tcf_meta_info { struct tcf_meta_info {
const struct tcf_meta_ops *ops; const struct tcf_meta_ops *ops;
......
...@@ -6,12 +6,11 @@ ...@@ -6,12 +6,11 @@
struct xt_entry_target; struct xt_entry_target;
struct tcf_ipt { struct tcf_ipt {
struct tcf_common common; struct tc_action common;
u32 tcfi_hook; u32 tcfi_hook;
char *tcfi_tname; char *tcfi_tname;
struct xt_entry_target *tcfi_t; struct xt_entry_target *tcfi_t;
}; };
#define to_ipt(a) \ #define to_ipt(a) ((struct tcf_ipt *)a)
container_of(a->priv, struct tcf_ipt, common)
#endif /* __NET_TC_IPT_H */ #endif /* __NET_TC_IPT_H */
...@@ -5,15 +5,14 @@ ...@@ -5,15 +5,14 @@
#include <linux/tc_act/tc_mirred.h> #include <linux/tc_act/tc_mirred.h>
struct tcf_mirred { struct tcf_mirred {
struct tcf_common common; struct tc_action common;
int tcfm_eaction; int tcfm_eaction;
int tcfm_ifindex; int tcfm_ifindex;
int tcfm_ok_push; int tcfm_ok_push;
struct net_device __rcu *tcfm_dev; struct net_device __rcu *tcfm_dev;
struct list_head tcfm_list; struct list_head tcfm_list;
}; };
#define to_mirred(a) \ #define to_mirred(a) ((struct tcf_mirred *)a)
container_of(a->priv, struct tcf_mirred, common)
static inline bool is_tcf_mirred_redirect(const struct tc_action *a) static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
{ {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_nat { struct tcf_nat {
struct tcf_common common; struct tc_action common;
__be32 old_addr; __be32 old_addr;
__be32 new_addr; __be32 new_addr;
...@@ -13,9 +13,6 @@ struct tcf_nat { ...@@ -13,9 +13,6 @@ struct tcf_nat {
u32 flags; u32 flags;
}; };
static inline struct tcf_nat *to_tcf_nat(struct tc_action *a) #define to_tcf_nat(a) ((struct tcf_nat *)a)
{
return container_of(a->priv, struct tcf_nat, common);
}
#endif /* __NET_TC_NAT_H */ #endif /* __NET_TC_NAT_H */
...@@ -4,12 +4,11 @@ ...@@ -4,12 +4,11 @@
#include <net/act_api.h> #include <net/act_api.h>
struct tcf_pedit { struct tcf_pedit {
struct tcf_common common; struct tc_action common;
unsigned char tcfp_nkeys; unsigned char tcfp_nkeys;
unsigned char tcfp_flags; unsigned char tcfp_flags;
struct tc_pedit_key *tcfp_keys; struct tc_pedit_key *tcfp_keys;
}; };
#define to_pedit(a) \ #define to_pedit(a) ((struct tcf_pedit *)a)
container_of(a->priv, struct tcf_pedit, common)
#endif /* __NET_TC_PED_H */ #endif /* __NET_TC_PED_H */
...@@ -23,15 +23,14 @@ ...@@ -23,15 +23,14 @@
#include <linux/tc_act/tc_skbedit.h> #include <linux/tc_act/tc_skbedit.h>
struct tcf_skbedit { struct tcf_skbedit {
struct tcf_common common; struct tc_action common;
u32 flags; u32 flags;
u32 priority; u32 priority;
u32 mark; u32 mark;
u16 queue_mapping; u16 queue_mapping;
u16 ptype; u16 ptype;
}; };
#define to_skbedit(a) \ #define to_skbedit(a) ((struct tcf_skbedit *)a)
container_of(a->priv, struct tcf_skbedit, common)
/* Return true iff action is mark */ /* Return true iff action is mark */
static inline bool is_tcf_skbedit_mark(const struct tc_action *a) static inline bool is_tcf_skbedit_mark(const struct tc_action *a)
......
...@@ -16,12 +16,11 @@ ...@@ -16,12 +16,11 @@
#define VLAN_F_PUSH 0x2 #define VLAN_F_PUSH 0x2
struct tcf_vlan { struct tcf_vlan {
struct tcf_common common; struct tc_action common;
int tcfv_action; int tcfv_action;
u16 tcfv_push_vid; u16 tcfv_push_vid;
__be16 tcfv_push_proto; __be16 tcfv_push_proto;
}; };
#define to_vlan(a) \ #define to_vlan(a) ((struct tcf_vlan *)a)
container_of(a->priv, struct tcf_vlan, common)
#endif /* __NET_TC_VLAN_H */ #endif /* __NET_TC_VLAN_H */
...@@ -29,45 +29,43 @@ ...@@ -29,45 +29,43 @@
static void free_tcf(struct rcu_head *head) static void free_tcf(struct rcu_head *head)
{ {
struct tcf_common *p = container_of(head, struct tcf_common, tcfc_rcu); struct tc_action *p = container_of(head, struct tc_action, tcfa_rcu);
free_percpu(p->cpu_bstats); free_percpu(p->cpu_bstats);
free_percpu(p->cpu_qstats); free_percpu(p->cpu_qstats);
kfree(p); kfree(p);
} }
static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *p)
{ {
struct tcf_common *p = a->priv;
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
hlist_del(&p->tcfc_head); hlist_del(&p->tcfa_head);
spin_unlock_bh(&hinfo->lock); spin_unlock_bh(&hinfo->lock);
gen_kill_estimator(&p->tcfc_bstats, gen_kill_estimator(&p->tcfa_bstats,
&p->tcfc_rate_est); &p->tcfa_rate_est);
/* /*
* gen_estimator est_timer() might access p->tcfc_lock * gen_estimator est_timer() might access p->tcfa_lock
* or bstats, wait a RCU grace period before freeing p * or bstats, wait a RCU grace period before freeing p
*/ */
call_rcu(&p->tcfc_rcu, free_tcf); call_rcu(&p->tcfa_rcu, free_tcf);
} }
int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
{ {
struct tcf_common *p = a->priv;
int ret = 0; int ret = 0;
if (p) { if (p) {
if (bind) if (bind)
p->tcfc_bindcnt--; p->tcfa_bindcnt--;
else if (strict && p->tcfc_bindcnt > 0) else if (strict && p->tcfa_bindcnt > 0)
return -EPERM; return -EPERM;
p->tcfc_refcnt--; p->tcfa_refcnt--;
if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
if (a->ops->cleanup) if (p->ops->cleanup)
a->ops->cleanup(a, bind); p->ops->cleanup(p, bind);
tcf_hash_destroy(a->hinfo, a); list_del(&p->list);
tcf_hash_destroy(p->hinfo, p);
ret = ACT_P_DELETED; ret = ACT_P_DELETED;
} }
} }
...@@ -77,10 +75,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) ...@@ -77,10 +75,8 @@ 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 tcf_hashinfo *hinfo, struct sk_buff *skb, static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
struct netlink_callback *cb, struct tc_action *a) struct netlink_callback *cb)
{ {
struct hlist_head *head;
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;
struct nlattr *nest; struct nlattr *nest;
...@@ -89,19 +85,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, ...@@ -89,19 +85,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
s_i = cb->args[0]; s_i = cb->args[0];
for (i = 0; i < (hinfo->hmask + 1); i++) { for (i = 0; i < (hinfo->hmask + 1); i++) {
struct hlist_head *head;
struct tc_action *p;
head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
hlist_for_each_entry_rcu(p, head, tcfc_head) { hlist_for_each_entry_rcu(p, head, tcfa_head) {
index++; index++;
if (index < s_i) if (index < s_i)
continue; continue;
a->priv = p;
a->order = n_i;
nest = nla_nest_start(skb, a->order); nest = nla_nest_start(skb, n_i);
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
err = tcf_action_dump_1(skb, a, 0, 0); err = tcf_action_dump_1(skb, p, 0, 0);
if (err < 0) { if (err < 0) {
index--; index--;
nlmsg_trim(skb, nest); nlmsg_trim(skb, nest);
...@@ -125,27 +122,27 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, ...@@ -125,27 +122,27 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
} }
static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct hlist_head *head;
struct hlist_node *n;
struct tcf_common *p;
struct nlattr *nest; struct nlattr *nest;
int i = 0, n_i = 0; int i = 0, n_i = 0;
int ret = -EINVAL; int ret = -EINVAL;
nest = nla_nest_start(skb, a->order); nest = nla_nest_start(skb, 0);
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
if (nla_put_string(skb, TCA_KIND, a->ops->kind)) if (nla_put_string(skb, TCA_KIND, ops->kind))
goto nla_put_failure; goto nla_put_failure;
for (i = 0; i < (hinfo->hmask + 1); i++) { for (i = 0; i < (hinfo->hmask + 1); i++) {
struct hlist_head *head;
struct hlist_node *n;
struct tc_action *p;
head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
hlist_for_each_entry_safe(p, n, head, tcfc_head) { hlist_for_each_entry_safe(p, n, head, tcfa_head) {
a->priv = p; ret = __tcf_hash_release(p, false, true);
ret = __tcf_hash_release(a, false, true);
if (ret == ACT_P_DELETED) { if (ret == ACT_P_DELETED) {
module_put(a->ops->owner); module_put(p->ops->owner);
n_i++; n_i++;
} else if (ret < 0) } else if (ret < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -163,16 +160,14 @@ static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, ...@@ -163,16 +160,14 @@ static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tcf_hashinfo *hinfo = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
a->hinfo = hinfo;
if (type == RTM_DELACTION) { if (type == RTM_DELACTION) {
return tcf_del_walker(hinfo, skb, a); return tcf_del_walker(hinfo, skb, ops);
} else if (type == RTM_GETACTION) { } else if (type == RTM_GETACTION) {
return tcf_dump_walker(hinfo, skb, cb, a); return tcf_dump_walker(hinfo, skb, cb);
} 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;
...@@ -180,15 +175,15 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, ...@@ -180,15 +175,15 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
} }
EXPORT_SYMBOL(tcf_generic_walker); EXPORT_SYMBOL(tcf_generic_walker);
static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) static struct tc_action *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
{ {
struct tcf_common *p = NULL; struct tc_action *p = NULL;
struct hlist_head *head; struct hlist_head *head;
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
head = &hinfo->htab[tcf_hash(index, hinfo->hmask)]; head = &hinfo->htab[tcf_hash(index, hinfo->hmask)];
hlist_for_each_entry_rcu(p, head, tcfc_head) hlist_for_each_entry_rcu(p, head, tcfa_head)
if (p->tcfc_index == index) if (p->tcfa_index == index)
break; break;
spin_unlock_bh(&hinfo->lock); spin_unlock_bh(&hinfo->lock);
...@@ -210,31 +205,30 @@ u32 tcf_hash_new_index(struct tc_action_net *tn) ...@@ -210,31 +205,30 @@ u32 tcf_hash_new_index(struct tc_action_net *tn)
} }
EXPORT_SYMBOL(tcf_hash_new_index); EXPORT_SYMBOL(tcf_hash_new_index);
int tcf_hash_search(struct tc_action_net *tn, 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 = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
struct tcf_common *p = tcf_hash_lookup(index, hinfo); struct tc_action *p = tcf_hash_lookup(index, hinfo);
if (p) { if (p) {
a->priv = p; *a = p;
a->hinfo = hinfo;
return 1; return 1;
} }
return 0; return 0;
} }
EXPORT_SYMBOL(tcf_hash_search); EXPORT_SYMBOL(tcf_hash_search);
bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind) int bind)
{ {
struct tcf_hashinfo *hinfo = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
struct tcf_common *p = NULL; struct tc_action *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->tcfa_bindcnt++;
p->tcfc_refcnt++; p->tcfa_refcnt++;
a->priv = p; *a = p;
a->hinfo = hinfo;
return true; return true;
} }
return false; return false;
...@@ -243,26 +237,26 @@ EXPORT_SYMBOL(tcf_hash_check); ...@@ -243,26 +237,26 @@ EXPORT_SYMBOL(tcf_hash_check);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
{ {
struct tcf_common *pc = a->priv;
if (est) if (est)
gen_kill_estimator(&pc->tcfc_bstats, gen_kill_estimator(&a->tcfa_bstats,
&pc->tcfc_rate_est); &a->tcfa_rate_est);
call_rcu(&pc->tcfc_rcu, free_tcf); call_rcu(&a->tcfa_rcu, free_tcf);
} }
EXPORT_SYMBOL(tcf_hash_cleanup); EXPORT_SYMBOL(tcf_hash_cleanup);
int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action *a, int size, int bind, bool cpustats) struct tc_action **a, const struct tc_action_ops *ops,
int bind, bool cpustats)
{ {
struct tcf_common *p = kzalloc(size, GFP_KERNEL); struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
struct tcf_hashinfo *hinfo = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
int err = -ENOMEM; int err = -ENOMEM;
if (unlikely(!p)) if (unlikely(!p))
return -ENOMEM; return -ENOMEM;
p->tcfc_refcnt = 1; p->tcfa_refcnt = 1;
if (bind) if (bind)
p->tcfc_bindcnt = 1; p->tcfa_bindcnt = 1;
if (cpustats) { if (cpustats) {
p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
...@@ -278,36 +272,37 @@ int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, ...@@ -278,36 +272,37 @@ int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
goto err1; goto err1;
} }
} }
spin_lock_init(&p->tcfc_lock); spin_lock_init(&p->tcfa_lock);
INIT_HLIST_NODE(&p->tcfc_head); INIT_HLIST_NODE(&p->tcfa_head);
p->tcfc_index = index ? index : tcf_hash_new_index(tn); p->tcfa_index = index ? index : tcf_hash_new_index(tn);
p->tcfc_tm.install = jiffies; p->tcfa_tm.install = jiffies;
p->tcfc_tm.lastuse = jiffies; p->tcfa_tm.lastuse = jiffies;
p->tcfc_tm.firstuse = 0; p->tcfa_tm.firstuse = 0;
if (est) { if (est) {
err = gen_new_estimator(&p->tcfc_bstats, p->cpu_bstats, err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
&p->tcfc_rate_est, &p->tcfa_rate_est,
&p->tcfc_lock, NULL, est); &p->tcfa_lock, NULL, est);
if (err) { if (err) {
free_percpu(p->cpu_qstats); free_percpu(p->cpu_qstats);
goto err2; goto err2;
} }
} }
a->priv = (void *) p; p->hinfo = hinfo;
a->hinfo = hinfo; p->ops = ops;
INIT_LIST_HEAD(&p->list);
*a = p;
return 0; return 0;
} }
EXPORT_SYMBOL(tcf_hash_create); EXPORT_SYMBOL(tcf_hash_create);
void tcf_hash_insert(struct tc_action_net *tn, 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_hashinfo *hinfo = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); unsigned int h = tcf_hash(a->tcfa_index, hinfo->hmask);
spin_lock_bh(&hinfo->lock); spin_lock_bh(&hinfo->lock);
hlist_add_head(&p->tcfc_head, &hinfo->htab[h]); hlist_add_head(&a->tcfa_head, &hinfo->htab[h]);
spin_unlock_bh(&hinfo->lock); spin_unlock_bh(&hinfo->lock);
} }
EXPORT_SYMBOL(tcf_hash_insert); EXPORT_SYMBOL(tcf_hash_insert);
...@@ -315,21 +310,16 @@ EXPORT_SYMBOL(tcf_hash_insert); ...@@ -315,21 +310,16 @@ EXPORT_SYMBOL(tcf_hash_insert);
void tcf_hashinfo_destroy(const struct tc_action_ops *ops, void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
struct tcf_hashinfo *hinfo) struct tcf_hashinfo *hinfo)
{ {
struct tc_action a = {
.ops = ops,
.hinfo = hinfo,
};
int i; int i;
for (i = 0; i < hinfo->hmask + 1; i++) { for (i = 0; i < hinfo->hmask + 1; i++) {
struct tcf_common *p; struct tc_action *p;
struct hlist_node *n; struct hlist_node *n;
hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfa_head) {
int ret; int ret;
a.priv = p; ret = __tcf_hash_release(p, false, true);
ret = __tcf_hash_release(&a, false, true);
if (ret == ACT_P_DELETED) if (ret == ACT_P_DELETED)
module_put(ops->owner); module_put(ops->owner);
else if (ret < 0) else if (ret < 0)
...@@ -466,8 +456,6 @@ int tcf_action_destroy(struct list_head *actions, int bind) ...@@ -466,8 +456,6 @@ int tcf_action_destroy(struct list_head *actions, int bind)
module_put(a->ops->owner); module_put(a->ops->owner);
else if (ret < 0) else if (ret < 0)
return ret; return ret;
list_del(&a->list);
kfree(a);
} }
return ret; return ret;
} }
...@@ -581,20 +569,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, ...@@ -581,20 +569,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
goto err_out; goto err_out;
} }
err = -ENOMEM;
a = kzalloc(sizeof(*a), GFP_KERNEL);
if (a == NULL)
goto err_mod;
a->ops = a_o;
INIT_LIST_HEAD(&a->list);
/* backward compatibility for policer */ /* backward compatibility for policer */
if (name == NULL) if (name == NULL)
err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind); err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind);
else else
err = a_o->init(net, nla, est, a, ovr, bind); err = a_o->init(net, nla, est, &a, ovr, bind);
if (err < 0) if (err < 0)
goto err_free; goto err_mod;
/* module count goes up only when brand new policy is created /* module count goes up only when brand new policy is created
* if it exists and is only bound to in a_o->init() then * if it exists and is only bound to in a_o->init() then
...@@ -605,8 +586,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, ...@@ -605,8 +586,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
return a; return a;
err_free:
kfree(a);
err_mod: err_mod:
module_put(a_o->owner); module_put(a_o->owner);
err_out: err_out:
...@@ -642,12 +621,11 @@ int tcf_action_init(struct net *net, struct nlattr *nla, ...@@ -642,12 +621,11 @@ int tcf_action_init(struct net *net, struct nlattr *nla,
return err; return err;
} }
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
int compat_mode) int compat_mode)
{ {
int err = 0; int err = 0;
struct gnet_dump d; struct gnet_dump d;
struct tcf_common *p = a->priv;
if (p == NULL) if (p == NULL)
goto errout; goto errout;
...@@ -656,27 +634,27 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, ...@@ -656,27 +634,27 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
* to add additional backward compatibility statistic TLVs. * to add additional backward compatibility statistic TLVs.
*/ */
if (compat_mode) { if (compat_mode) {
if (a->type == TCA_OLD_COMPAT) if (p->type == TCA_OLD_COMPAT)
err = gnet_stats_start_copy_compat(skb, 0, err = gnet_stats_start_copy_compat(skb, 0,
TCA_STATS, TCA_STATS,
TCA_XSTATS, TCA_XSTATS,
&p->tcfc_lock, &d, &p->tcfa_lock, &d,
TCA_PAD); TCA_PAD);
else else
return 0; return 0;
} else } else
err = gnet_stats_start_copy(skb, TCA_ACT_STATS, err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
&p->tcfc_lock, &d, TCA_ACT_PAD); &p->tcfa_lock, &d, TCA_ACT_PAD);
if (err < 0) if (err < 0)
goto errout; goto errout;
if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfc_bstats) < 0 || if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
gnet_stats_copy_rate_est(&d, &p->tcfc_bstats, gnet_stats_copy_rate_est(&d, &p->tcfa_bstats,
&p->tcfc_rate_est) < 0 || &p->tcfa_rate_est) < 0 ||
gnet_stats_copy_queue(&d, p->cpu_qstats, gnet_stats_copy_queue(&d, p->cpu_qstats,
&p->tcfc_qstats, &p->tcfa_qstats,
p->tcfc_qstats.qlen) < 0) p->tcfa_qstats.qlen) < 0)
goto errout; goto errout;
if (gnet_stats_finish_copy(&d) < 0) if (gnet_stats_finish_copy(&d) < 0)
...@@ -740,24 +718,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, ...@@ -740,24 +718,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
return rtnl_unicast(skb, net, portid); return rtnl_unicast(skb, net, portid);
} }
static struct tc_action *create_a(int i)
{
struct tc_action *act;
act = kzalloc(sizeof(*act), GFP_KERNEL);
if (act == NULL) {
pr_debug("create_a: failed to alloc!\n");
return NULL;
}
act->order = i;
INIT_LIST_HEAD(&act->list);
return act;
}
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, static struct tc_action *tcf_action_get_1(struct net *net, 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];
const struct tc_action_ops *ops;
struct tc_action *a; struct tc_action *a;
int index; int index;
int err; int err;
...@@ -772,26 +737,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, ...@@ -772,26 +737,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
goto err_out; goto err_out;
index = nla_get_u32(tb[TCA_ACT_INDEX]); index = nla_get_u32(tb[TCA_ACT_INDEX]);
err = -ENOMEM;
a = create_a(0);
if (a == NULL)
goto err_out;
err = -EINVAL; err = -EINVAL;
a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); ops = tc_lookup_action(tb[TCA_ACT_KIND]);
if (a->ops == NULL) /* could happen in batch of actions */ if (!ops) /* could happen in batch of actions */
goto err_free; goto err_out;
err = -ENOENT; err = -ENOENT;
if (a->ops->lookup(net, a, index) == 0) if (ops->lookup(net, &a, index) == 0)
goto err_mod; goto err_mod;
module_put(a->ops->owner); module_put(ops->owner);
return a; return a;
err_mod: err_mod:
module_put(a->ops->owner); module_put(ops->owner);
err_free:
kfree(a);
err_out: err_out:
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -816,8 +774,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -816,8 +774,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
struct netlink_callback dcb; struct netlink_callback dcb;
struct nlattr *nest; struct nlattr *nest;
struct nlattr *tb[TCA_ACT_MAX + 1]; struct nlattr *tb[TCA_ACT_MAX + 1];
const struct tc_action_ops *ops;
struct nlattr *kind; struct nlattr *kind;
struct tc_action a;
int err = -ENOMEM; int err = -ENOMEM;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
...@@ -834,10 +792,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -834,10 +792,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
err = -EINVAL; err = -EINVAL;
kind = tb[TCA_ACT_KIND]; kind = tb[TCA_ACT_KIND];
memset(&a, 0, sizeof(struct tc_action)); ops = tc_lookup_action(kind);
INIT_LIST_HEAD(&a.list); if (!ops) /*some idjot trying to flush unknown action */
a.ops = tc_lookup_action(kind);
if (a.ops == NULL) /*some idjot trying to flush unknown action */
goto err_out; goto err_out;
nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
...@@ -853,7 +809,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -853,7 +809,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(net, skb, &dcb, RTM_DELACTION, &a); err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops);
if (err < 0) if (err < 0)
goto out_module_put; goto out_module_put;
if (err == 0) if (err == 0)
...@@ -863,7 +819,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -863,7 +819,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
nlh->nlmsg_len = skb_tail_pointer(skb) - b; nlh->nlmsg_len = skb_tail_pointer(skb) - b;
nlh->nlmsg_flags |= NLM_F_ROOT; nlh->nlmsg_flags |= NLM_F_ROOT;
module_put(a.ops->owner); module_put(ops->owner);
err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO); n->nlmsg_flags & NLM_F_ECHO);
if (err > 0) if (err > 0)
...@@ -872,7 +828,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -872,7 +828,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
return err; return err;
out_module_put: out_module_put:
module_put(a.ops->owner); module_put(ops->owner);
err_out: err_out:
noflush_out: noflush_out:
kfree_skb(skb); kfree_skb(skb);
...@@ -1084,7 +1040,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1084,7 +1040,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct nlattr *nest; struct nlattr *nest;
struct tc_action_ops *a_o; struct tc_action_ops *a_o;
struct tc_action a;
int ret = 0; int ret = 0;
struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh);
struct nlattr *kind = find_dump_kind(cb->nlh); struct nlattr *kind = find_dump_kind(cb->nlh);
...@@ -1098,9 +1053,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1098,9 +1053,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
if (a_o == NULL) if (a_o == NULL)
return 0; return 0;
memset(&a, 0, sizeof(struct tc_action));
a.ops = a_o;
nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
cb->nlh->nlmsg_type, sizeof(*t), 0); cb->nlh->nlmsg_type, sizeof(*t), 0);
if (!nlh) if (!nlh)
...@@ -1114,7 +1066,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1114,7 +1066,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(net, skb, cb, RTM_GETACTION, &a); ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
if (ret < 0) if (ret < 0)
goto out_module_put; goto out_module_put;
......
...@@ -34,11 +34,12 @@ struct tcf_bpf_cfg { ...@@ -34,11 +34,12 @@ struct tcf_bpf_cfg {
}; };
static int bpf_net_id; static int bpf_net_id;
static struct tc_action_ops act_bpf_ops;
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)
{ {
struct tcf_bpf *prog = act->priv; struct tcf_bpf *prog = to_bpf(act);
struct bpf_prog *filter; struct bpf_prog *filter;
int action, filter_res; int action, filter_res;
bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS; bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS;
...@@ -134,7 +135,7 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act, ...@@ -134,7 +135,7 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
int bind, int ref) int bind, int ref)
{ {
unsigned char *tp = skb_tail_pointer(skb); unsigned char *tp = skb_tail_pointer(skb);
struct tcf_bpf *prog = act->priv; struct tcf_bpf *prog = to_bpf(act);
struct tc_act_bpf opt = { struct tc_act_bpf opt = {
.index = prog->tcf_index, .index = prog->tcf_index,
.refcnt = prog->tcf_refcnt - ref, .refcnt = prog->tcf_refcnt - ref,
...@@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog, ...@@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
} }
static int tcf_bpf_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, bpf_net_id);
...@@ -295,7 +296,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -295,7 +296,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (!tcf_hash_check(tn, parm->index, act, bind)) { if (!tcf_hash_check(tn, parm->index, act, bind)) {
ret = tcf_hash_create(tn, parm->index, est, act, ret = tcf_hash_create(tn, parm->index, est, act,
sizeof(*prog), bind, true); &act_bpf_ops, bind, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (bind) if (bind)
return 0; return 0;
tcf_hash_release(act, bind); tcf_hash_release(*act, bind);
if (!replace) if (!replace)
return -EEXIST; return -EEXIST;
} }
...@@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (ret < 0) if (ret < 0)
goto out; goto out;
prog = to_bpf(act); prog = to_bpf(*act);
ASSERT_RTNL(); ASSERT_RTNL();
if (res != ACT_P_CREATED) if (res != ACT_P_CREATED)
...@@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -343,7 +344,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(tn, 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();
...@@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
return res; return res;
out: out:
if (res == ACT_P_CREATED) if (res == ACT_P_CREATED)
tcf_hash_cleanup(act, est); tcf_hash_cleanup(*act, est);
return ret; return ret;
} }
...@@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind) ...@@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind)
{ {
struct tcf_bpf_cfg tmp; struct tcf_bpf_cfg tmp;
tcf_bpf_prog_fill_cfg(act->priv, &tmp); tcf_bpf_prog_fill_cfg(to_bpf(act), &tmp);
tcf_bpf_cfg_cleanup(&tmp); tcf_bpf_cfg_cleanup(&tmp);
} }
static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id); struct tc_action_net *tn = net_generic(net, bpf_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, bpf_net_id);
...@@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { ...@@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
.init = tcf_bpf_init, .init = tcf_bpf_init,
.walk = tcf_bpf_walker, .walk = tcf_bpf_walker,
.lookup = tcf_bpf_search, .lookup = tcf_bpf_search,
.size = sizeof(struct tcf_bpf),
}; };
static __net_init int bpf_init_net(struct net *net) static __net_init int bpf_init_net(struct net *net)
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define CONNMARK_TAB_MASK 3 #define CONNMARK_TAB_MASK 3
static int connmark_net_id; static int connmark_net_id;
static struct tc_action_ops act_connmark_ops;
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)
...@@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, ...@@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
const struct nf_conntrack_tuple_hash *thash; const struct nf_conntrack_tuple_hash *thash;
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct tcf_connmark_info *ca = a->priv; struct tcf_connmark_info *ca = to_connmark(a);
struct nf_conntrack_zone zone; struct nf_conntrack_zone zone;
struct nf_conn *c; struct nf_conn *c;
int proto; int proto;
...@@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { ...@@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
}; };
static int tcf_connmark_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, connmark_net_id);
...@@ -116,22 +117,22 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -116,22 +117,22 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*ci), bind, false); &act_connmark_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
ci = to_connmark(a); ci = to_connmark(*a);
ci->tcf_action = parm->action; ci->tcf_action = parm->action;
ci->net = net; ci->net = net;
ci->zone = parm->zone; ci->zone = parm->zone;
tcf_hash_insert(tn, a); tcf_hash_insert(tn, *a);
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
ci = to_connmark(a); ci = to_connmark(*a);
if (bind) if (bind)
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
/* replacing action and zone */ /* replacing action and zone */
...@@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_connmark_info *ci = a->priv; struct tcf_connmark_info *ci = to_connmark(a);
struct tc_connmark opt = { struct tc_connmark opt = {
.index = ci->tcf_index, .index = ci->tcf_index,
...@@ -173,14 +174,14 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -173,14 +174,14 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id); struct tc_action_net *tn = net_generic(net, connmark_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, connmark_net_id);
...@@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = { ...@@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = {
.init = tcf_connmark_init, .init = tcf_connmark_init,
.walk = tcf_connmark_walker, .walk = tcf_connmark_walker,
.lookup = tcf_connmark_search, .lookup = tcf_connmark_search,
.size = sizeof(struct tcf_connmark_info),
}; };
static __net_init int connmark_init_net(struct net *net) static __net_init int connmark_init_net(struct net *net)
......
...@@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { ...@@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
}; };
static int csum_net_id; static int csum_net_id;
static struct tc_action_ops act_csum_ops;
static int tcf_csum_init(struct net *net, struct nlattr *nla, static int tcf_csum_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, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
...@@ -67,26 +68,26 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, ...@@ -67,26 +68,26 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*p), bind, false); &act_csum_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
p = to_tcf_csum(a); p = to_tcf_csum(*a);
spin_lock_bh(&p->tcf_lock); spin_lock_bh(&p->tcf_lock);
p->tcf_action = parm->action; p->tcf_action = parm->action;
p->update_flags = parm->update_flags; p->update_flags = parm->update_flags;
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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -496,7 +497,7 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags) ...@@ -496,7 +497,7 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags)
static int tcf_csum(struct sk_buff *skb, static int tcf_csum(struct sk_buff *skb,
const struct tc_action *a, struct tcf_result *res) const struct tc_action *a, struct tcf_result *res)
{ {
struct tcf_csum *p = a->priv; struct tcf_csum *p = to_tcf_csum(a);
int action; int action;
u32 update_flags; u32 update_flags;
...@@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb, ...@@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb,
struct tc_action *a, int bind, int ref) struct tc_action *a, int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_csum *p = a->priv; struct tcf_csum *p = to_tcf_csum(a);
struct tc_csum opt = { struct tc_csum opt = {
.update_flags = p->update_flags, .update_flags = p->update_flags,
.index = p->tcf_index, .index = p->tcf_index,
...@@ -560,14 +561,14 @@ static int tcf_csum_dump(struct sk_buff *skb, ...@@ -560,14 +561,14 @@ static int tcf_csum_dump(struct sk_buff *skb,
static int tcf_csum_walker(struct net *net, struct sk_buff *skb, static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, csum_net_id);
...@@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = { ...@@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = {
.init = tcf_csum_init, .init = tcf_csum_init,
.walk = tcf_csum_walker, .walk = tcf_csum_walker,
.lookup = tcf_csum_search, .lookup = tcf_csum_search,
.size = sizeof(struct tcf_csum),
}; };
static __net_init int csum_init_net(struct net *net) static __net_init int csum_init_net(struct net *net)
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define GACT_TAB_MASK 15 #define GACT_TAB_MASK 15
static int gact_net_id; static int gact_net_id;
static struct tc_action_ops act_gact_ops;
#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)
...@@ -56,7 +57,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { ...@@ -56,7 +57,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
}; };
static int tcf_gact_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, gact_net_id);
...@@ -93,19 +94,19 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -93,19 +94,19 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*gact), bind, true); &act_gact_ops, bind, true);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
gact = to_gact(a); gact = to_gact(*a);
ASSERT_RTNL(); ASSERT_RTNL();
gact->tcf_action = parm->action; gact->tcf_action = parm->action;
...@@ -121,14 +122,14 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -121,14 +122,14 @@ 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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_gact *gact = a->priv; struct tcf_gact *gact = to_gact(a);
int action = READ_ONCE(gact->tcf_action); int action = READ_ONCE(gact->tcf_action);
#ifdef CONFIG_GACT_PROB #ifdef CONFIG_GACT_PROB
...@@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, ...@@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets,
u64 lastuse) u64 lastuse)
{ {
struct tcf_gact *gact = a->priv; struct tcf_gact *gact = to_gact(a);
int action = READ_ONCE(gact->tcf_action); int action = READ_ONCE(gact->tcf_action);
struct tcf_t *tm = &gact->tcf_tm; struct tcf_t *tm = &gact->tcf_tm;
...@@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_gact *gact = a->priv; struct tcf_gact *gact = to_gact(a);
struct tc_gact opt = { struct tc_gact opt = {
.index = gact->tcf_index, .index = gact->tcf_index,
.refcnt = gact->tcf_refcnt - ref, .refcnt = gact->tcf_refcnt - ref,
...@@ -201,14 +202,14 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -201,14 +202,14 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_gact_walker(struct net *net, struct sk_buff *skb, static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id); struct tc_action_net *tn = net_generic(net, gact_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, gact_net_id);
...@@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = { ...@@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = {
.init = tcf_gact_init, .init = tcf_gact_init,
.walk = tcf_gact_walker, .walk = tcf_gact_walker,
.lookup = tcf_gact_search, .lookup = tcf_gact_search,
.size = sizeof(struct tcf_gact),
}; };
static __net_init int gact_init_net(struct net *net) static __net_init int gact_init_net(struct net *net)
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
static int ife_net_id; static int ife_net_id;
static int max_metacnt = IFE_META_MAX + 1; static int max_metacnt = IFE_META_MAX + 1;
static struct tc_action_ops act_ife_ops;
static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
[TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)},
...@@ -364,7 +365,7 @@ static int dump_metalist(struct sk_buff *skb, struct tcf_ife_info *ife) ...@@ -364,7 +365,7 @@ static int dump_metalist(struct sk_buff *skb, struct tcf_ife_info *ife)
/* under ife->tcf_lock */ /* under ife->tcf_lock */
static void _tcf_ife_cleanup(struct tc_action *a, int bind) static void _tcf_ife_cleanup(struct tc_action *a, int bind)
{ {
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
struct tcf_meta_info *e, *n; struct tcf_meta_info *e, *n;
list_for_each_entry_safe(e, n, &ife->metalist, metalist) { list_for_each_entry_safe(e, n, &ife->metalist, metalist) {
...@@ -382,7 +383,7 @@ static void _tcf_ife_cleanup(struct tc_action *a, int bind) ...@@ -382,7 +383,7 @@ static void _tcf_ife_cleanup(struct tc_action *a, int bind)
static void tcf_ife_cleanup(struct tc_action *a, int bind) static void tcf_ife_cleanup(struct tc_action *a, int bind)
{ {
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
spin_lock_bh(&ife->tcf_lock); spin_lock_bh(&ife->tcf_lock);
_tcf_ife_cleanup(a, bind); _tcf_ife_cleanup(a, bind);
...@@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, ...@@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
} }
static int tcf_ife_init(struct net *net, struct nlattr *nla, static int tcf_ife_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, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
...@@ -451,25 +452,25 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -451,25 +452,25 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
**/ **/
if (!tb[TCA_IFE_TYPE]) { if (!tb[TCA_IFE_TYPE]) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
pr_info("You MUST pass etherype for encoding\n"); pr_info("You MUST pass etherype for encoding\n");
return -EINVAL; return -EINVAL;
} }
} }
if (!exists) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
bind, false); bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
ife = to_ife(a); ife = to_ife(*a);
ife->flags = parm->flags; ife->flags = parm->flags;
if (parm->flags & IFE_ENCODE) { if (parm->flags & IFE_ENCODE) {
...@@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
if (err) { if (err) {
metadata_parse_err: metadata_parse_err:
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
_tcf_ife_cleanup(a, bind); _tcf_ife_cleanup(*a, bind);
if (exists) if (exists)
spin_unlock_bh(&ife->tcf_lock); spin_unlock_bh(&ife->tcf_lock);
...@@ -529,7 +530,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -529,7 +530,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
err = use_all_metadata(ife); err = use_all_metadata(ife);
if (err) { if (err) {
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
_tcf_ife_cleanup(a, bind); _tcf_ife_cleanup(*a, bind);
if (exists) if (exists)
spin_unlock_bh(&ife->tcf_lock); spin_unlock_bh(&ife->tcf_lock);
...@@ -541,7 +542,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -541,7 +542,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&ife->tcf_lock); spin_unlock_bh(&ife->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_insert(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, ...@@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
int ref) int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
struct tc_ife opt = { struct tc_ife opt = {
.index = ife->tcf_index, .index = ife->tcf_index,
.refcnt = ife->tcf_refcnt - ref, .refcnt = ife->tcf_refcnt - ref,
...@@ -623,7 +624,7 @@ struct meta_tlvhdr { ...@@ -623,7 +624,7 @@ struct meta_tlvhdr {
static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
int action = ife->tcf_action; int action = ife->tcf_action;
struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data;
u16 ifehdrln = ifehdr->metalen; u16 ifehdrln = ifehdr->metalen;
...@@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife) ...@@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife)
static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
int action = ife->tcf_action; int action = ife->tcf_action;
struct ethhdr *oethh; /* outer ether header */ struct ethhdr *oethh; /* outer ether header */
struct ethhdr *iethh; /* inner eth header */ struct ethhdr *iethh; /* inner eth header */
...@@ -799,7 +800,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, ...@@ -799,7 +800,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_ife_info *ife = a->priv; struct tcf_ife_info *ife = to_ife(a);
if (ife->flags & IFE_ENCODE) if (ife->flags & IFE_ENCODE)
return tcf_ife_encode(skb, a, res); return tcf_ife_encode(skb, a, res);
...@@ -819,14 +820,14 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, ...@@ -819,14 +820,14 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
static int tcf_ife_walker(struct net *net, struct sk_buff *skb, static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index) static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
...@@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = { ...@@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = {
.init = tcf_ife_init, .init = tcf_ife_init,
.walk = tcf_ife_walker, .walk = tcf_ife_walker,
.lookup = tcf_ife_search, .lookup = tcf_ife_search,
.size = sizeof(struct tcf_ife_info),
}; };
static __net_init int ife_init_net(struct net *net) static __net_init int ife_init_net(struct net *net)
......
...@@ -31,8 +31,10 @@ ...@@ -31,8 +31,10 @@
#define IPT_TAB_MASK 15 #define IPT_TAB_MASK 15
static int ipt_net_id; static int ipt_net_id;
static struct tc_action_ops act_ipt_ops;
static int xt_net_id; static int xt_net_id;
static struct tc_action_ops act_xt_ops;
static int ipt_init_target(struct xt_entry_target *t, char *table, static int ipt_init_target(struct xt_entry_target *t, char *table,
unsigned int hook) unsigned int hook)
...@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { ...@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
}; };
static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
struct nlattr *est, struct tc_action *a, int ovr, struct nlattr *est, struct tc_action **a,
int bind) const struct tc_action_ops *ops, 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;
...@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, ret = tcf_hash_create(tn, index, est, a, ops, bind,
false); false);
if (ret) if (ret)
return ret; return ret;
...@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
} else { } else {
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
ipt = to_ipt(a);
hook = nla_get_u32(tb[TCA_IPT_HOOK]); hook = nla_get_u32(tb[TCA_IPT_HOOK]);
err = -ENOMEM; err = -ENOMEM;
...@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
if (err < 0) if (err < 0)
goto err3; goto err3;
ipt = to_ipt(*a);
spin_lock_bh(&ipt->tcf_lock); spin_lock_bh(&ipt->tcf_lock);
if (ret != ACT_P_CREATED) { if (ret != ACT_P_CREATED) {
ipt_destroy_target(ipt->tcfi_t); ipt_destroy_target(ipt->tcfi_t);
...@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
err3: err3:
...@@ -183,33 +185,33 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -183,33 +185,33 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
kfree(tname); kfree(tname);
err1: err1:
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_cleanup(a, est); tcf_hash_cleanup(*a, est);
return err; return err;
} }
static int tcf_ipt_init(struct net *net, struct nlattr *nla, static int tcf_ipt_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, ipt_net_id); struct tc_action_net *tn = net_generic(net, ipt_net_id);
return __tcf_ipt_init(tn, nla, est, a, ovr, bind); return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
} }
static int tcf_xt_init(struct net *net, struct nlattr *nla, static int tcf_xt_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, xt_net_id); struct tc_action_net *tn = net_generic(net, xt_net_id);
return __tcf_ipt_init(tn, nla, est, a, ovr, bind); return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, 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)
{ {
int ret = 0, result = 0; int ret = 0, result = 0;
struct tcf_ipt *ipt = a->priv; struct tcf_ipt *ipt = to_ipt(a);
struct xt_action_param par; struct xt_action_param par;
if (skb_unclone(skb, GFP_ATOMIC)) if (skb_unclone(skb, GFP_ATOMIC))
...@@ -259,7 +261,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, ...@@ -259,7 +261,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
int ref) int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_ipt *ipt = a->priv; struct tcf_ipt *ipt = to_ipt(a);
struct xt_entry_target *t; struct xt_entry_target *t;
struct tcf_t tm; struct tcf_t tm;
struct tc_cnt c; struct tc_cnt c;
...@@ -299,14 +301,14 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, ...@@ -299,14 +301,14 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, ipt_net_id); struct tc_action_net *tn = net_generic(net, ipt_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, ipt_net_id);
...@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = { ...@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = {
.init = tcf_ipt_init, .init = tcf_ipt_init,
.walk = tcf_ipt_walker, .walk = tcf_ipt_walker,
.lookup = tcf_ipt_search, .lookup = tcf_ipt_search,
.size = sizeof(struct tcf_ipt),
}; };
static __net_init int ipt_init_net(struct net *net) static __net_init int ipt_init_net(struct net *net)
...@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = { ...@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = {
static int tcf_xt_walker(struct net *net, struct sk_buff *skb, static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, xt_net_id); struct tc_action_net *tn = net_generic(net, xt_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, xt_net_id);
...@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = { ...@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = {
.init = tcf_xt_init, .init = tcf_xt_init,
.walk = tcf_xt_walker, .walk = tcf_xt_walker,
.lookup = tcf_xt_search, .lookup = tcf_xt_search,
.size = sizeof(struct tcf_ipt),
}; };
static __net_init int xt_init_net(struct net *net) static __net_init int xt_init_net(struct net *net)
......
...@@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { ...@@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
}; };
static int mirred_net_id; static int mirred_net_id;
static struct tc_action_ops act_mirred_ops;
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 tc_action_net *tn = net_generic(net, mirred_net_id);
...@@ -84,14 +85,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -84,14 +85,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
break; break;
default: default:
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
if (parm->ifindex) { if (parm->ifindex) {
dev = __dev_get_by_index(net, parm->ifindex); dev = __dev_get_by_index(net, parm->ifindex);
if (dev == NULL) { if (dev == NULL) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -ENODEV; return -ENODEV;
} }
switch (dev->type) { switch (dev->type) {
...@@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
if (dev == NULL) if (dev == NULL)
return -EINVAL; return -EINVAL;
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*m), bind, true); &act_mirred_ops, bind, true);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
m = to_mirred(a); m = to_mirred(*a);
ASSERT_RTNL(); ASSERT_RTNL();
m->tcf_action = parm->action; m->tcf_action = parm->action;
...@@ -142,7 +143,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -142,7 +143,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(tn, a); tcf_hash_insert(tn, *a);
} }
return ret; return ret;
...@@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_mirred *m = a->priv; struct tcf_mirred *m = to_mirred(a);
struct net_device *dev; struct net_device *dev;
struct sk_buff *skb2; struct sk_buff *skb2;
int retval, err; int retval, err;
...@@ -206,7 +207,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, ...@@ -206,7 +207,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_mirred *m = a->priv; struct tcf_mirred *m = to_mirred(a);
struct tc_mirred opt = { struct tc_mirred opt = {
.index = m->tcf_index, .index = m->tcf_index,
.action = m->tcf_action, .action = m->tcf_action,
...@@ -232,14 +233,14 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i ...@@ -232,14 +233,14 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i
static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id); struct tc_action_net *tn = net_generic(net, mirred_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, mirred_net_id);
...@@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = { ...@@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = {
.init = tcf_mirred_init, .init = tcf_mirred_init,
.walk = tcf_mirred_walker, .walk = tcf_mirred_walker,
.lookup = tcf_mirred_search, .lookup = tcf_mirred_search,
.size = sizeof(struct tcf_mirred),
}; };
static __net_init int mirred_init_net(struct net *net) static __net_init int mirred_init_net(struct net *net)
......
...@@ -32,13 +32,14 @@ ...@@ -32,13 +32,14 @@
#define NAT_TAB_MASK 15 #define NAT_TAB_MASK 15
static int nat_net_id; static int nat_net_id;
static struct tc_action_ops act_nat_ops;
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) },
}; };
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 tc_action_net *tn = net_generic(net, nat_net_id);
struct nlattr *tb[TCA_NAT_MAX + 1]; struct nlattr *tb[TCA_NAT_MAX + 1];
...@@ -59,18 +60,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -59,18 +60,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!tcf_hash_check(tn, parm->index, a, bind)) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*p), bind, false); &act_nat_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind) if (bind)
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
p = to_tcf_nat(a); p = to_tcf_nat(*a);
spin_lock_bh(&p->tcf_lock); spin_lock_bh(&p->tcf_lock);
p->old_addr = parm->old_addr; p->old_addr = parm->old_addr;
...@@ -82,7 +83,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -82,7 +83,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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_nat *p = a->priv; struct tcf_nat *p = to_tcf_nat(a);
struct iphdr *iph; struct iphdr *iph;
__be32 old_addr; __be32 old_addr;
__be32 new_addr; __be32 new_addr;
...@@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_nat *p = a->priv; struct tcf_nat *p = to_tcf_nat(a);
struct tc_nat opt = { struct tc_nat opt = {
.old_addr = p->old_addr, .old_addr = p->old_addr,
.new_addr = p->new_addr, .new_addr = p->new_addr,
...@@ -278,14 +279,14 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -278,14 +279,14 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_nat_walker(struct net *net, struct sk_buff *skb, static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id); struct tc_action_net *tn = net_generic(net, nat_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, nat_net_id);
...@@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = { ...@@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = {
.init = tcf_nat_init, .init = tcf_nat_init,
.walk = tcf_nat_walker, .walk = tcf_nat_walker,
.lookup = tcf_nat_search, .lookup = tcf_nat_search,
.size = sizeof(struct tcf_nat),
}; };
static __net_init int nat_init_net(struct net *net) static __net_init int nat_init_net(struct net *net)
......
...@@ -26,13 +26,14 @@ ...@@ -26,13 +26,14 @@
#define PEDIT_TAB_MASK 15 #define PEDIT_TAB_MASK 15
static int pedit_net_id; static int pedit_net_id;
static struct tc_action_ops act_pedit_ops;
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) },
}; };
static int tcf_pedit_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, pedit_net_id);
...@@ -61,23 +62,23 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -61,23 +62,23 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
if (!parm->nkeys) if (!parm->nkeys)
return -EINVAL; return -EINVAL;
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*p), bind, false); &act_pedit_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
p = to_pedit(a); p = to_pedit(*a);
keys = kmalloc(ksize, GFP_KERNEL); keys = kmalloc(ksize, GFP_KERNEL);
if (keys == NULL) { if (keys == NULL) {
tcf_hash_cleanup(a, est); tcf_hash_cleanup(*a, est);
return -ENOMEM; return -ENOMEM;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind) if (bind)
return 0; return 0;
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
p = to_pedit(a); p = to_pedit(*a);
if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
keys = kmalloc(ksize, GFP_KERNEL); keys = kmalloc(ksize, GFP_KERNEL);
if (keys == NULL) if (keys == NULL)
...@@ -96,13 +97,13 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -96,13 +97,13 @@ 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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
static void tcf_pedit_cleanup(struct tc_action *a, int bind) static void tcf_pedit_cleanup(struct tc_action *a, int bind)
{ {
struct tcf_pedit *p = a->priv; struct tcf_pedit *p = to_pedit(a);
struct tc_pedit_key *keys = p->tcfp_keys; struct tc_pedit_key *keys = p->tcfp_keys;
kfree(keys); kfree(keys);
} }
...@@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind) ...@@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_pedit *p = a->priv; struct tcf_pedit *p = to_pedit(a);
int i; int i;
unsigned int off; unsigned int off;
...@@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_pedit *p = a->priv; struct tcf_pedit *p = to_pedit(a);
struct tc_pedit *opt; struct tc_pedit *opt;
struct tcf_t t; struct tcf_t t;
int s; int s;
...@@ -216,14 +217,14 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -216,14 +217,14 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id); struct tc_action_net *tn = net_generic(net, pedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, pedit_net_id);
...@@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = { ...@@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = {
.init = tcf_pedit_init, .init = tcf_pedit_init,
.walk = tcf_pedit_walker, .walk = tcf_pedit_walker,
.lookup = tcf_pedit_search, .lookup = tcf_pedit_search,
.size = sizeof(struct tcf_pedit),
}; };
static __net_init int pedit_init_net(struct net *net) static __net_init int pedit_init_net(struct net *net)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <net/netlink.h> #include <net/netlink.h>
struct tcf_police { struct tcf_police {
struct tcf_common common; struct tc_action common;
int tcfp_result; int tcfp_result;
u32 tcfp_ewma_rate; u32 tcfp_ewma_rate;
s64 tcfp_burst; s64 tcfp_burst;
...@@ -37,8 +37,8 @@ struct tcf_police { ...@@ -37,8 +37,8 @@ struct tcf_police {
struct psched_ratecfg peak; struct psched_ratecfg peak;
bool peak_present; bool peak_present;
}; };
#define to_police(pc) \
container_of(pc->priv, struct tcf_police, common) #define to_police(pc) ((struct tcf_police *)pc)
#define POL_TAB_MASK 15 #define POL_TAB_MASK 15
...@@ -56,15 +56,14 @@ struct tc_police_compat { ...@@ -56,15 +56,14 @@ struct tc_police_compat {
/* Each policer is serialized by its individual spinlock */ /* Each policer is serialized by its individual spinlock */
static int police_net_id; static int police_net_id;
static struct tc_action_ops act_police_ops;
static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, police_net_id); struct tc_action_net *tn = net_generic(net, police_net_id);
struct tcf_hashinfo *hinfo = tn->hinfo; struct tcf_hashinfo *hinfo = tn->hinfo;
struct hlist_head *head;
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;
struct nlattr *nest; struct nlattr *nest;
...@@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, ...@@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
s_i = cb->args[0]; s_i = cb->args[0];
for (i = 0; i < (POL_TAB_MASK + 1); i++) { for (i = 0; i < (POL_TAB_MASK + 1); i++) {
struct hlist_head *head;
struct tc_action *p;
head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)]; head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)];
hlist_for_each_entry_rcu(p, head, tcfc_head) { hlist_for_each_entry_rcu(p, head, tcfa_head) {
index++; index++;
if (index < s_i) if (index < s_i)
continue; continue;
a->priv = p; nest = nla_nest_start(skb, index);
a->order = index;
nest = nla_nest_start(skb, a->order);
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
if (type == RTM_DELACTION) if (type == RTM_DELACTION)
err = tcf_action_dump_1(skb, a, 0, 1); err = tcf_action_dump_1(skb, p, 0, 1);
else else
err = tcf_action_dump_1(skb, a, 0, 0); err = tcf_action_dump_1(skb, p, 0, 0);
if (err < 0) { if (err < 0) {
index--; index--;
nla_nest_cancel(skb, nest); nla_nest_cancel(skb, nest);
...@@ -116,7 +116,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { ...@@ -116,7 +116,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
}; };
static int tcf_act_police_init(struct net *net, struct nlattr *nla, static int tcf_act_police_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)
{ {
int ret = 0, err; int ret = 0, err;
...@@ -142,13 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, ...@@ -142,13 +142,7 @@ static int tcf_act_police_init(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(tn, a, parm->index)) { if (tcf_hash_check(tn, parm->index, a, bind)) {
police = to_police(a);
if (bind) {
police->tcf_bindcnt += 1;
police->tcf_refcnt += 1;
return 0;
}
if (ovr) if (ovr)
goto override; goto override;
/* not replacing */ /* not replacing */
...@@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, ...@@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
} }
} else { } else {
ret = tcf_hash_create(tn, parm->index, NULL, a, ret = tcf_hash_create(tn, parm->index, NULL, a,
sizeof(*police), bind, false); &act_police_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} }
police = to_police(a);
override: override:
police = to_police(*a);
if (parm->rate.rate) { if (parm->rate.rate) {
err = -ENOMEM; err = -ENOMEM;
R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
...@@ -235,7 +229,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, ...@@ -235,7 +229,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
return ret; return ret;
police->tcfp_t_c = ktime_get_ns(); police->tcfp_t_c = ktime_get_ns();
tcf_hash_insert(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
...@@ -245,14 +239,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, ...@@ -245,14 +239,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
qdisc_put_rtab(P_tab); qdisc_put_rtab(P_tab);
qdisc_put_rtab(R_tab); qdisc_put_rtab(R_tab);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_hash_cleanup(a, est); tcf_hash_cleanup(*a, est);
return err; return err;
} }
static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
struct tcf_result *res) struct tcf_result *res)
{ {
struct tcf_police *police = a->priv; struct tcf_police *police = to_police(a);
s64 now; s64 now;
s64 toks; s64 toks;
s64 ptoks = 0; s64 ptoks = 0;
...@@ -311,7 +305,7 @@ static int ...@@ -311,7 +305,7 @@ static int
tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_police *police = a->priv; struct tcf_police *police = to_police(a);
struct tc_police opt = { struct tc_police opt = {
.index = police->tcf_index, .index = police->tcf_index,
.action = police->tcf_action, .action = police->tcf_action,
...@@ -349,7 +343,7 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -349,7 +343,7 @@ 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) 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); struct tc_action_net *tn = net_generic(net, police_net_id);
...@@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = { ...@@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = {
.init = tcf_act_police_init, .init = tcf_act_police_init,
.walk = tcf_act_police_walker, .walk = tcf_act_police_walker,
.lookup = tcf_police_search, .lookup = tcf_police_search,
.size = sizeof(struct tcf_police),
}; };
static __net_init int police_init_net(struct net *net) static __net_init int police_init_net(struct net *net)
......
...@@ -27,12 +27,13 @@ ...@@ -27,12 +27,13 @@
#define SIMP_TAB_MASK 7 #define SIMP_TAB_MASK 7
static int simp_net_id; static int simp_net_id;
static struct tc_action_ops act_simp_ops;
#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)
{ {
struct tcf_defact *d = a->priv; struct tcf_defact *d = to_defact(a);
spin_lock(&d->tcf_lock); spin_lock(&d->tcf_lock);
tcf_lastuse_update(&d->tcf_tm); tcf_lastuse_update(&d->tcf_tm);
...@@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { ...@@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
}; };
static int tcf_simp_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, simp_net_id);
...@@ -100,7 +101,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -100,7 +101,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (tb[TCA_DEF_PARMS] == NULL) if (tb[TCA_DEF_PARMS] == NULL)
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]); parm = nla_data(tb[TCA_DEF_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind); exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind) if (exists && bind)
...@@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (tb[TCA_DEF_DATA] == NULL) { if (tb[TCA_DEF_DATA] == NULL) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
...@@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*d), bind, false); &act_simp_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
d = to_defact(a); d = to_defact(*a);
ret = alloc_defdata(d, defdata); ret = alloc_defdata(d, defdata);
if (ret < 0) { if (ret < 0) {
tcf_hash_cleanup(a, est); tcf_hash_cleanup(*a, est);
return ret; return ret;
} }
d->tcf_action = parm->action; d->tcf_action = parm->action;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
d = to_defact(a); d = to_defact(*a);
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
...@@ -139,7 +139,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -139,7 +139,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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_defact *d = a->priv; struct tcf_defact *d = to_defact(a);
struct tc_defact opt = { struct tc_defact opt = {
.index = d->tcf_index, .index = d->tcf_index,
.refcnt = d->tcf_refcnt - ref, .refcnt = d->tcf_refcnt - ref,
...@@ -172,14 +172,14 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -172,14 +172,14 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_simp_walker(struct net *net, struct sk_buff *skb, static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id); struct tc_action_net *tn = net_generic(net, simp_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, simp_net_id);
...@@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = { ...@@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = {
.init = tcf_simp_init, .init = tcf_simp_init,
.walk = tcf_simp_walker, .walk = tcf_simp_walker,
.lookup = tcf_simp_search, .lookup = tcf_simp_search,
.size = sizeof(struct tcf_defact),
}; };
static __net_init int simp_init_net(struct net *net) static __net_init int simp_init_net(struct net *net)
......
...@@ -30,11 +30,12 @@ ...@@ -30,11 +30,12 @@
#define SKBEDIT_TAB_MASK 15 #define SKBEDIT_TAB_MASK 15
static int skbedit_net_id; static int skbedit_net_id;
static struct tc_action_ops act_skbedit_ops;
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)
{ {
struct tcf_skbedit *d = a->priv; struct tcf_skbedit *d = to_skbedit(a);
spin_lock(&d->tcf_lock); spin_lock(&d->tcf_lock);
tcf_lastuse_update(&d->tcf_tm); tcf_lastuse_update(&d->tcf_tm);
...@@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { ...@@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
}; };
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, skbedit_net_id);
...@@ -114,21 +115,21 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -114,21 +115,21 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
return 0; return 0;
if (!flags) { if (!flags) {
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
if (!exists) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*d), bind, false); &act_skbedit_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
d = to_skbedit(a); d = to_skbedit(*a);
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
d = to_skbedit(a); d = to_skbedit(*a);
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
...@@ -150,7 +151,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -150,7 +151,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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_skbedit *d = a->priv; struct tcf_skbedit *d = to_skbedit(a);
struct tc_skbedit opt = { struct tc_skbedit opt = {
.index = d->tcf_index, .index = d->tcf_index,
.refcnt = d->tcf_refcnt - ref, .refcnt = d->tcf_refcnt - ref,
...@@ -194,14 +195,14 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -194,14 +195,14 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
...@@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = { ...@@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = {
.init = tcf_skbedit_init, .init = tcf_skbedit_init,
.walk = tcf_skbedit_walker, .walk = tcf_skbedit_walker,
.lookup = tcf_skbedit_search, .lookup = tcf_skbedit_search,
.size = sizeof(struct tcf_skbedit),
}; };
static __net_init int skbedit_init_net(struct net *net) static __net_init int skbedit_init_net(struct net *net)
......
...@@ -22,11 +22,12 @@ ...@@ -22,11 +22,12 @@
#define VLAN_TAB_MASK 15 #define VLAN_TAB_MASK 15
static int vlan_net_id; static int vlan_net_id;
static struct tc_action_ops act_vlan_ops;
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)
{ {
struct tcf_vlan *v = a->priv; struct tcf_vlan *v = to_vlan(a);
int action; int action;
int err; int err;
...@@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = { ...@@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
}; };
static int tcf_vlan_init(struct net *net, struct nlattr *nla, 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 tc_action_net *tn = net_generic(net, vlan_net_id);
...@@ -100,13 +101,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -100,13 +101,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
case TCA_VLAN_ACT_PUSH: case TCA_VLAN_ACT_PUSH:
if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
if (push_vid >= VLAN_VID_MASK) { if (push_vid >= VLAN_VID_MASK) {
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -ERANGE; return -ERANGE;
} }
...@@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
break; break;
default: default:
if (exists) if (exists)
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
return -EINVAL; return -EINVAL;
} }
action = parm->v_action; action = parm->v_action;
if (!exists) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*v), bind, false); &act_vlan_ops, bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
tcf_hash_release(a, bind); tcf_hash_release(*a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
} }
v = to_vlan(a); v = to_vlan(*a);
spin_lock_bh(&v->tcf_lock); spin_lock_bh(&v->tcf_lock);
...@@ -156,7 +157,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -156,7 +157,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(tn, a); tcf_hash_insert(tn, *a);
return ret; return ret;
} }
...@@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref) int bind, int ref)
{ {
unsigned char *b = skb_tail_pointer(skb); unsigned char *b = skb_tail_pointer(skb);
struct tcf_vlan *v = a->priv; struct tcf_vlan *v = to_vlan(a);
struct tc_vlan opt = { struct tc_vlan opt = {
.index = v->tcf_index, .index = v->tcf_index,
.refcnt = v->tcf_refcnt - ref, .refcnt = v->tcf_refcnt - ref,
...@@ -195,14 +196,14 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -195,14 +196,14 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
struct tc_action *a) const struct tc_action_ops *ops)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id); struct tc_action_net *tn = net_generic(net, vlan_net_id);
return tcf_generic_walker(tn, skb, cb, type, a); return tcf_generic_walker(tn, skb, cb, type, ops);
} }
static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index) 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); struct tc_action_net *tn = net_generic(net, vlan_net_id);
...@@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = { ...@@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = {
.init = tcf_vlan_init, .init = tcf_vlan_init,
.walk = tcf_vlan_walker, .walk = tcf_vlan_walker,
.lookup = tcf_vlan_search, .lookup = tcf_vlan_search,
.size = sizeof(struct tcf_vlan),
}; };
static __net_init int vlan_init_net(struct net *net) static __net_init int vlan_init_net(struct net *net)
......
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