summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-07-25 21:49:20 -0700
committerDavid S. Miller <davem@davemloft.net>2016-07-25 21:49:20 -0700
commitc43212bb7bebe24a93a7a7d86e767e1ce295d72a (patch)
treeec43ad59bbc09fa3ddc8382f33100bd1434fe182
parentb93dd49c1a35884864027abd707889b795637f7a (diff)
parentec0595cc4495be579309b4bfd5e997af0f2ae6f9 (diff)
downloadlinux-c43212bb7bebe24a93a7a7d86e767e1ce295d72a.tar.gz
linux-c43212bb7bebe24a93a7a7d86e767e1ce295d72a.tar.bz2
linux-c43212bb7bebe24a93a7a7d86e767e1ce295d72a.zip
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: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/act_api.h91
-rw-r--r--include/net/tc_act/tc_bpf.h5
-rw-r--r--include/net/tc_act/tc_connmark.h5
-rw-r--r--include/net/tc_act/tc_csum.h5
-rw-r--r--include/net/tc_act/tc_defact.h5
-rw-r--r--include/net/tc_act/tc_gact.h7
-rw-r--r--include/net/tc_act/tc_ife.h5
-rw-r--r--include/net/tc_act/tc_ipt.h5
-rw-r--r--include/net/tc_act/tc_mirred.h5
-rw-r--r--include/net/tc_act/tc_nat.h7
-rw-r--r--include/net/tc_act/tc_pedit.h5
-rw-r--r--include/net/tc_act/tc_skbedit.h5
-rw-r--r--include/net/tc_act/tc_vlan.h5
-rw-r--r--net/sched/act_api.c250
-rw-r--r--net/sched/act_bpf.c26
-rw-r--r--net/sched/act_connmark.c24
-rw-r--r--net/sched/act_csum.c22
-rw-r--r--net/sched/act_gact.c24
-rw-r--r--net/sched/act_ife.c38
-rw-r--r--net/sched/act_ipt.c48
-rw-r--r--net/sched/act_mirred.c26
-rw-r--r--net/sched/act_nat.c22
-rw-r--r--net/sched/act_pedit.c28
-rw-r--r--net/sched/act_police.c49
-rw-r--r--net/sched/act_simple.c29
-rw-r--r--net/sched/act_skbedit.c26
-rw-r--r--net/sched/act_vlan.c28
27 files changed, 378 insertions, 417 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 0bb210635e5f..41e6a24a44b9 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -10,34 +10,6 @@
#include <net/net_namespace.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 hlist_head *htab;
@@ -46,6 +18,44 @@ struct tcf_hashinfo {
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)
{
return index & hmask;
@@ -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);
}
-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
#define ACT_P_CREATED 1
@@ -106,17 +107,18 @@ struct tc_action_ops {
struct list_head head;
char kind[IFNAMSIZ];
__u32 type; /* TBD to match kind */
+ size_t size;
struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *,
struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
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,
- struct nlattr *est, struct tc_action *act, int ovr,
+ struct nlattr *est, struct tc_action **act, int ovr,
int bind);
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);
};
@@ -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,
struct netlink_callback *cb, int type,
- struct tc_action *a);
-int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index);
+ const struct tc_action_ops *ops);
+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);
-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 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_insert(struct tc_action_net *tn, struct tc_action *a);
diff --git a/include/net/tc_act/tc_bpf.h b/include/net/tc_act/tc_bpf.h
index 958d69cfb19c..2b94673a3dbc 100644
--- a/include/net/tc_act/tc_bpf.h
+++ b/include/net/tc_act/tc_bpf.h
@@ -14,7 +14,7 @@
#include <net/act_api.h>
struct tcf_bpf {
- struct tcf_common common;
+ struct tc_action common;
struct bpf_prog __rcu *filter;
union {
u32 bpf_fd;
@@ -23,7 +23,6 @@ struct tcf_bpf {
struct sock_filter *bpf_ops;
const char *bpf_name;
};
-#define to_bpf(a) \
- container_of(a->priv, struct tcf_bpf, common)
+#define to_bpf(a) ((struct tcf_bpf *)a)
#endif /* __NET_TC_BPF_H */
diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h
index 02caa406611b..59b515d32bb4 100644
--- a/include/net/tc_act/tc_connmark.h
+++ b/include/net/tc_act/tc_connmark.h
@@ -4,12 +4,11 @@
#include <net/act_api.h>
struct tcf_connmark_info {
- struct tcf_common common;
+ struct tc_action common;
struct net *net;
u16 zone;
};
-#define to_connmark(a) \
- container_of(a->priv, struct tcf_connmark_info, common)
+#define to_connmark(a) ((struct tcf_connmark_info *)a)
#endif /* __NET_TC_CONNMARK_H */
diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
index fa8f5fac65e9..f31fb6331a53 100644
--- a/include/net/tc_act/tc_csum.h
+++ b/include/net/tc_act/tc_csum.h
@@ -5,11 +5,10 @@
#include <net/act_api.h>
struct tcf_csum {
- struct tcf_common common;
+ struct tc_action common;
u32 update_flags;
};
-#define to_tcf_csum(a) \
- container_of(a->priv,struct tcf_csum,common)
+#define to_tcf_csum(a) ((struct tcf_csum *)a)
#endif /* __NET_TC_CSUM_H */
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
index ab9b5d6be67b..d47f040a3bdf 100644
--- a/include/net/tc_act/tc_defact.h
+++ b/include/net/tc_act/tc_defact.h
@@ -4,11 +4,10 @@
#include <net/act_api.h>
struct tcf_defact {
- struct tcf_common common;
+ struct tc_action common;
u32 tcfd_datalen;
void *tcfd_defdata;
};
-#define to_defact(a) \
- container_of(a->priv, struct tcf_defact, common)
+#define to_defact(a) ((struct tcf_defact *)a)
#endif /* __NET_TC_DEF_H */
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
index 93c520b83d10..b6f173910226 100644
--- a/include/net/tc_act/tc_gact.h
+++ b/include/net/tc_act/tc_gact.h
@@ -5,7 +5,7 @@
#include <linux/tc_act/tc_gact.h>
struct tcf_gact {
- struct tcf_common common;
+ struct tc_action common;
#ifdef CONFIG_GACT_PROB
u16 tcfg_ptype;
u16 tcfg_pval;
@@ -13,8 +13,7 @@ struct tcf_gact {
atomic_t packets;
#endif
};
-#define to_gact(a) \
- container_of(a->priv, struct tcf_gact, common)
+#define to_gact(a) ((struct tcf_gact *)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)
if (a->ops && a->ops->type != TCA_ACT_GACT)
return false;
- gact = a->priv;
+ gact = to_gact(a);
if (gact->tcf_action == TC_ACT_SHOT)
return true;
diff --git a/include/net/tc_act/tc_ife.h b/include/net/tc_act/tc_ife.h
index c55facd17b7e..5164bd7a38fb 100644
--- a/include/net/tc_act/tc_ife.h
+++ b/include/net/tc_act/tc_ife.h
@@ -8,7 +8,7 @@
#define IFE_METAHDRLEN 2
struct tcf_ife_info {
- struct tcf_common common;
+ struct tc_action common;
u8 eth_dst[ETH_ALEN];
u8 eth_src[ETH_ALEN];
u16 eth_type;
@@ -16,8 +16,7 @@ struct tcf_ife_info {
/* list of metaids allowed */
struct list_head metalist;
};
-#define to_ife(a) \
- container_of(a->priv, struct tcf_ife_info, common)
+#define to_ife(a) ((struct tcf_ife_info *)a)
struct tcf_meta_info {
const struct tcf_meta_ops *ops;
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
index c0f4193f432c..31309766e379 100644
--- a/include/net/tc_act/tc_ipt.h
+++ b/include/net/tc_act/tc_ipt.h
@@ -6,12 +6,11 @@
struct xt_entry_target;
struct tcf_ipt {
- struct tcf_common common;
+ struct tc_action common;
u32 tcfi_hook;
char *tcfi_tname;
struct xt_entry_target *tcfi_t;
};
-#define to_ipt(a) \
- container_of(a->priv, struct tcf_ipt, common)
+#define to_ipt(a) ((struct tcf_ipt *)a)
#endif /* __NET_TC_IPT_H */
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
index 6a13a7c74e0c..62770add15bd 100644
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -5,15 +5,14 @@
#include <linux/tc_act/tc_mirred.h>
struct tcf_mirred {
- struct tcf_common common;
+ struct tc_action common;
int tcfm_eaction;
int tcfm_ifindex;
int tcfm_ok_push;
struct net_device __rcu *tcfm_dev;
struct list_head tcfm_list;
};
-#define to_mirred(a) \
- container_of(a->priv, struct tcf_mirred, common)
+#define to_mirred(a) ((struct tcf_mirred *)a)
static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
{
diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h
index 63d8e9ca9d99..56681a320612 100644
--- a/include/net/tc_act/tc_nat.h
+++ b/include/net/tc_act/tc_nat.h
@@ -5,7 +5,7 @@
#include <net/act_api.h>
struct tcf_nat {
- struct tcf_common common;
+ struct tc_action common;
__be32 old_addr;
__be32 new_addr;
@@ -13,9 +13,6 @@ struct tcf_nat {
u32 flags;
};
-static inline struct tcf_nat *to_tcf_nat(struct tc_action *a)
-{
- return container_of(a->priv, struct tcf_nat, common);
-}
+#define to_tcf_nat(a) ((struct tcf_nat *)a)
#endif /* __NET_TC_NAT_H */
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
index 5b80998879c7..29e38d6823df 100644
--- a/include/net/tc_act/tc_pedit.h
+++ b/include/net/tc_act/tc_pedit.h
@@ -4,12 +4,11 @@
#include <net/act_api.h>
struct tcf_pedit {
- struct tcf_common common;
+ struct tc_action common;
unsigned char tcfp_nkeys;
unsigned char tcfp_flags;
struct tc_pedit_key *tcfp_keys;
};
-#define to_pedit(a) \
- container_of(a->priv, struct tcf_pedit, common)
+#define to_pedit(a) ((struct tcf_pedit *)a)
#endif /* __NET_TC_PED_H */
diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
index d01a5d40cfb5..5767e9dbcf92 100644
--- a/include/net/tc_act/tc_skbedit.h
+++ b/include/net/tc_act/tc_skbedit.h
@@ -23,15 +23,14 @@
#include <linux/tc_act/tc_skbedit.h>
struct tcf_skbedit {
- struct tcf_common common;
+ struct tc_action common;
u32 flags;
u32 priority;
u32 mark;
u16 queue_mapping;
u16 ptype;
};
-#define to_skbedit(a) \
- container_of(a->priv, struct tcf_skbedit, common)
+#define to_skbedit(a) ((struct tcf_skbedit *)a)
/* Return true iff action is mark */
static inline bool is_tcf_skbedit_mark(const struct tc_action *a)
diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h
index 93b70ade1ff3..e29f52e8bdf1 100644
--- a/include/net/tc_act/tc_vlan.h
+++ b/include/net/tc_act/tc_vlan.h
@@ -16,12 +16,11 @@
#define VLAN_F_PUSH 0x2
struct tcf_vlan {
- struct tcf_common common;
+ struct tc_action common;
int tcfv_action;
u16 tcfv_push_vid;
__be16 tcfv_push_proto;
};
-#define to_vlan(a) \
- container_of(a->priv, struct tcf_vlan, common)
+#define to_vlan(a) ((struct tcf_vlan *)a)
#endif /* __NET_TC_VLAN_H */
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 47ec2305f920..e4a5f2607ffa 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -29,45 +29,43 @@
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_qstats);
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);
- hlist_del(&p->tcfc_head);
+ hlist_del(&p->tcfa_head);
spin_unlock_bh(&hinfo->lock);
- gen_kill_estimator(&p->tcfc_bstats,
- &p->tcfc_rate_est);
+ gen_kill_estimator(&p->tcfa_bstats,
+ &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
*/
- 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;
if (p) {
if (bind)
- p->tcfc_bindcnt--;
- else if (strict && p->tcfc_bindcnt > 0)
+ p->tcfa_bindcnt--;
+ else if (strict && p->tcfa_bindcnt > 0)
return -EPERM;
- p->tcfc_refcnt--;
- if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
- if (a->ops->cleanup)
- a->ops->cleanup(a, bind);
- tcf_hash_destroy(a->hinfo, a);
+ p->tcfa_refcnt--;
+ if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
+ if (p->ops->cleanup)
+ p->ops->cleanup(p, bind);
+ list_del(&p->list);
+ tcf_hash_destroy(p->hinfo, p);
ret = ACT_P_DELETED;
}
}
@@ -77,10 +75,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
EXPORT_SYMBOL(__tcf_hash_release);
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;
struct nlattr *nest;
@@ -89,19 +85,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
s_i = cb->args[0];
for (i = 0; i < (hinfo->hmask + 1); i++) {
+ struct hlist_head *head;
+ struct tc_action *p;
+
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++;
if (index < s_i)
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)
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) {
index--;
nlmsg_trim(skb, nest);
@@ -125,27 +122,27 @@ nla_put_failure:
}
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;
int i = 0, n_i = 0;
int ret = -EINVAL;
- nest = nla_nest_start(skb, a->order);
+ nest = nla_nest_start(skb, 0);
if (nest == NULL)
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;
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)];
- hlist_for_each_entry_safe(p, n, head, tcfc_head) {
- a->priv = p;
- ret = __tcf_hash_release(a, false, true);
+ hlist_for_each_entry_safe(p, n, head, tcfa_head) {
+ ret = __tcf_hash_release(p, false, true);
if (ret == ACT_P_DELETED) {
- module_put(a->ops->owner);
+ module_put(p->ops->owner);
n_i++;
} else if (ret < 0)
goto nla_put_failure;
@@ -163,16 +160,14 @@ nla_put_failure:
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type,
- struct tc_action *a)
+ const struct tc_action_ops *ops)
{
struct tcf_hashinfo *hinfo = tn->hinfo;
- a->hinfo = hinfo;
-
if (type == RTM_DELACTION) {
- return tcf_del_walker(hinfo, skb, a);
+ return tcf_del_walker(hinfo, skb, ops);
} else if (type == RTM_GETACTION) {
- return tcf_dump_walker(hinfo, skb, cb, a);
+ return tcf_dump_walker(hinfo, skb, cb);
} else {
WARN(1, "tcf_generic_walker: unknown action %d\n", type);
return -EINVAL;
@@ -180,15 +175,15 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
}
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;
spin_lock_bh(&hinfo->lock);
head = &hinfo->htab[tcf_hash(index, hinfo->hmask)];
- hlist_for_each_entry_rcu(p, head, tcfc_head)
- if (p->tcfc_index == index)
+ hlist_for_each_entry_rcu(p, head, tcfa_head)
+ if (p->tcfa_index == index)
break;
spin_unlock_bh(&hinfo->lock);
@@ -210,31 +205,30 @@ u32 tcf_hash_new_index(struct tc_action_net *tn)
}
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_common *p = tcf_hash_lookup(index, hinfo);
+ struct tc_action *p = tcf_hash_lookup(index, hinfo);
if (p) {
- a->priv = p;
- a->hinfo = hinfo;
+ *a = p;
return 1;
}
return 0;
}
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)
{
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 (bind)
- p->tcfc_bindcnt++;
- p->tcfc_refcnt++;
- a->priv = p;
- a->hinfo = hinfo;
+ p->tcfa_bindcnt++;
+ p->tcfa_refcnt++;
+ *a = p;
return true;
}
return false;
@@ -243,26 +237,26 @@ EXPORT_SYMBOL(tcf_hash_check);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
{
- struct tcf_common *pc = a->priv;
if (est)
- gen_kill_estimator(&pc->tcfc_bstats,
- &pc->tcfc_rate_est);
- call_rcu(&pc->tcfc_rcu, free_tcf);
+ gen_kill_estimator(&a->tcfa_bstats,
+ &a->tcfa_rate_est);
+ call_rcu(&a->tcfa_rcu, free_tcf);
}
EXPORT_SYMBOL(tcf_hash_cleanup);
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;
int err = -ENOMEM;
if (unlikely(!p))
return -ENOMEM;
- p->tcfc_refcnt = 1;
+ p->tcfa_refcnt = 1;
if (bind)
- p->tcfc_bindcnt = 1;
+ p->tcfa_bindcnt = 1;
if (cpustats) {
p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
@@ -278,36 +272,37 @@ err2:
goto err1;
}
}
- spin_lock_init(&p->tcfc_lock);
- INIT_HLIST_NODE(&p->tcfc_head);
- p->tcfc_index = index ? index : tcf_hash_new_index(tn);
- p->tcfc_tm.install = jiffies;
- p->tcfc_tm.lastuse = jiffies;
- p->tcfc_tm.firstuse = 0;
+ spin_lock_init(&p->tcfa_lock);
+ INIT_HLIST_NODE(&p->tcfa_head);
+ p->tcfa_index = index ? index : tcf_hash_new_index(tn);
+ p->tcfa_tm.install = jiffies;
+ p->tcfa_tm.lastuse = jiffies;
+ p->tcfa_tm.firstuse = 0;
if (est) {
- err = gen_new_estimator(&p->tcfc_bstats, p->cpu_bstats,
- &p->tcfc_rate_est,
- &p->tcfc_lock, NULL, est);
+ err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
+ &p->tcfa_rate_est,
+ &p->tcfa_lock, NULL, est);
if (err) {
free_percpu(p->cpu_qstats);
goto err2;
}
}
- a->priv = (void *) p;
- a->hinfo = hinfo;
+ p->hinfo = hinfo;
+ p->ops = ops;
+ INIT_LIST_HEAD(&p->list);
+ *a = p;
return 0;
}
EXPORT_SYMBOL(tcf_hash_create);
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;
- 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);
- hlist_add_head(&p->tcfc_head, &hinfo->htab[h]);
+ hlist_add_head(&a->tcfa_head, &hinfo->htab[h]);
spin_unlock_bh(&hinfo->lock);
}
EXPORT_SYMBOL(tcf_hash_insert);
@@ -315,21 +310,16 @@ EXPORT_SYMBOL(tcf_hash_insert);
void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
struct tcf_hashinfo *hinfo)
{
- struct tc_action a = {
- .ops = ops,
- .hinfo = hinfo,
- };
int i;
for (i = 0; i < hinfo->hmask + 1; i++) {
- struct tcf_common *p;
+ struct tc_action *p;
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;
- a.priv = p;
- ret = __tcf_hash_release(&a, false, true);
+ ret = __tcf_hash_release(p, false, true);
if (ret == ACT_P_DELETED)
module_put(ops->owner);
else if (ret < 0)
@@ -466,8 +456,6 @@ int tcf_action_destroy(struct list_head *actions, int bind)
module_put(a->ops->owner);
else if (ret < 0)
return ret;
- list_del(&a->list);
- kfree(a);
}
return ret;
}
@@ -581,20 +569,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
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 */
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
- err = a_o->init(net, nla, est, a, ovr, bind);
+ err = a_o->init(net, nla, est, &a, ovr, bind);
if (err < 0)
- goto err_free;
+ goto err_mod;
/* module count goes up only when brand new policy is created
* 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,
return a;
-err_free:
- kfree(a);
err_mod:
module_put(a_o->owner);
err_out:
@@ -642,12 +621,11 @@ 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 err = 0;
struct gnet_dump d;
- struct tcf_common *p = a->priv;
if (p == NULL)
goto errout;
@@ -656,27 +634,27 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
* to add additional backward compatibility statistic TLVs.
*/
if (compat_mode) {
- if (a->type == TCA_OLD_COMPAT)
+ if (p->type == TCA_OLD_COMPAT)
err = gnet_stats_start_copy_compat(skb, 0,
TCA_STATS,
TCA_XSTATS,
- &p->tcfc_lock, &d,
+ &p->tcfa_lock, &d,
TCA_PAD);
else
return 0;
} else
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)
goto errout;
- if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfc_bstats) < 0 ||
- gnet_stats_copy_rate_est(&d, &p->tcfc_bstats,
- &p->tcfc_rate_est) < 0 ||
+ if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
+ gnet_stats_copy_rate_est(&d, &p->tcfa_bstats,
+ &p->tcfa_rate_est) < 0 ||
gnet_stats_copy_queue(&d, p->cpu_qstats,
- &p->tcfc_qstats,
- p->tcfc_qstats.qlen) < 0)
+ &p->tcfa_qstats,
+ p->tcfa_qstats.qlen) < 0)
goto errout;
if (gnet_stats_finish_copy(&d) < 0)
@@ -740,24 +718,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
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,
struct nlmsghdr *n, u32 portid)
{
struct nlattr *tb[TCA_ACT_MAX + 1];
+ const struct tc_action_ops *ops;
struct tc_action *a;
int index;
int err;
@@ -772,26 +737,19 @@ static struct tc_acti