diff options
-rw-r--r-- | include/net/act_api.h | 52 | ||||
-rw-r--r-- | include/net/tc_act/tc_bpf.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_connmark.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_csum.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_defact.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_gact.h | 5 | ||||
-rw-r--r-- | include/net/tc_act/tc_ife.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_ipt.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_mirred.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_nat.h | 5 | ||||
-rw-r--r-- | include/net/tc_act/tc_pedit.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_skbedit.h | 3 | ||||
-rw-r--r-- | include/net/tc_act/tc_vlan.h | 3 | ||||
-rw-r--r-- | net/sched/act_api.c | 149 | ||||
-rw-r--r-- | net/sched/act_bpf.c | 26 | ||||
-rw-r--r-- | net/sched/act_connmark.c | 24 | ||||
-rw-r--r-- | net/sched/act_csum.c | 22 | ||||
-rw-r--r-- | net/sched/act_gact.c | 24 | ||||
-rw-r--r-- | net/sched/act_ife.c | 38 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 48 | ||||
-rw-r--r-- | net/sched/act_mirred.c | 26 | ||||
-rw-r--r-- | net/sched/act_nat.c | 22 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 28 | ||||
-rw-r--r-- | net/sched/act_police.c | 45 | ||||
-rw-r--r-- | net/sched/act_simple.c | 29 | ||||
-rw-r--r-- | net/sched/act_skbedit.c | 26 | ||||
-rw-r--r-- | net/sched/act_vlan.c | 28 |
27 files changed, 298 insertions, 329 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h index 0bb210635e5f..8b199095ea51 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -10,7 +10,26 @@ #include <net/net_namespace.h> #include <net/netns/generic.h> + +struct tcf_hashinfo { + struct hlist_head *htab; + unsigned int hmask; + spinlock_t lock; + 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 tcf_common { + struct tc_action tcfc_act; struct hlist_node tcfc_head; u32 tcfc_index; int tcfc_refcnt; @@ -26,6 +45,7 @@ struct tcf_common { struct gnet_stats_basic_cpu __percpu *cpu_bstats; struct gnet_stats_queue __percpu *cpu_qstats; }; +#define tcf_act common.tcfc_act #define tcf_head common.tcfc_head #define tcf_index common.tcfc_index #define tcf_refcnt common.tcfc_refcnt @@ -39,13 +59,6 @@ struct tcf_common { #define tcf_lock common.tcfc_lock #define tcf_rcu common.tcfc_rcu -struct tcf_hashinfo { - struct hlist_head *htab; - unsigned int hmask; - spinlock_t lock; - u32 index; -}; - static inline unsigned int tcf_hash(u32 index, unsigned int hmask) { return index & hmask; @@ -88,15 +101,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 +110,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 +157,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..80a4d6f49773 100644 --- a/include/net/tc_act/tc_bpf.h +++ b/include/net/tc_act/tc_bpf.h @@ -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..8a661135f4ac 100644 --- a/include/net/tc_act/tc_connmark.h +++ b/include/net/tc_act/tc_connmark.h @@ -9,7 +9,6 @@ struct tcf_connmark_info { 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..1a9ef15d573b 100644 --- a/include/net/tc_act/tc_csum.h +++ b/include/net/tc_act/tc_csum.h @@ -9,7 +9,6 @@ struct tcf_csum { 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..e25b4eb4fc66 100644 --- a/include/net/tc_act/tc_defact.h +++ b/include/net/tc_act/tc_defact.h @@ -8,7 +8,6 @@ struct tcf_defact { 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..119cdb418c23 100644 --- a/include/net/tc_act/tc_gact.h +++ b/include/net/tc_act/tc_gact.h @@ -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..7921abe42adc 100644 --- a/include/net/tc_act/tc_ife.h +++ b/include/net/tc_act/tc_ife.h @@ -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..c22ae7ab66ed 100644 --- a/include/net/tc_act/tc_ipt.h +++ b/include/net/tc_act/tc_ipt.h @@ -11,7 +11,6 @@ struct tcf_ipt { 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..89aebd22cd79 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h @@ -12,8 +12,7 @@ struct tcf_mirred { 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..a91ad3ad565e 100644 --- a/include/net/tc_act/tc_nat.h +++ b/include/net/tc_act/tc_nat.h @@ -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..2cccfbaae800 100644 --- a/include/net/tc_act/tc_pedit.h +++ b/include/net/tc_act/tc_pedit.h @@ -9,7 +9,6 @@ struct tcf_pedit { 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..9e0548998327 100644 --- a/include/net/tc_act/tc_skbedit.h +++ b/include/net/tc_act/tc_skbedit.h @@ -30,8 +30,7 @@ struct tcf_skbedit { 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..584b80788d52 100644 --- a/include/net/tc_act/tc_vlan.h +++ b/include/net/tc_act/tc_vlan.h @@ -21,7 +21,6 @@ struct tcf_vlan { 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..d97419f35e7e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -38,7 +38,7 @@ static void free_tcf(struct rcu_head *head) static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) { - struct tcf_common *p = a->priv; + struct tcf_common *p = (struct tcf_common *)a; spin_lock_bh(&hinfo->lock); hlist_del(&p->tcfc_head); @@ -54,7 +54,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) { - struct tcf_common *p = a->priv; + struct tcf_common *p = (struct tcf_common *)a; int ret = 0; if (p) { @@ -67,6 +67,7 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { if (a->ops->cleanup) a->ops->cleanup(a, bind); + list_del(&a->list); tcf_hash_destroy(a->hinfo, a); ret = ACT_P_DELETED; } @@ -77,10 +78,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 +88,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 tcf_common *p; + head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; hlist_for_each_entry_rcu(p, head, tcfc_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, (struct tc_action *)p, 0, 0); if (err < 0) { index--; nlmsg_trim(skb, nest); @@ -125,27 +125,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 tcf_common *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); + ret = __tcf_hash_release((struct tc_action *)p, false, true); if (ret == ACT_P_DELETED) { - module_put(a->ops->owner); + module_put(p->tcfc_act.ops->owner); n_i++; } else if (ret < 0) goto nla_put_failure; @@ -163,16 +163,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; @@ -210,21 +208,20 @@ 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); if (p) { - a->priv = p; - a->hinfo = hinfo; + *a = &p->tcfc_act; 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; @@ -233,8 +230,7 @@ bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, if (bind) p->tcfc_bindcnt++; p->tcfc_refcnt++; - a->priv = p; - a->hinfo = hinfo; + *a = &p->tcfc_act; return true; } return false; @@ -243,7 +239,7 @@ EXPORT_SYMBOL(tcf_hash_check); void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) { - struct tcf_common *pc = a->priv; + struct tcf_common *pc = (struct tcf_common *)a; if (est) gen_kill_estimator(&pc->tcfc_bstats, &pc->tcfc_rate_est); @@ -252,9 +248,10 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) 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 tcf_common *p = kzalloc(ops->size, GFP_KERNEL); struct tcf_hashinfo *hinfo = tn->hinfo; int err = -ENOMEM; @@ -294,15 +291,17 @@ err2: } } - a->priv = (void *) p; - a->hinfo = hinfo; + p->tcfc_act.hinfo = hinfo; + p->tcfc_act.ops = ops; + INIT_LIST_HEAD(&p->tcfc_act.list); + *a = &p->tcfc_act; 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_common *p = (struct tcf_common *)a; struct tcf_hashinfo *hinfo = tn->hinfo; unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); @@ -315,10 +314,6 @@ 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++) { @@ -328,8 +323,7 @@ void tcf_hashinfo_destroy(const struct tc_action_ops *ops, hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { int ret; - a.priv = p; - ret = __tcf_hash_release(&a, false, true); + ret = __tcf_hash_release((struct tc_action *)p, false, true); if (ret == ACT_P_DELETED) module_put(ops->owner); else if (ret < 0) @@ -466,8 +460,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 +573,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 +590,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: @@ -647,7 +630,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, { int err = 0; struct gnet_dump d; - struct tcf_common *p = a->priv; + struct tcf_common *p = (struct tcf_common *)a; if (p == NULL) goto errout; @@ -740,24 +723,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 +742,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, goto err_out; index = nla_get_u32(tb[TCA_ACT_INDEX]); - err = -ENOMEM; - a = create_a(0); - if (a == NULL) - goto err_out; - err = -EINVAL; - a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); - if (a->ops == NULL) /* could happen in batch of actions */ - goto err_free; + ops = tc_lookup_action(tb[TCA_ACT_KIND]); + if (!ops) /* could happen in batch of actions */ + goto err_out; err = -ENOENT; - if (a->ops->lookup(net, a, index) == 0) + if (ops->lookup(net, &a, index) == 0) goto err_mod; - module_put(a->ops->owner); + module_put(ops->owner); return a; err_mod: - module_put(a->ops->owner); -err_free: - kfree(a); + module_put(ops->owner); err_out: return ERR_PTR(err); } @@ -816,8 +779,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, struct netlink_callback dcb; struct nlattr *nest; struct nlattr *tb[TCA_ACT_MAX + 1]; + const struct tc_action_ops *ops; struct nlattr *kind; - struct tc_action a; int err = -ENOMEM; skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); @@ -834,10 +797,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, err = -EINVAL; kind = tb[TCA_ACT_KIND]; - memset(&a, 0, sizeof(struct tc_action)); - INIT_LIST_HEAD(&a.list); - a.ops = tc_lookup_action(kind); - if (a.ops == NULL) /*some idjot trying to flush unknown action */ + ops = tc_lookup_action(kind); + if (!ops) /*some idjot trying to flush unknown action */ goto err_out; nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, @@ -853,7 +814,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, if (nest == NULL) 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) goto out_module_put; if (err == 0) @@ -863,7 +824,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, nlh->nlmsg_len = skb_tail_pointer(skb) - b; nlh->nlmsg_flags |= NLM_F_ROOT; - module_put(a.ops->owner); + module_put(ops->owner); err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, n->nlmsg_flags & NLM_F_ECHO); if (err > 0) @@ -872,7 +833,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, return err; out_module_put: - module_put(a.ops->owner); + module_put(ops->owner); err_out: noflush_out: kfree_skb(skb); @@ -1084,7 +1045,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) unsigned char *b = skb_tail_pointer(skb); struct nlattr *nest; struct tc_action_ops *a_o; - struct tc_action a; int ret = 0; struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); struct nlattr *kind = find_dump_kind(cb->nlh); @@ -1098,9 +1058,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) if (a_o == NULL) 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, cb->nlh->nlmsg_type, sizeof(*t), 0); if (!nlh) @@ -1114,7 +1071,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) if (nest == NULL) 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) goto out_module_put; diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index ef74bffa6101..bfa870731e74 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -34,11 +34,12 @@ struct tcf_bpf_cfg { }; 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, struct tcf_result *res) { - struct tcf_bpf *prog = act->priv; + struct tcf_bpf *prog = to_bpf(act); struct bpf_prog *filter; int action, filter_res; 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, int bind, int ref) { 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 = { .index = prog->tcf_index, .refcnt = prog->tcf_refcnt - ref, @@ -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, - struct nlattr *est, struct tc_action *act, + struct nlattr *est, struct tc_action **act, int replace, int bind) { 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, if (!tcf_hash_check(tn, parm->index, act, bind)) { ret = tcf_hash_create(tn, parm->index, est, act, - sizeof(*prog), bind, true); + &act_bpf_ops, bind, true); if (ret < 0) return ret; @@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, if (bind) return 0; - tcf_hash_release(act, bind); + tcf_hash_release(*act, bind); if (!replace) return -EEXIST; } @@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, if (ret < 0) goto out; - prog = to_bpf(act); + prog = to_bpf(*act); ASSERT_RTNL(); if (res != ACT_P_CREATED) @@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, rcu_assign_pointer(prog->filter, cfg.filter); if (res == ACT_P_CREATED) { - tcf_hash_insert(tn, act); + tcf_hash_insert(tn, *act); } else { /* make sure the program being replaced is no longer executing */ synchronize_rcu(); @@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, return res; out: if (res == ACT_P_CREATED) - tcf_hash_cleanup(act, est); + tcf_hash_cleanup(*act, est); return ret; } @@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind) { 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); } static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, 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); - 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); @@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { .init = tcf_bpf_init, .walk = tcf_bpf_walker, .lookup = tcf_bpf_search, + .size = sizeof(struct tcf_bpf), }; static __net_init int bpf_init_net(struct net *net) diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 35a5270f289d..eae07a2e774d 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -31,6 +31,7 @@ #define CONNMARK_TAB_MASK 3 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, struct tcf_result *res) @@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, const struct nf_conntrack_tuple_hash *thash; struct nf_conntrack_tuple tuple; 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_conn *c; int proto; @@ -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, - struct nlattr *est, struct tc_action *a, + struct nlattr *est, struct tc_action **a, int ovr, int bind) { 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, if (!tcf_hash_check(tn, parm->index, a, bind)) { ret = tcf_hash_create(tn, parm->index, est, a, - sizeof(*ci), bind, false); + &act_connmark_ops, bind, false); if (ret) return ret; - ci = to_connmark(a); + ci = to_connmark(*a); ci->tcf_action = parm->action; ci->net = net; ci->zone = parm->zone; - tcf_hash_insert(tn, a); + tcf_hash_insert(tn, *a); ret = ACT_P_CREATED; } else { - ci = to_connmark(a); + ci = to_connmark(*a); if (bind) return 0; - tcf_hash_release(a, bind); + tcf_hash_release(*a, bind); if (!ovr) return -EEXIST; /* replacing action and zone */ @@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { 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 = { .index = ci->tcf_index, @@ -173,14 +174,14 @@ nla_put_failure: static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, 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); - 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); @@ -196,6 +197,7 @@ static struct tc_action_ |