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 @@ | |||
| 10 | #include <net/net_namespace.h> | 10 | #include <net/net_namespace.h> |
| 11 | #include <net/netns/generic.h> | 11 | #include <net/netns/generic.h> |
| 12 | 12 | ||
| 13 | |||
| 14 | struct tcf_hashinfo { | ||
| 15 | struct hlist_head *htab; | ||
| 16 | unsigned int hmask; | ||
| 17 | spinlock_t lock; | ||
| 18 | u32 index; | ||
| 19 | }; | ||
| 20 | |||
| 21 | struct tc_action_ops; | ||
| 22 | |||
| 23 | struct tc_action { | ||
| 24 | const struct tc_action_ops *ops; | ||
| 25 | __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ | ||
| 26 | __u32 order; | ||
| 27 | struct list_head list; | ||
| 28 | struct tcf_hashinfo *hinfo; | ||
| 29 | }; | ||
| 30 | |||
| 13 | struct tcf_common { | 31 | struct tcf_common { |
| 32 | struct tc_action tcfc_act; | ||
| 14 | struct hlist_node tcfc_head; | 33 | struct hlist_node tcfc_head; |
| 15 | u32 tcfc_index; | 34 | u32 tcfc_index; |
| 16 | int tcfc_refcnt; | 35 | int tcfc_refcnt; |
| @@ -26,6 +45,7 @@ struct tcf_common { | |||
| 26 | struct gnet_stats_basic_cpu __percpu *cpu_bstats; | 45 | struct gnet_stats_basic_cpu __percpu *cpu_bstats; |
| 27 | struct gnet_stats_queue __percpu *cpu_qstats; | 46 | struct gnet_stats_queue __percpu *cpu_qstats; |
| 28 | }; | 47 | }; |
| 48 | #define tcf_act common.tcfc_act | ||
| 29 | #define tcf_head common.tcfc_head | 49 | #define tcf_head common.tcfc_head |
| 30 | #define tcf_index common.tcfc_index | 50 | #define tcf_index common.tcfc_index |
| 31 | #define tcf_refcnt common.tcfc_refcnt | 51 | #define tcf_refcnt common.tcfc_refcnt |
| @@ -39,13 +59,6 @@ struct tcf_common { | |||
| 39 | #define tcf_lock common.tcfc_lock | 59 | #define tcf_lock common.tcfc_lock |
| 40 | #define tcf_rcu common.tcfc_rcu | 60 | #define tcf_rcu common.tcfc_rcu |
| 41 | 61 | ||
| 42 | struct tcf_hashinfo { | ||
| 43 | struct hlist_head *htab; | ||
| 44 | unsigned int hmask; | ||
| 45 | spinlock_t lock; | ||
| 46 | u32 index; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static inline unsigned int tcf_hash(u32 index, unsigned int hmask) | 62 | static inline unsigned int tcf_hash(u32 index, unsigned int hmask) |
| 50 | { | 63 | { |
| 51 | return index & hmask; | 64 | return index & hmask; |
| @@ -88,15 +101,6 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm) | |||
| 88 | dtm->expires = jiffies_to_clock_t(stm->expires); | 101 | dtm->expires = jiffies_to_clock_t(stm->expires); |
| 89 | } | 102 | } |
| 90 | 103 | ||
| 91 | struct tc_action { | ||
| 92 | void *priv; | ||
| 93 | const struct tc_action_ops *ops; | ||
| 94 | __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ | ||
| 95 | __u32 order; | ||
| 96 | struct list_head list; | ||
| 97 | struct tcf_hashinfo *hinfo; | ||
| 98 | }; | ||
| 99 | |||
| 100 | #ifdef CONFIG_NET_CLS_ACT | 104 | #ifdef CONFIG_NET_CLS_ACT |
| 101 | 105 | ||
| 102 | #define ACT_P_CREATED 1 | 106 | #define ACT_P_CREATED 1 |
| @@ -106,17 +110,18 @@ struct tc_action_ops { | |||
| 106 | struct list_head head; | 110 | struct list_head head; |
| 107 | char kind[IFNAMSIZ]; | 111 | char kind[IFNAMSIZ]; |
| 108 | __u32 type; /* TBD to match kind */ | 112 | __u32 type; /* TBD to match kind */ |
| 113 | size_t size; | ||
| 109 | struct module *owner; | 114 | struct module *owner; |
| 110 | int (*act)(struct sk_buff *, const struct tc_action *, | 115 | int (*act)(struct sk_buff *, const struct tc_action *, |
| 111 | struct tcf_result *); | 116 | struct tcf_result *); |
| 112 | int (*dump)(struct sk_buff *, struct tc_action *, int, int); | 117 | int (*dump)(struct sk_buff *, struct tc_action *, int, int); |
| 113 | void (*cleanup)(struct tc_action *, int bind); | 118 | void (*cleanup)(struct tc_action *, int bind); |
| 114 | int (*lookup)(struct net *, struct tc_action *, u32); | 119 | int (*lookup)(struct net *, struct tc_action **, u32); |
| 115 | int (*init)(struct net *net, struct nlattr *nla, | 120 | int (*init)(struct net *net, struct nlattr *nla, |
| 116 | struct nlattr *est, struct tc_action *act, int ovr, | 121 | struct nlattr *est, struct tc_action **act, int ovr, |
| 117 | int bind); | 122 | int bind); |
| 118 | int (*walk)(struct net *, struct sk_buff *, | 123 | int (*walk)(struct net *, struct sk_buff *, |
| 119 | struct netlink_callback *, int, struct tc_action *); | 124 | struct netlink_callback *, int, const struct tc_action_ops *); |
| 120 | void (*stats_update)(struct tc_action *, u64, u32, u64); | 125 | void (*stats_update)(struct tc_action *, u64, u32, u64); |
| 121 | }; | 126 | }; |
| 122 | 127 | ||
| @@ -152,13 +157,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn) | |||
| 152 | 157 | ||
| 153 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, | 158 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, |
| 154 | struct netlink_callback *cb, int type, | 159 | struct netlink_callback *cb, int type, |
| 155 | struct tc_action *a); | 160 | const struct tc_action_ops *ops); |
| 156 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index); | 161 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index); |
| 157 | u32 tcf_hash_new_index(struct tc_action_net *tn); | 162 | u32 tcf_hash_new_index(struct tc_action_net *tn); |
| 158 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, | 163 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a, |
| 159 | int bind); | 164 | int bind); |
| 160 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, | 165 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, |
| 161 | struct tc_action *a, int size, int bind, bool cpustats); | 166 | struct tc_action **a, const struct tc_action_ops *ops, int bind, |
| 167 | bool cpustats); | ||
| 162 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est); | 168 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est); |
| 163 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a); | 169 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a); |
| 164 | 170 | ||
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 { | |||
| 23 | struct sock_filter *bpf_ops; | 23 | struct sock_filter *bpf_ops; |
| 24 | const char *bpf_name; | 24 | const char *bpf_name; |
| 25 | }; | 25 | }; |
| 26 | #define to_bpf(a) \ | 26 | #define to_bpf(a) ((struct tcf_bpf *)a) |
| 27 | container_of(a->priv, struct tcf_bpf, common) | ||
| 28 | 27 | ||
| 29 | #endif /* __NET_TC_BPF_H */ | 28 | #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 { | |||
| 9 | u16 zone; | 9 | u16 zone; |
| 10 | }; | 10 | }; |
| 11 | 11 | ||
| 12 | #define to_connmark(a) \ | 12 | #define to_connmark(a) ((struct tcf_connmark_info *)a) |
| 13 | container_of(a->priv, struct tcf_connmark_info, common) | ||
| 14 | 13 | ||
| 15 | #endif /* __NET_TC_CONNMARK_H */ | 14 | #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 { | |||
| 9 | 9 | ||
| 10 | u32 update_flags; | 10 | u32 update_flags; |
| 11 | }; | 11 | }; |
| 12 | #define to_tcf_csum(a) \ | 12 | #define to_tcf_csum(a) ((struct tcf_csum *)a) |
| 13 | container_of(a->priv,struct tcf_csum,common) | ||
| 14 | 13 | ||
| 15 | #endif /* __NET_TC_CSUM_H */ | 14 | #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 { | |||
| 8 | u32 tcfd_datalen; | 8 | u32 tcfd_datalen; |
| 9 | void *tcfd_defdata; | 9 | void *tcfd_defdata; |
| 10 | }; | 10 | }; |
| 11 | #define to_defact(a) \ | 11 | #define to_defact(a) ((struct tcf_defact *)a) |
| 12 | container_of(a->priv, struct tcf_defact, common) | ||
| 13 | 12 | ||
| 14 | #endif /* __NET_TC_DEF_H */ | 13 | #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 { | |||
| 13 | atomic_t packets; | 13 | atomic_t packets; |
| 14 | #endif | 14 | #endif |
| 15 | }; | 15 | }; |
| 16 | #define to_gact(a) \ | 16 | #define to_gact(a) ((struct tcf_gact *)a) |
| 17 | container_of(a->priv, struct tcf_gact, common) | ||
| 18 | 17 | ||
| 19 | static inline bool is_tcf_gact_shot(const struct tc_action *a) | 18 | static inline bool is_tcf_gact_shot(const struct tc_action *a) |
| 20 | { | 19 | { |
| @@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a) | |||
| 24 | if (a->ops && a->ops->type != TCA_ACT_GACT) | 23 | if (a->ops && a->ops->type != TCA_ACT_GACT) |
| 25 | return false; | 24 | return false; |
| 26 | 25 | ||
| 27 | gact = a->priv; | 26 | gact = to_gact(a); |
| 28 | if (gact->tcf_action == TC_ACT_SHOT) | 27 | if (gact->tcf_action == TC_ACT_SHOT) |
| 29 | return true; | 28 | return true; |
| 30 | 29 | ||
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 { | |||
| 16 | /* list of metaids allowed */ | 16 | /* list of metaids allowed */ |
| 17 | struct list_head metalist; | 17 | struct list_head metalist; |
| 18 | }; | 18 | }; |
| 19 | #define to_ife(a) \ | 19 | #define to_ife(a) ((struct tcf_ife_info *)a) |
| 20 | container_of(a->priv, struct tcf_ife_info, common) | ||
| 21 | 20 | ||
| 22 | struct tcf_meta_info { | 21 | struct tcf_meta_info { |
| 23 | const struct tcf_meta_ops *ops; | 22 | 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 { | |||
| 11 | char *tcfi_tname; | 11 | char *tcfi_tname; |
| 12 | struct xt_entry_target *tcfi_t; | 12 | struct xt_entry_target *tcfi_t; |
| 13 | }; | 13 | }; |
| 14 | #define to_ipt(a) \ | 14 | #define to_ipt(a) ((struct tcf_ipt *)a) |
| 15 | container_of(a->priv, struct tcf_ipt, common) | ||
| 16 | 15 | ||
| 17 | #endif /* __NET_TC_IPT_H */ | 16 | #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 { | |||
| 12 | struct net_device __rcu *tcfm_dev; | 12 | struct net_device __rcu *tcfm_dev; |
| 13 | struct list_head tcfm_list; | 13 | struct list_head tcfm_list; |
| 14 | }; | 14 | }; |
| 15 | #define to_mirred(a) \ | 15 | #define to_mirred(a) ((struct tcf_mirred *)a) |
| 16 | container_of(a->priv, struct tcf_mirred, common) | ||
| 17 | 16 | ||
| 18 | static inline bool is_tcf_mirred_redirect(const struct tc_action *a) | 17 | static inline bool is_tcf_mirred_redirect(const struct tc_action *a) |
| 19 | { | 18 | { |
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 { | |||
| 13 | u32 flags; | 13 | u32 flags; |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | static inline struct tcf_nat *to_tcf_nat(struct tc_action *a) | 16 | #define to_tcf_nat(a) ((struct tcf_nat *)a) |
| 17 | { | ||
| 18 | return container_of(a->priv, struct tcf_nat, common); | ||
| 19 | } | ||
| 20 | 17 | ||
| 21 | #endif /* __NET_TC_NAT_H */ | 18 | #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 { | |||
| 9 | unsigned char tcfp_flags; | 9 | unsigned char tcfp_flags; |
| 10 | struct tc_pedit_key *tcfp_keys; | 10 | struct tc_pedit_key *tcfp_keys; |
| 11 | }; | 11 | }; |
| 12 | #define to_pedit(a) \ | 12 | #define to_pedit(a) ((struct tcf_pedit *)a) |
| 13 | container_of(a->priv, struct tcf_pedit, common) | ||
| 14 | 13 | ||
| 15 | #endif /* __NET_TC_PED_H */ | 14 | #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 { | |||
| 30 | u16 queue_mapping; | 30 | u16 queue_mapping; |
| 31 | u16 ptype; | 31 | u16 ptype; |
| 32 | }; | 32 | }; |
| 33 | #define to_skbedit(a) \ | 33 | #define to_skbedit(a) ((struct tcf_skbedit *)a) |
| 34 | container_of(a->priv, struct tcf_skbedit, common) | ||
| 35 | 34 | ||
| 36 | /* Return true iff action is mark */ | 35 | /* Return true iff action is mark */ |
| 37 | static inline bool is_tcf_skbedit_mark(const struct tc_action *a) | 36 | 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 { | |||
| 21 | u16 tcfv_push_vid; | 21 | u16 tcfv_push_vid; |
| 22 | __be16 tcfv_push_proto; | 22 | __be16 tcfv_push_proto; |
| 23 | }; | 23 | }; |
| 24 | #define to_vlan(a) \ | 24 | #define to_vlan(a) ((struct tcf_vlan *)a) |
| 25 | container_of(a->priv, struct tcf_vlan, common) | ||
| 26 | 25 | ||
| 27 | #endif /* __NET_TC_VLAN_H */ | 26 | #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) | |||
| 38 | 38 | ||
| 39 | static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) | 39 | static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) |
| 40 | { | 40 | { |
| 41 | struct tcf_common *p = a->priv; | 41 | struct tcf_common *p = (struct tcf_common *)a; |
| 42 | 42 | ||
| 43 | spin_lock_bh(&hinfo->lock); | 43 | spin_lock_bh(&hinfo->lock); |
| 44 | hlist_del(&p->tcfc_head); | 44 | hlist_del(&p->tcfc_head); |
| @@ -54,7 +54,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) | |||
| 54 | 54 | ||
| 55 | int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | 55 | int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) |
| 56 | { | 56 | { |
| 57 | struct tcf_common *p = a->priv; | 57 | struct tcf_common *p = (struct tcf_common *)a; |
| 58 | int ret = 0; | 58 | int ret = 0; |
| 59 | 59 | ||
| 60 | if (p) { | 60 | if (p) { |
| @@ -67,6 +67,7 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | |||
| 67 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { | 67 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { |
| 68 | if (a->ops->cleanup) | 68 | if (a->ops->cleanup) |
| 69 | a->ops->cleanup(a, bind); | 69 | a->ops->cleanup(a, bind); |
| 70 | list_del(&a->list); | ||
| 70 | tcf_hash_destroy(a->hinfo, a); | 71 | tcf_hash_destroy(a->hinfo, a); |
| 71 | ret = ACT_P_DELETED; | 72 | ret = ACT_P_DELETED; |
| 72 | } | 73 | } |
| @@ -77,10 +78,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | |||
| 77 | EXPORT_SYMBOL(__tcf_hash_release); | 78 | EXPORT_SYMBOL(__tcf_hash_release); |
| 78 | 79 | ||
| 79 | static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | 80 | static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, |
| 80 | struct netlink_callback *cb, struct tc_action *a) | 81 | struct netlink_callback *cb) |
| 81 | { | 82 | { |
| 82 | struct hlist_head *head; | ||
| 83 | struct tcf_common *p; | ||
| 84 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; | 83 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
| 85 | struct nlattr *nest; | 84 | struct nlattr *nest; |
| 86 | 85 | ||
| @@ -89,19 +88,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | |||
| 89 | s_i = cb->args[0]; | 88 | s_i = cb->args[0]; |
| 90 | 89 | ||
| 91 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 90 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
| 91 | struct hlist_head *head; | ||
| 92 | struct tcf_common *p; | ||
| 93 | |||
| 92 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 94 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
| 93 | 95 | ||
| 94 | hlist_for_each_entry_rcu(p, head, tcfc_head) { | 96 | hlist_for_each_entry_rcu(p, head, tcfc_head) { |
| 95 | index++; | 97 | index++; |
| 96 | if (index < s_i) | 98 | if (index < s_i) |
| 97 | continue; | 99 | continue; |
| 98 | a->priv = p; | ||
| 99 | a->order = n_i; | ||
| 100 | 100 | ||
| 101 | nest = nla_nest_start(skb, a->order); | 101 | nest = nla_nest_start(skb, n_i); |
| 102 | if (nest == NULL) | 102 | if (nest == NULL) |
| 103 | goto nla_put_failure; | 103 | goto nla_put_failure; |
| 104 | err = tcf_action_dump_1(skb, a, 0, 0); | 104 | err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 0); |
| 105 | if (err < 0) { | 105 | if (err < 0) { |
| 106 | index--; | 106 | index--; |
| 107 | nlmsg_trim(skb, nest); | 107 | nlmsg_trim(skb, nest); |
| @@ -125,27 +125,27 @@ nla_put_failure: | |||
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | 127 | static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, |
| 128 | struct tc_action *a) | 128 | const struct tc_action_ops *ops) |
| 129 | { | 129 | { |
| 130 | struct hlist_head *head; | ||
| 131 | struct hlist_node *n; | ||
| 132 | struct tcf_common *p; | ||
| 133 | struct nlattr *nest; | 130 | struct nlattr *nest; |
| 134 | int i = 0, n_i = 0; | 131 | int i = 0, n_i = 0; |
| 135 | int ret = -EINVAL; | 132 | int ret = -EINVAL; |
| 136 | 133 | ||
| 137 | nest = nla_nest_start(skb, a->order); | 134 | nest = nla_nest_start(skb, 0); |
| 138 | if (nest == NULL) | 135 | if (nest == NULL) |
| 139 | goto nla_put_failure; | 136 | goto nla_put_failure; |
| 140 | if (nla_put_string(skb, TCA_KIND, a->ops->kind)) | 137 | if (nla_put_string(skb, TCA_KIND, ops->kind)) |
| 141 | goto nla_put_failure; | 138 | goto nla_put_failure; |
| 142 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 139 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
| 140 | struct hlist_head *head; | ||
| 141 | struct hlist_node *n; | ||
| 142 | struct tcf_common *p; | ||
| 143 | |||
| 143 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 144 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
| 144 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { | 145 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { |
| 145 | a->priv = p; | 146 | ret = __tcf_hash_release((struct tc_action *)p, false, true); |
| 146 | ret = __tcf_hash_release(a, false, true); | ||
| 147 | if (ret == ACT_P_DELETED) { | 147 | if (ret == ACT_P_DELETED) { |
| 148 | module_put(a->ops->owner); | 148 | module_put(p->tcfc_act.ops->owner); |
| 149 | n_i++; | 149 | n_i++; |
| 150 | } else if (ret < 0) | 150 | } else if (ret < 0) |
| 151 | goto nla_put_failure; | 151 | goto nla_put_failure; |
| @@ -163,16 +163,14 @@ nla_put_failure: | |||
| 163 | 163 | ||
| 164 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, | 164 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, |
| 165 | struct netlink_callback *cb, int type, | 165 | struct netlink_callback *cb, int type, |
| 166 | struct tc_action *a) | 166 | const struct tc_action_ops *ops) |
| 167 | { | 167 | { |
| 168 | struct tcf_hashinfo *hinfo = tn->hinfo; | 168 | struct tcf_hashinfo *hinfo = tn->hinfo; |
| 169 | 169 | ||
| 170 | a->hinfo = hinfo; | ||
| 171 | |||
| 172 | if (type == RTM_DELACTION) { | 170 | if (type == RTM_DELACTION) { |
| 173 | return tcf_del_walker(hinfo, skb, a); | 171 | return tcf_del_walker(hinfo, skb, ops); |
| 174 | } else if (type == RTM_GETACTION) { | 172 | } else if (type == RTM_GETACTION) { |
| 175 | return tcf_dump_walker(hinfo, skb, cb, a); | 173 | return tcf_dump_walker(hinfo, skb, cb); |
| 176 | } else { | 174 | } else { |
| 177 | WARN(1, "tcf_generic_walker: unknown action %d\n", type); | 175 | WARN(1, "tcf_generic_walker: unknown action %d\n", type); |
| 178 | return -EINVAL; | 176 | return -EINVAL; |
| @@ -210,21 +208,20 @@ u32 tcf_hash_new_index(struct tc_action_net *tn) | |||
| 210 | } | 208 | } |
| 211 | EXPORT_SYMBOL(tcf_hash_new_index); | 209 | EXPORT_SYMBOL(tcf_hash_new_index); |
| 212 | 210 | ||
| 213 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index) | 211 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index) |
| 214 | { | 212 | { |
| 215 | struct tcf_hashinfo *hinfo = tn->hinfo; | 213 | struct tcf_hashinfo *hinfo = tn->hinfo; |
| 216 | struct tcf_common *p = tcf_hash_lookup(index, hinfo); | 214 | struct tcf_common *p = tcf_hash_lookup(index, hinfo); |
| 217 | 215 | ||
| 218 | if (p) { | 216 | if (p) { |
| 219 | a->priv = p; | 217 | *a = &p->tcfc_act; |
| 220 | a->hinfo = hinfo; | ||
| 221 | return 1; | 218 | return 1; |
| 222 | } | 219 | } |
| 223 | return 0; | 220 | return 0; |
| 224 | } | 221 | } |
| 225 | EXPORT_SYMBOL(tcf_hash_search); | 222 | EXPORT_SYMBOL(tcf_hash_search); |
| 226 | 223 | ||
| 227 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, | 224 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a, |
| 228 | int bind) | 225 | int bind) |
| 229 | { | 226 | { |
| 230 | struct tcf_hashinfo *hinfo = tn->hinfo; | 227 | 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, | |||
| 233 | if (bind) | 230 | if (bind) |
| 234 | p->tcfc_bindcnt++; | 231 | p->tcfc_bindcnt++; |
| 235 | p->tcfc_refcnt++; | 232 | p->tcfc_refcnt++; |
| 236 | a->priv = p; | 233 | *a = &p->tcfc_act; |
| 237 | a->hinfo = hinfo; | ||
| 238 | return true; | 234 | return true; |
| 239 | } | 235 | } |
| 240 | return false; | 236 | return false; |
| @@ -243,7 +239,7 @@ EXPORT_SYMBOL(tcf_hash_check); | |||
| 243 | 239 | ||
| 244 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) | 240 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) |
| 245 | { | 241 | { |
| 246 | struct tcf_common *pc = a->priv; | 242 | struct tcf_common *pc = (struct tcf_common *)a; |
| 247 | if (est) | 243 | if (est) |
| 248 | gen_kill_estimator(&pc->tcfc_bstats, | 244 | gen_kill_estimator(&pc->tcfc_bstats, |
| 249 | &pc->tcfc_rate_est); | 245 | &pc->tcfc_rate_est); |
| @@ -252,9 +248,10 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) | |||
| 252 | EXPORT_SYMBOL(tcf_hash_cleanup); | 248 | EXPORT_SYMBOL(tcf_hash_cleanup); |
| 253 | 249 | ||
| 254 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, | 250 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, |
| 255 | struct tc_action *a, int size, int bind, bool cpustats) | 251 | struct tc_action **a, const struct tc_action_ops *ops, |
| 252 | int bind, bool cpustats) | ||
| 256 | { | 253 | { |
| 257 | struct tcf_common *p = kzalloc(size, GFP_KERNEL); | 254 | struct tcf_common *p = kzalloc(ops->size, GFP_KERNEL); |
| 258 | struct tcf_hashinfo *hinfo = tn->hinfo; | 255 | struct tcf_hashinfo *hinfo = tn->hinfo; |
| 259 | int err = -ENOMEM; | 256 | int err = -ENOMEM; |
| 260 | 257 | ||
| @@ -294,15 +291,17 @@ err2: | |||
| 294 | } | 291 | } |
| 295 | } | 292 | } |
| 296 | 293 | ||
| 297 | a->priv = (void *) p; | 294 | p->tcfc_act.hinfo = hinfo; |
| 298 | a->hinfo = hinfo; | 295 | p->tcfc_act.ops = ops; |
| 296 | INIT_LIST_HEAD(&p->tcfc_act.list); | ||
| 297 | *a = &p->tcfc_act; | ||
| 299 | return 0; | 298 | return 0; |
| 300 | } | 299 | } |
| 301 | EXPORT_SYMBOL(tcf_hash_create); | 300 | EXPORT_SYMBOL(tcf_hash_create); |
| 302 | 301 | ||
| 303 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) | 302 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) |
| 304 | { | 303 | { |
| 305 | struct tcf_common *p = a->priv; | 304 | struct tcf_common *p = (struct tcf_common *)a; |
| 306 | struct tcf_hashinfo *hinfo = tn->hinfo; | 305 | struct tcf_hashinfo *hinfo = tn->hinfo; |
| 307 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); | 306 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); |
| 308 | 307 | ||
| @@ -315,10 +314,6 @@ EXPORT_SYMBOL(tcf_hash_insert); | |||
| 315 | void tcf_hashinfo_destroy(const struct tc_action_ops *ops, | 314 | void tcf_hashinfo_destroy(const struct tc_action_ops *ops, |
| 316 | struct tcf_hashinfo *hinfo) | 315 | struct tcf_hashinfo *hinfo) |
| 317 | { | 316 | { |
| 318 | struct tc_action a = { | ||
| 319 | .ops = ops, | ||
| 320 | .hinfo = hinfo, | ||
| 321 | }; | ||
| 322 | int i; | 317 | int i; |
| 323 | 318 | ||
| 324 | for (i = 0; i < hinfo->hmask + 1; i++) { | 319 | for (i = 0; i < hinfo->hmask + 1; i++) { |
| @@ -328,8 +323,7 @@ void tcf_hashinfo_destroy(const struct tc_action_ops *ops, | |||
| 328 | hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { | 323 | hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { |
| 329 | int ret; | 324 | int ret; |
| 330 | 325 | ||
| 331 | a.priv = p; | 326 | ret = __tcf_hash_release((struct tc_action *)p, false, true); |
| 332 | ret = __tcf_hash_release(&a, false, true); | ||
| 333 | if (ret == ACT_P_DELETED) | 327 | if (ret == ACT_P_DELETED) |
| 334 | module_put(ops->owner); | 328 | module_put(ops->owner); |
| 335 | else if (ret < 0) | 329 | else if (ret < 0) |
| @@ -466,8 +460,6 @@ int tcf_action_destroy(struct list_head *actions, int bind) | |||
| 466 | module_put(a->ops->owner); | 460 | module_put(a->ops->owner); |
| 467 | else if (ret < 0) | 461 | else if (ret < 0) |
| 468 | return ret; | 462 | return ret; |
| 469 | list_del(&a->list); | ||
| 470 | kfree(a); | ||
| 471 | } | 463 | } |
| 472 | return ret; | 464 | return ret; |
| 473 | } | 465 | } |
| @@ -581,20 +573,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, | |||
| 581 | goto err_out; | 573 | goto err_out; |
| 582 | } | 574 | } |
| 583 | 575 | ||
| 584 | err = -ENOMEM; | ||
| 585 | a = kzalloc(sizeof(*a), GFP_KERNEL); | ||
| 586 | if (a == NULL) | ||
| 587 | goto err_mod; | ||
| 588 | |||
| 589 | a->ops = a_o; | ||
| 590 | INIT_LIST_HEAD(&a->list); | ||
| 591 | /* backward compatibility for policer */ | 576 | /* backward compatibility for policer */ |
| 592 | if (name == NULL) | 577 | if (name == NULL) |
| 593 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind); | 578 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind); |
| 594 | else | 579 | else |
| 595 | err = a_o->init(net, nla, est, a, ovr, bind); | 580 | err = a_o->init(net, nla, est, &a, ovr, bind); |
| 596 | if (err < 0) | 581 | if (err < 0) |
| 597 | goto err_free; | 582 | goto err_mod; |
| 598 | 583 | ||
| 599 | /* module count goes up only when brand new policy is created | 584 | /* module count goes up only when brand new policy is created |
| 600 | * if it exists and is only bound to in a_o->init() then | 585 | * 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, | |||
| 605 | 590 | ||
| 606 | return a; | 591 | return a; |
| 607 | 592 | ||
| 608 | err_free: | ||
| 609 | kfree(a); | ||
| 610 | err_mod: | 593 | err_mod: |
| 611 | module_put(a_o->owner); | 594 | module_put(a_o->owner); |
| 612 | err_out: | 595 | err_out: |
| @@ -647,7 +630,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
| 647 | { | 630 | { |
| 648 | int err = 0; | 631 | int err = 0; |
| 649 | struct gnet_dump d; | 632 | struct gnet_dump d; |
| 650 | struct tcf_common *p = a->priv; | 633 | struct tcf_common *p = (struct tcf_common *)a; |
| 651 | 634 | ||
| 652 | if (p == NULL) | 635 | if (p == NULL) |
| 653 | goto errout; | 636 | goto errout; |
| @@ -740,24 +723,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, | |||
| 740 | return rtnl_unicast(skb, net, portid); | 723 | return rtnl_unicast(skb, net, portid); |
| 741 | } | 724 | } |
| 742 | 725 | ||
| 743 | static struct tc_action *create_a(int i) | ||
| 744 | { | ||
| 745 | struct tc_action *act; | ||
| 746 | |||
| 747 | act = kzalloc(sizeof(*act), GFP_KERNEL); | ||
| 748 | if (act == NULL) { | ||
| 749 | pr_debug("create_a: failed to alloc!\n"); | ||
| 750 | return NULL; | ||
| 751 | } | ||
| 752 | act->order = i; | ||
| 753 | INIT_LIST_HEAD(&act->list); | ||
| 754 | return act; | ||
| 755 | } | ||
| 756 | |||
| 757 | static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, | 726 | static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, |
| 758 | struct nlmsghdr *n, u32 portid) | 727 | struct nlmsghdr *n, u32 portid) |
| 759 | { | 728 | { |
| 760 | struct nlattr *tb[TCA_ACT_MAX + 1]; | 729 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
| 730 | const struct tc_action_ops *ops; | ||
| 761 | struct tc_action *a; | 731 | struct tc_action *a; |
| 762 | int index; | 732 | int index; |
| 763 | int err; | 733 | int err; |
| @@ -772,26 +742,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, | |||
| 772 | goto err_out; | 742 | goto err_out; |
| 773 | index = nla_get_u32(tb[TCA_ACT_INDEX]); | 743 | index = nla_get_u32(tb[TCA_ACT_INDEX]); |
| 774 | 744 | ||
| 775 | err = -ENOMEM; | ||
| 776 | a = create_a(0); | ||
| 777 | if (a == NULL) | ||
| 778 | goto err_out; | ||
| 779 | |||
| 780 | err = -EINVAL; | 745 | err = -EINVAL; |
| 781 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); | 746 | ops = tc_lookup_action(tb[TCA_ACT_KIND]); |
| 782 | if (a->ops == NULL) /* could happen in batch of actions */ | 747 | if (!ops) /* could happen in batch of actions */ |
| 783 | goto err_free; | 748 | goto err_out; |
| 784 | err = -ENOENT; | 749 | err = -ENOENT; |
| 785 | if (a->ops->lookup(net, a, index) == 0) | 750 | if (ops->lookup(net, &a, index) == 0) |
| 786 | goto err_mod; | 751 | goto err_mod; |
| 787 | 752 | ||
| 788 | module_put(a->ops->owner); | 753 | module_put(ops->owner); |
| 789 | return a; | 754 | return a; |
| 790 | 755 | ||
| 791 | err_mod: | 756 | err_mod: |
| 792 | module_put(a->ops->owner); | 757 | module_put(ops->owner); |
| 793 | err_free: | ||
| 794 | kfree(a); | ||
| 795 | err_out: | 758 | err_out: |
| 796 | return ERR_PTR(err); | 759 | return ERR_PTR(err); |
| 797 | } | 760 | } |
| @@ -816,8 +779,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 816 | struct netlink_callback dcb; | 779 | struct netlink_callback dcb; |
| 817 | struct nlattr *nest; | 780 | struct nlattr *nest; |
| 818 | struct nlattr *tb[TCA_ACT_MAX + 1]; | 781 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
| 782 | const struct tc_action_ops *ops; | ||
| 819 | struct nlattr *kind; | 783 | struct nlattr *kind; |
| 820 | struct tc_action a; | ||
| 821 | int err = -ENOMEM; | 784 | int err = -ENOMEM; |
| 822 | 785 | ||
| 823 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 786 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| @@ -834,10 +797,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 834 | 797 | ||
| 835 | err = -EINVAL; | 798 | err = -EINVAL; |
| 836 | kind = tb[TCA_ACT_KIND]; | 799 | kind = tb[TCA_ACT_KIND]; |
| 837 | memset(&a, 0, sizeof(struct tc_action)); | 800 | ops = tc_lookup_action(kind); |
| 838 | INIT_LIST_HEAD(&a.list); | 801 | if (!ops) /*some idjot trying to flush unknown action */ |
| 839 | a.ops = tc_lookup_action(kind); | ||
| 840 | if (a.ops == NULL) /*some idjot trying to flush unknown action */ | ||
| 841 | goto err_out; | 802 | goto err_out; |
| 842 | 803 | ||
| 843 | nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, | 804 | 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, | |||
| 853 | if (nest == NULL) | 814 | if (nest == NULL) |
| 854 | goto out_module_put; | 815 | goto out_module_put; |
| 855 | 816 | ||
| 856 | err = a.ops->walk(net, skb, &dcb, RTM_DELACTION, &a); | 817 | err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops); |
| 857 | if (err < 0) | 818 | if (err < 0) |
| 858 | goto out_module_put; | 819 | goto out_module_put; |
| 859 | if (err == 0) | 820 | if (err == 0) |
| @@ -863,7 +824,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 863 | 824 | ||
| 864 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 825 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
| 865 | nlh->nlmsg_flags |= NLM_F_ROOT; | 826 | nlh->nlmsg_flags |= NLM_F_ROOT; |
| 866 | module_put(a.ops->owner); | 827 | module_put(ops->owner); |
| 867 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, | 828 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, |
| 868 | n->nlmsg_flags & NLM_F_ECHO); | 829 | n->nlmsg_flags & NLM_F_ECHO); |
| 869 | if (err > 0) | 830 | if (err > 0) |
| @@ -872,7 +833,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 872 | return err; | 833 | return err; |
| 873 | 834 | ||
| 874 | out_module_put: | 835 | out_module_put: |
| 875 | module_put(a.ops->owner); | 836 | module_put(ops->owner); |
| 876 | err_out: | 837 | err_out: |
| 877 | noflush_out: | 838 | noflush_out: |
| 878 | kfree_skb(skb); | 839 | kfree_skb(skb); |
| @@ -1084,7 +1045,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1084 | unsigned char *b = skb_tail_pointer(skb); | 1045 | unsigned char *b = skb_tail_pointer(skb); |
| 1085 | struct nlattr *nest; | 1046 | struct nlattr *nest; |
| 1086 | struct tc_action_ops *a_o; | 1047 | struct tc_action_ops *a_o; |
| 1087 | struct tc_action a; | ||
| 1088 | int ret = 0; | 1048 | int ret = 0; |
| 1089 | struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); | 1049 | struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); |
| 1090 | struct nlattr *kind = find_dump_kind(cb->nlh); | 1050 | struct nlattr *kind = find_dump_kind(cb->nlh); |
| @@ -1098,9 +1058,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1098 | if (a_o == NULL) | 1058 | if (a_o == NULL) |
| 1099 | return 0; | 1059 | return 0; |
| 1100 | 1060 | ||
| 1101 | memset(&a, 0, sizeof(struct tc_action)); | ||
| 1102 | a.ops = a_o; | ||
| 1103 | |||
| 1104 | nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, | 1061 | nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
| 1105 | cb->nlh->nlmsg_type, sizeof(*t), 0); | 1062 | cb->nlh->nlmsg_type, sizeof(*t), 0); |
| 1106 | if (!nlh) | 1063 | if (!nlh) |
| @@ -1114,7 +1071,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1114 | if (nest == NULL) | 1071 | if (nest == NULL) |
| 1115 | goto out_module_put; | 1072 | goto out_module_put; |
| 1116 | 1073 | ||
| 1117 | ret = a_o->walk(net, skb, cb, RTM_GETACTION, &a); | 1074 | ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o); |
| 1118 | if (ret < 0) | 1075 | if (ret < 0) |
| 1119 | goto out_module_put; | 1076 | goto out_module_put; |
| 1120 | 1077 | ||
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 { | |||
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | static int bpf_net_id; | 36 | static int bpf_net_id; |
| 37 | static struct tc_action_ops act_bpf_ops; | ||
| 37 | 38 | ||
| 38 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, | 39 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, |
| 39 | struct tcf_result *res) | 40 | struct tcf_result *res) |
| 40 | { | 41 | { |
| 41 | struct tcf_bpf *prog = act->priv; | 42 | struct tcf_bpf *prog = to_bpf(act); |
| 42 | struct bpf_prog *filter; | 43 | struct bpf_prog *filter; |
| 43 | int action, filter_res; | 44 | int action, filter_res; |
| 44 | bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS; | 45 | 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 | int bind, int ref) | 135 | int bind, int ref) |
| 135 | { | 136 | { |
| 136 | unsigned char *tp = skb_tail_pointer(skb); | 137 | unsigned char *tp = skb_tail_pointer(skb); |
| 137 | struct tcf_bpf *prog = act->priv; | 138 | struct tcf_bpf *prog = to_bpf(act); |
| 138 | struct tc_act_bpf opt = { | 139 | struct tc_act_bpf opt = { |
| 139 | .index = prog->tcf_index, | 140 | .index = prog->tcf_index, |
| 140 | .refcnt = prog->tcf_refcnt - ref, | 141 | .refcnt = prog->tcf_refcnt - ref, |
| @@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog, | |||
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, | 273 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, |
| 273 | struct nlattr *est, struct tc_action *act, | 274 | struct nlattr *est, struct tc_action **act, |
| 274 | int replace, int bind) | 275 | int replace, int bind) |
| 275 | { | 276 | { |
| 276 | struct tc_action_net *tn = net_generic(net, bpf_net_id); | 277 | 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 | 296 | ||
| 296 | if (!tcf_hash_check(tn, parm->index, act, bind)) { | 297 | if (!tcf_hash_check(tn, parm->index, act, bind)) { |
| 297 | ret = tcf_hash_create(tn, parm->index, est, act, | 298 | ret = tcf_hash_create(tn, parm->index, est, act, |
| 298 | sizeof(*prog), bind, true); | 299 | &act_bpf_ops, bind, true); |
| 299 | if (ret < 0) | 300 | if (ret < 0) |
| 300 | return ret; | 301 | return ret; |
| 301 | 302 | ||
| @@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 305 | if (bind) | 306 | if (bind) |
| 306 | return 0; | 307 | return 0; |
| 307 | 308 | ||
| 308 | tcf_hash_release(act, bind); | 309 | tcf_hash_release(*act, bind); |
| 309 | if (!replace) | 310 | if (!replace) |
| 310 | return -EEXIST; | 311 | return -EEXIST; |
| 311 | } | 312 | } |
| @@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 325 | if (ret < 0) | 326 | if (ret < 0) |
| 326 | goto out; | 327 | goto out; |
| 327 | 328 | ||
| 328 | prog = to_bpf(act); | 329 | prog = to_bpf(*act); |
| 329 | ASSERT_RTNL(); | 330 | ASSERT_RTNL(); |
| 330 | 331 | ||
| 331 | if (res != ACT_P_CREATED) | 332 | if (res != ACT_P_CREATED) |
| @@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 343 | rcu_assign_pointer(prog->filter, cfg.filter); | 344 | rcu_assign_pointer(prog->filter, cfg.filter); |
| 344 | 345 | ||
| 345 | if (res == ACT_P_CREATED) { | 346 | if (res == ACT_P_CREATED) { |
| 346 | tcf_hash_insert(tn, act); | 347 | tcf_hash_insert(tn, *act); |
| 347 | } else { | 348 | } else { |
| 348 | /* make sure the program being replaced is no longer executing */ | 349 | /* make sure the program being replaced is no longer executing */ |
| 349 | synchronize_rcu(); | 350 | synchronize_rcu(); |
| @@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 353 | return res; | 354 | return res; |
| 354 | out: | 355 | out: |
| 355 | if (res == ACT_P_CREATED) | 356 | if (res == ACT_P_CREATED) |
| 356 | tcf_hash_cleanup(act, est); | 357 | tcf_hash_cleanup(*act, est); |
| 357 | 358 | ||
| 358 | return ret; | 359 | return ret; |
| 359 | } | 360 | } |
| @@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind) | |||
| 362 | { | 363 | { |
| 363 | struct tcf_bpf_cfg tmp; | 364 | struct tcf_bpf_cfg tmp; |
| 364 | 365 | ||
| 365 | tcf_bpf_prog_fill_cfg(act->priv, &tmp); | 366 | tcf_bpf_prog_fill_cfg(to_bpf(act), &tmp); |
| 366 | tcf_bpf_cfg_cleanup(&tmp); | 367 | tcf_bpf_cfg_cleanup(&tmp); |
| 367 | } | 368 | } |
| 368 | 369 | ||
| 369 | static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, | 370 | static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, |
| 370 | struct netlink_callback *cb, int type, | 371 | struct netlink_callback *cb, int type, |
| 371 | struct tc_action *a) | 372 | const struct tc_action_ops *ops) |
| 372 | { | 373 | { |
| 373 | struct tc_action_net *tn = net_generic(net, bpf_net_id); | 374 | struct tc_action_net *tn = net_generic(net, bpf_net_id); |
| 374 | 375 | ||
| 375 | return tcf_generic_walker(tn, skb, cb, type, a); | 376 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 376 | } | 377 | } |
| 377 | 378 | ||
| 378 | static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index) | 379 | static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index) |
| 379 | { | 380 | { |
| 380 | struct tc_action_net *tn = net_generic(net, bpf_net_id); | 381 | struct tc_action_net *tn = net_generic(net, bpf_net_id); |
| 381 | 382 | ||
| @@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { | |||
| 392 | .init = tcf_bpf_init, | 393 | .init = tcf_bpf_init, |
| 393 | .walk = tcf_bpf_walker, | 394 | .walk = tcf_bpf_walker, |
| 394 | .lookup = tcf_bpf_search, | 395 | .lookup = tcf_bpf_search, |
| 396 | .size = sizeof(struct tcf_bpf), | ||
| 395 | }; | 397 | }; |
| 396 | 398 | ||
| 397 | static __net_init int bpf_init_net(struct net *net) | 399 | 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 @@ | |||
| 31 | #define CONNMARK_TAB_MASK 3 | 31 | #define CONNMARK_TAB_MASK 3 |
| 32 | 32 | ||
| 33 | static int connmark_net_id; | 33 | static int connmark_net_id; |
| 34 | static struct tc_action_ops act_connmark_ops; | ||
| 34 | 35 | ||
| 35 | static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, | 36 | static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, |
| 36 | struct tcf_result *res) | 37 | struct tcf_result *res) |
| @@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, | |||
| 38 | const struct nf_conntrack_tuple_hash *thash; | 39 | const struct nf_conntrack_tuple_hash *thash; |
| 39 | struct nf_conntrack_tuple tuple; | 40 | struct nf_conntrack_tuple tuple; |
| 40 | enum ip_conntrack_info ctinfo; | 41 | enum ip_conntrack_info ctinfo; |
| 41 | struct tcf_connmark_info *ca = a->priv; | 42 | struct tcf_connmark_info *ca = to_connmark(a); |
| 42 | struct nf_conntrack_zone zone; | 43 | struct nf_conntrack_zone zone; |
| 43 | struct nf_conn *c; | 44 | struct nf_conn *c; |
| 44 | int proto; | 45 | int proto; |
| @@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { | |||
| 96 | }; | 97 | }; |
| 97 | 98 | ||
| 98 | static int tcf_connmark_init(struct net *net, struct nlattr *nla, | 99 | static int tcf_connmark_init(struct net *net, struct nlattr *nla, |
| 99 | struct nlattr *est, struct tc_action *a, | 100 | struct nlattr *est, struct tc_action **a, |
| 100 | int ovr, int bind) | 101 | int ovr, int bind) |
| 101 | { | 102 | { |
| 102 | struct tc_action_net *tn = net_generic(net, connmark_net_id); | 103 | 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 | 117 | ||
| 117 | if (!tcf_hash_check(tn, parm->index, a, bind)) { | 118 | if (!tcf_hash_check(tn, parm->index, a, bind)) { |
| 118 | ret = tcf_hash_create(tn, parm->index, est, a, | 119 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 119 | sizeof(*ci), bind, false); | 120 | &act_connmark_ops, bind, false); |
| 120 | if (ret) | 121 | if (ret) |
| 121 | return ret; | 122 | return ret; |
| 122 | 123 | ||
| 123 | ci = to_connmark(a); | 124 | ci = to_connmark(*a); |
| 124 | ci->tcf_action = parm->action; | 125 | ci->tcf_action = parm->action; |
| 125 | ci->net = net; | 126 | ci->net = net; |
| 126 | ci->zone = parm->zone; | 127 | ci->zone = parm->zone; |
| 127 | 128 | ||
| 128 | tcf_hash_insert(tn, a); | 129 | tcf_hash_insert(tn, *a); |
| 129 | ret = ACT_P_CREATED; | 130 | ret = ACT_P_CREATED; |
| 130 | } else { | 131 | } else { |
| 131 | ci = to_connmark(a); | 132 | ci = to_connmark(*a); |
| 132 | if (bind) | 133 | if (bind) |
| 133 | return 0; | 134 | return 0; |
| 134 | tcf_hash_release(a, bind); | 135 | tcf_hash_release(*a, bind); |
| 135 | if (!ovr) | 136 | if (!ovr) |
| 136 | return -EEXIST; | 137 | return -EEXIST; |
| 137 | /* replacing action and zone */ | 138 | /* replacing action and zone */ |
| @@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 146 | int bind, int ref) | 147 | int bind, int ref) |
| 147 | { | 148 | { |
| 148 | unsigned char *b = skb_tail_pointer(skb); | 149 | unsigned char *b = skb_tail_pointer(skb); |
| 149 | struct tcf_connmark_info *ci = a->priv; | 150 | struct tcf_connmark_info *ci = to_connmark(a); |
| 150 | 151 | ||
| 151 | struct tc_connmark opt = { | 152 | struct tc_connmark opt = { |
| 152 | .index = ci->tcf_index, | 153 | .index = ci->tcf_index, |
| @@ -173,14 +174,14 @@ nla_put_failure: | |||
| 173 | 174 | ||
| 174 | static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, | 175 | static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, |
| 175 | struct netlink_callback *cb, int type, | 176 | struct netlink_callback *cb, int type, |
| 176 | struct tc_action *a) | 177 | const struct tc_action_ops *ops) |
| 177 | { | 178 | { |
| 178 | struct tc_action_net *tn = net_generic(net, connmark_net_id); | 179 | struct tc_action_net *tn = net_generic(net, connmark_net_id); |
| 179 | 180 | ||
| 180 | return tcf_generic_walker(tn, skb, cb, type, a); | 181 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) | 184 | static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index) |
| 184 | { | 185 | { |
| 185 | struct tc_action_net *tn = net_generic(net, connmark_net_id); | 186 | struct tc_action_net *tn = net_generic(net, connmark_net_id); |
| 186 | 187 | ||
| @@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = { | |||
| 196 | .init = tcf_connmark_init, | 197 | .init = tcf_connmark_init, |
| 197 | .walk = tcf_connmark_walker, | 198 | .walk = tcf_connmark_walker, |
| 198 | .lookup = tcf_connmark_search, | 199 | .lookup = tcf_connmark_search, |
| 200 | .size = sizeof(struct tcf_connmark_info), | ||
| 199 | }; | 201 | }; |
| 200 | 202 | ||
| 201 | static __net_init int connmark_init_net(struct net *net) | 203 | static __net_init int connmark_init_net(struct net *net) |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index dcd9ababd351..b5dbf633a863 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
| @@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { | |||
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | static int csum_net_id; | 45 | static int csum_net_id; |
| 46 | static struct tc_action_ops act_csum_ops; | ||
| 46 | 47 | ||
| 47 | static int tcf_csum_init(struct net *net, struct nlattr *nla, | 48 | static int tcf_csum_init(struct net *net, struct nlattr *nla, |
| 48 | struct nlattr *est, struct tc_action *a, int ovr, | 49 | struct nlattr *est, struct tc_action **a, int ovr, |
| 49 | int bind) | 50 | int bind) |
| 50 | { | 51 | { |
| 51 | struct tc_action_net *tn = net_generic(net, csum_net_id); | 52 | 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 | 68 | ||
| 68 | if (!tcf_hash_check(tn, parm->index, a, bind)) { | 69 | if (!tcf_hash_check(tn, parm->index, a, bind)) { |
| 69 | ret = tcf_hash_create(tn, parm->index, est, a, | 70 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 70 | sizeof(*p), bind, false); | 71 | &act_csum_ops, bind, false); |
| 71 | if (ret) | 72 | if (ret) |
| 72 | return ret; | 73 | return ret; |
| 73 | ret = ACT_P_CREATED; | 74 | ret = ACT_P_CREATED; |
| 74 | } else { | 75 | } else { |
| 75 | if (bind)/* dont override defaults */ | 76 | if (bind)/* dont override defaults */ |
| 76 | return 0; | 77 | return 0; |
| 77 | tcf_hash_release(a, bind); | 78 | tcf_hash_release(*a, bind); |
| 78 | if (!ovr) | 79 | if (!ovr) |
| 79 | return -EEXIST; | 80 | return -EEXIST; |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | p = to_tcf_csum(a); | 83 | p = to_tcf_csum(*a); |
| 83 | spin_lock_bh(&p->tcf_lock); | 84 | spin_lock_bh(&p->tcf_lock); |
| 84 | p->tcf_action = parm->action; | 85 | p->tcf_action = parm->action; |
| 85 | p->update_flags = parm->update_flags; | 86 | p->update_flags = parm->update_flags; |
| 86 | spin_unlock_bh(&p->tcf_lock); | 87 | spin_unlock_bh(&p->tcf_lock); |
| 87 | 88 | ||
| 88 | if (ret == ACT_P_CREATED) | 89 | if (ret == ACT_P_CREATED) |
| 89 | tcf_hash_insert(tn, a); | 90 | tcf_hash_insert(tn, *a); |
| 90 | 91 | ||
| 91 | return ret; | 92 | return ret; |
| 92 | } | 93 | } |
| @@ -496,7 +497,7 @@ fail: | |||
| 496 | static int tcf_csum(struct sk_buff *skb, | 497 | static int tcf_csum(struct sk_buff *skb, |
| 497 | const struct tc_action *a, struct tcf_result *res) | 498 | const struct tc_action *a, struct tcf_result *res) |
| 498 | { | 499 | { |
| 499 | struct tcf_csum *p = a->priv; | 500 | struct tcf_csum *p = to_tcf_csum(a); |
| 500 | int action; | 501 | int action; |
| 501 | u32 update_flags; | 502 | u32 update_flags; |
| 502 | 503 | ||
| @@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb, | |||
| 534 | struct tc_action *a, int bind, int ref) | 535 | struct tc_action *a, int bind, int ref) |
| 535 | { | 536 | { |
| 536 | unsigned char *b = skb_tail_pointer(skb); | 537 | unsigned char *b = skb_tail_pointer(skb); |
| 537 | struct tcf_csum *p = a->priv; | 538 | struct tcf_csum *p = to_tcf_csum(a); |
| 538 | struct tc_csum opt = { | 539 | struct tc_csum opt = { |
| 539 | .update_flags = p->update_flags, | 540 | .update_flags = p->update_flags, |
| 540 | .index = p->tcf_index, | 541 | .index = p->tcf_index, |
| @@ -560,14 +561,14 @@ nla_put_failure: | |||
| 560 | 561 | ||
| 561 | static int tcf_csum_walker(struct net *net, struct sk_buff *skb, | 562 | static int tcf_csum_walker(struct net *net, struct sk_buff *skb, |
| 562 | struct netlink_callback *cb, int type, | 563 | struct netlink_callback *cb, int type, |
| 563 | struct tc_action *a) | 564 | const struct tc_action_ops *ops) |
| 564 | { | 565 | { |
| 565 | struct tc_action_net *tn = net_generic(net, csum_net_id); | 566 | struct tc_action_net *tn = net_generic(net, csum_net_id); |
| 566 | 567 | ||
| 567 | return tcf_generic_walker(tn, skb, cb, type, a); | 568 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 568 | } | 569 | } |
| 569 | 570 | ||
| 570 | static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index) | 571 | static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index) |
| 571 | { | 572 | { |
| 572 | struct tc_action_net *tn = net_generic(net, csum_net_id); | 573 | struct tc_action_net *tn = net_generic(net, csum_net_id); |
| 573 | 574 | ||
| @@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = { | |||
| 583 | .init = tcf_csum_init, | 584 | .init = tcf_csum_init, |
| 584 | .walk = tcf_csum_walker, | 585 | .walk = tcf_csum_walker, |
| 585 | .lookup = tcf_csum_search, | 586 | .lookup = tcf_csum_search, |
| 587 | .size = sizeof(struct tcf_csum), | ||
| 586 | }; | 588 | }; |
| 587 | 589 | ||
| 588 | static __net_init int csum_init_net(struct net *net) | 590 | static __net_init int csum_init_net(struct net *net) |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 19058a7f3e5c..e24a4093d6f6 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #define GACT_TAB_MASK 15 | 26 | #define GACT_TAB_MASK 15 |
| 27 | 27 | ||
| 28 | static int gact_net_id; | 28 | static int gact_net_id; |
| 29 | static struct tc_action_ops act_gact_ops; | ||
| 29 | 30 | ||
| 30 | #ifdef CONFIG_GACT_PROB | 31 | #ifdef CONFIG_GACT_PROB |
| 31 | static int gact_net_rand(struct tcf_gact *gact) | 32 | 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 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | static int tcf_gact_init(struct net *net, struct nlattr *nla, | 59 | static int tcf_gact_init(struct net *net, struct nlattr *nla, |
| 59 | struct nlattr *est, struct tc_action *a, | 60 | struct nlattr *est, struct tc_action **a, |
| 60 | int ovr, int bind) | 61 | int ovr, int bind) |
| 61 | { | 62 | { |
| 62 | struct tc_action_net *tn = net_generic(net, gact_net_id); | 63 | 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 | 94 | ||
| 94 | if (!tcf_hash_check(tn, parm->index, a, bind)) { | 95 | if (!tcf_hash_check(tn, parm->index, a, bind)) { |
| 95 | ret = tcf_hash_create(tn, parm->index, est, a, | 96 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 96 | sizeof(*gact), bind, true); | 97 | &act_gact_ops, bind, true); |
| 97 | if (ret) | 98 | if (ret) |
| 98 | return ret; | 99 | return ret; |
| 99 | ret = ACT_P_CREATED; | 100 | ret = ACT_P_CREATED; |
| 100 | } else { | 101 | } else { |
| 101 | if (bind)/* dont override defaults */ | 102 | if (bind)/* dont override defaults */ |
| 102 | return 0; | 103 | return 0; |
| 103 | tcf_hash_release(a, bind); | 104 | tcf_hash_release(*a, bind); |
| 104 | if (!ovr) | 105 | if (!ovr) |
| 105 | return -EEXIST; | 106 | return -EEXIST; |
| 106 | } | 107 | } |
| 107 | 108 | ||
| 108 | gact = to_gact(a); | 109 | gact = to_gact(*a); |
| 109 | 110 | ||
| 110 | ASSERT_RTNL(); | 111 | ASSERT_RTNL(); |
| 111 | gact->tcf_action = parm->action; | 112 | gact->tcf_action = parm->action; |
| @@ -121,14 +122,14 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 121 | } | 122 | } |
| 122 | #endif | 123 | #endif |
| 123 | if (ret == ACT_P_CREATED) | 124 | if (ret == ACT_P_CREATED) |
| 124 | tcf_hash_insert(tn, a); | 125 | tcf_hash_insert(tn, *a); |
| 125 | return ret; | 126 | return ret; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, | 129 | static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, |
| 129 | struct tcf_result *res) | 130 | struct tcf_result *res) |
| 130 | { | 131 | { |
| 131 | struct tcf_gact *gact = a->priv; | 132 | struct tcf_gact *gact = to_gact(a); |
| 132 | int action = READ_ONCE(gact->tcf_action); | 133 | int action = READ_ONCE(gact->tcf_action); |
| 133 | 134 | ||
| 134 | #ifdef CONFIG_GACT_PROB | 135 | #ifdef CONFIG_GACT_PROB |
| @@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, | |||
| 151 | static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, | 152 | static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, |
| 152 | u64 lastuse) | 153 | u64 lastuse) |
| 153 | { | 154 | { |
| 154 | struct tcf_gact *gact = a->priv; | 155 | struct tcf_gact *gact = to_gact(a); |
| 155 | int action = READ_ONCE(gact->tcf_action); | 156 | int action = READ_ONCE(gact->tcf_action); |
| 156 | struct tcf_t *tm = &gact->tcf_tm; | 157 | struct tcf_t *tm = &gact->tcf_tm; |
| 157 | 158 | ||
| @@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 166 | int bind, int ref) | 167 | int bind, int ref) |
| 167 | { | 168 | { |
| 168 | unsigned char *b = skb_tail_pointer(skb); | 169 | unsigned char *b = skb_tail_pointer(skb); |
| 169 | struct tcf_gact *gact = a->priv; | 170 | struct tcf_gact *gact = to_gact(a); |
| 170 | struct tc_gact opt = { | 171 | struct tc_gact opt = { |
| 171 | .index = gact->tcf_index, | 172 | .index = gact->tcf_index, |
| 172 | .refcnt = gact->tcf_refcnt - ref, | 173 | .refcnt = gact->tcf_refcnt - ref, |
| @@ -201,14 +202,14 @@ nla_put_failure: | |||
| 201 | 202 | ||
| 202 | static int tcf_gact_walker(struct net *net, struct sk_buff *skb, | 203 | static int tcf_gact_walker(struct net *net, struct sk_buff *skb, |
| 203 | struct netlink_callback *cb, int type, | 204 | struct netlink_callback *cb, int type, |
| 204 | struct tc_action *a) | 205 | const struct tc_action_ops *ops) |
| 205 | { | 206 | { |
| 206 | struct tc_action_net *tn = net_generic(net, gact_net_id); | 207 | struct tc_action_net *tn = net_generic(net, gact_net_id); |
| 207 | 208 | ||
| 208 | return tcf_generic_walker(tn, skb, cb, type, a); | 209 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index) | 212 | static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index) |
| 212 | { | 213 | { |
| 213 | struct tc_action_net *tn = net_generic(net, gact_net_id); | 214 | struct tc_action_net *tn = net_generic(net, gact_net_id); |
| 214 | 215 | ||
| @@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = { | |||
| 225 | .init = tcf_gact_init, | 226 | .init = tcf_gact_init, |
| 226 | .walk = tcf_gact_walker, | 227 | .walk = tcf_gact_walker, |
| 227 | .lookup = tcf_gact_search, | 228 | .lookup = tcf_gact_search, |
| 229 | .size = sizeof(struct tcf_gact), | ||
| 228 | }; | 230 | }; |
| 229 | 231 | ||
| 230 | static __net_init int gact_init_net(struct net *net) | 232 | static __net_init int gact_init_net(struct net *net) |
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 845ab5119c05..141a06eeb1e5 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | static int ife_net_id; | 38 | static int ife_net_id; |
| 39 | static int max_metacnt = IFE_META_MAX + 1; | 39 | static int max_metacnt = IFE_META_MAX + 1; |
| 40 | static struct tc_action_ops act_ife_ops; | ||
| 40 | 41 | ||
| 41 | static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { | 42 | static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { |
| 42 | [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, | 43 | [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, |
| @@ -364,7 +365,7 @@ out_nlmsg_trim: | |||
| 364 | /* under ife->tcf_lock */ | 365 | /* under ife->tcf_lock */ |
| 365 | static void _tcf_ife_cleanup(struct tc_action *a, int bind) | 366 | static void _tcf_ife_cleanup(struct tc_action *a, int bind) |
| 366 | { | 367 | { |
| 367 | struct tcf_ife_info *ife = a->priv; | 368 | struct tcf_ife_info *ife = to_ife(a); |
| 368 | struct tcf_meta_info *e, *n; | 369 | struct tcf_meta_info *e, *n; |
| 369 | 370 | ||
| 370 | list_for_each_entry_safe(e, n, &ife->metalist, metalist) { | 371 | 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 | 383 | ||
| 383 | static void tcf_ife_cleanup(struct tc_action *a, int bind) | 384 | static void tcf_ife_cleanup(struct tc_action *a, int bind) |
| 384 | { | 385 | { |
| 385 | struct tcf_ife_info *ife = a->priv; | 386 | struct tcf_ife_info *ife = to_ife(a); |
| 386 | 387 | ||
| 387 | spin_lock_bh(&ife->tcf_lock); | 388 | spin_lock_bh(&ife->tcf_lock); |
| 388 | _tcf_ife_cleanup(a, bind); | 389 | _tcf_ife_cleanup(a, bind); |
| @@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, | |||
| 417 | } | 418 | } |
| 418 | 419 | ||
| 419 | static int tcf_ife_init(struct net *net, struct nlattr *nla, | 420 | static int tcf_ife_init(struct net *net, struct nlattr *nla, |
| 420 | struct nlattr *est, struct tc_action *a, | 421 | struct nlattr *est, struct tc_action **a, |
| 421 | int ovr, int bind) | 422 | int ovr, int bind) |
| 422 | { | 423 | { |
| 423 | struct tc_action_net *tn = net_generic(net, ife_net_id); | 424 | 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 | **/ | 452 | **/ |
| 452 | if (!tb[TCA_IFE_TYPE]) { | 453 | if (!tb[TCA_IFE_TYPE]) { |
| 453 | if (exists) | 454 | if (exists) |
| 454 | tcf_hash_release(a, bind); | 455 | tcf_hash_release(*a, bind); |
| 455 | pr_info("You MUST pass etherype for encoding\n"); | 456 | pr_info("You MUST pass etherype for encoding\n"); |
| 456 | return -EINVAL; | 457 | return -EINVAL; |
| 457 | } | 458 | } |
| 458 | } | 459 | } |
| 459 | 460 | ||
| 460 | if (!exists) { | 461 | if (!exists) { |
| 461 | ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), | 462 | ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops, |
| 462 | bind, false); | 463 | bind, false); |
| 463 | if (ret) | 464 | if (ret) |
| 464 | return ret; | 465 | return ret; |
| 465 | ret = ACT_P_CREATED; | 466 | ret = ACT_P_CREATED; |
| 466 | } else { | 467 | } else { |
| 467 | tcf_hash_release(a, bind); | 468 | tcf_hash_release(*a, bind); |
| 468 | if (!ovr) | 469 | if (!ovr) |
| 469 | return -EEXIST; | 470 | return -EEXIST; |
| 470 | } | 471 | } |
| 471 | 472 | ||
| 472 | ife = to_ife(a); | 473 | ife = to_ife(*a); |
| 473 | ife->flags = parm->flags; | 474 | ife->flags = parm->flags; |
| 474 | 475 | ||
| 475 | if (parm->flags & IFE_ENCODE) { | 476 | if (parm->flags & IFE_ENCODE) { |
| @@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 507 | if (err) { | 508 | if (err) { |
| 508 | metadata_parse_err: | 509 | metadata_parse_err: |
| 509 | if (exists) | 510 | if (exists) |
| 510 | tcf_hash_release(a, bind); | 511 | tcf_hash_release(*a, bind); |
| 511 | if (ret == ACT_P_CREATED) | 512 | if (ret == ACT_P_CREATED) |
| 512 | _tcf_ife_cleanup(a, bind); | 513 | _tcf_ife_cleanup(*a, bind); |
| 513 | 514 | ||
| 514 | if (exists) | 515 | if (exists) |
| 515 | spin_unlock_bh(&ife->tcf_lock); | 516 | spin_unlock_bh(&ife->tcf_lock); |
| @@ -529,7 +530,7 @@ metadata_parse_err: | |||
| 529 | err = use_all_metadata(ife); | 530 | err = use_all_metadata(ife); |
| 530 | if (err) { | 531 | if (err) { |
| 531 | if (ret == ACT_P_CREATED) | 532 | if (ret == ACT_P_CREATED) |
| 532 | _tcf_ife_cleanup(a, bind); | 533 | _tcf_ife_cleanup(*a, bind); |
| 533 | 534 | ||
| 534 | if (exists) | 535 | if (exists) |
| 535 | spin_unlock_bh(&ife->tcf_lock); | 536 | spin_unlock_bh(&ife->tcf_lock); |
| @@ -541,7 +542,7 @@ metadata_parse_err: | |||
| 541 | spin_unlock_bh(&ife->tcf_lock); | 542 | spin_unlock_bh(&ife->tcf_lock); |
| 542 | 543 | ||
| 543 | if (ret == ACT_P_CREATED) | 544 | if (ret == ACT_P_CREATED) |
| 544 | tcf_hash_insert(tn, a); | 545 | tcf_hash_insert(tn, *a); |
| 545 | 546 | ||
| 546 | return ret; | 547 | return ret; |
| 547 | } | 548 | } |
| @@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
| 550 | int ref) | 551 | int ref) |
| 551 | { | 552 | { |
| 552 | unsigned char *b = skb_tail_pointer(skb); | 553 | unsigned char *b = skb_tail_pointer(skb); |
| 553 | struct tcf_ife_info *ife = a->priv; | 554 | struct tcf_ife_info *ife = to_ife(a); |
| 554 | struct tc_ife opt = { | 555 | struct tc_ife opt = { |
| 555 | .index = ife->tcf_index, | 556 | .index = ife->tcf_index, |
| 556 | .refcnt = ife->tcf_refcnt - ref, | 557 | .refcnt = ife->tcf_refcnt - ref, |
| @@ -623,7 +624,7 @@ struct meta_tlvhdr { | |||
| 623 | static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, | 624 | static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, |
| 624 | struct tcf_result *res) | 625 | struct tcf_result *res) |
| 625 | { | 626 | { |
| 626 | struct tcf_ife_info *ife = a->priv; | 627 | struct tcf_ife_info *ife = to_ife(a); |
| 627 | int action = ife->tcf_action; | 628 | int action = ife->tcf_action; |
| 628 | struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; | 629 | struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; |
| 629 | u16 ifehdrln = ifehdr->metalen; | 630 | u16 ifehdrln = ifehdr->metalen; |
| @@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife) | |||
| 695 | static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, | 696 | static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, |
| 696 | struct tcf_result *res) | 697 | struct tcf_result *res) |
| 697 | { | 698 | { |
| 698 | struct tcf_ife_info *ife = a->priv; | 699 | struct tcf_ife_info *ife = to_ife(a); |
| 699 | int action = ife->tcf_action; | 700 | int action = ife->tcf_action; |
| 700 | struct ethhdr *oethh; /* outer ether header */ | 701 | struct ethhdr *oethh; /* outer ether header */ |
| 701 | struct ethhdr *iethh; /* inner eth header */ | 702 | 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 | static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, | 800 | static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, |
| 800 | struct tcf_result *res) | 801 | struct tcf_result *res) |
| 801 | { | 802 | { |
| 802 | struct tcf_ife_info *ife = a->priv; | 803 | struct tcf_ife_info *ife = to_ife(a); |
| 803 | 804 | ||
| 804 | if (ife->flags & IFE_ENCODE) | 805 | if (ife->flags & IFE_ENCODE) |
| 805 | return tcf_ife_encode(skb, a, res); | 806 | 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 | 820 | ||
| 820 | static int tcf_ife_walker(struct net *net, struct sk_buff *skb, | 821 | static int tcf_ife_walker(struct net *net, struct sk_buff *skb, |
| 821 | struct netlink_callback *cb, int type, | 822 | struct netlink_callback *cb, int type, |
| 822 | struct tc_action *a) | 823 | const struct tc_action_ops *ops) |
| 823 | { | 824 | { |
| 824 | struct tc_action_net *tn = net_generic(net, ife_net_id); | 825 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
| 825 | 826 | ||
| 826 | return tcf_generic_walker(tn, skb, cb, type, a); | 827 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 827 | } | 828 | } |
| 828 | 829 | ||
| 829 | static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index) | 830 | static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index) |
| 830 | { | 831 | { |
| 831 | struct tc_action_net *tn = net_generic(net, ife_net_id); | 832 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
| 832 | 833 | ||
| @@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = { | |||
| 843 | .init = tcf_ife_init, | 844 | .init = tcf_ife_init, |
| 844 | .walk = tcf_ife_walker, | 845 | .walk = tcf_ife_walker, |
| 845 | .lookup = tcf_ife_search, | 846 | .lookup = tcf_ife_search, |
| 847 | .size = sizeof(struct tcf_ife_info), | ||
| 846 | }; | 848 | }; |
| 847 | 849 | ||
| 848 | static __net_init int ife_init_net(struct net *net) | 850 | static __net_init int ife_init_net(struct net *net) |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b8c50600697a..378c1c976058 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
| @@ -31,8 +31,10 @@ | |||
| 31 | #define IPT_TAB_MASK 15 | 31 | #define IPT_TAB_MASK 15 |
| 32 | 32 | ||
| 33 | static int ipt_net_id; | 33 | static int ipt_net_id; |
| 34 | static struct tc_action_ops act_ipt_ops; | ||
| 34 | 35 | ||
| 35 | static int xt_net_id; | 36 | static int xt_net_id; |
| 37 | static struct tc_action_ops act_xt_ops; | ||
| 36 | 38 | ||
| 37 | static int ipt_init_target(struct xt_entry_target *t, char *table, | 39 | static int ipt_init_target(struct xt_entry_target *t, char *table, |
| 38 | unsigned int hook) | 40 | unsigned int hook) |
| @@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { | |||
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| 92 | static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | 94 | static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, |
| 93 | struct nlattr *est, struct tc_action *a, int ovr, | 95 | struct nlattr *est, struct tc_action **a, |
| 94 | int bind) | 96 | const struct tc_action_ops *ops, int ovr, int bind) |
| 95 | { | 97 | { |
| 96 | struct nlattr *tb[TCA_IPT_MAX + 1]; | 98 | struct nlattr *tb[TCA_IPT_MAX + 1]; |
| 97 | struct tcf_ipt *ipt; | 99 | struct tcf_ipt *ipt; |
| @@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
| 118 | 120 | ||
| 119 | if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { | 121 | if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { |
| 120 | if (exists) | 122 | if (exists) |
| 121 | tcf_hash_release(a, bind); | 123 | tcf_hash_release(*a, bind); |
| 122 | return -EINVAL; | 124 | return -EINVAL; |
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); | 127 | td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); |
| 126 | if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { | 128 | if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { |
| 127 | if (exists) | 129 | if (exists) |
| 128 | tcf_hash_release(a, bind); | 130 | tcf_hash_release(*a, bind); |
| 129 | return -EINVAL; | 131 | return -EINVAL; |
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | if (!exists) { | 134 | if (!exists) { |
| 133 | ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, | 135 | ret = tcf_hash_create(tn, index, est, a, ops, bind, |
| 134 | false); | 136 | false); |
| 135 | if (ret) | 137 | if (ret) |
| 136 | return ret; | 138 | return ret; |
| @@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
| 138 | } else { | 140 | } else { |
| 139 | if (bind)/* dont override defaults */ | 141 | if (bind)/* dont override defaults */ |
| 140 | return 0; | 142 | return 0; |
| 141 | tcf_hash_release(a, bind); | 143 | tcf_hash_release(*a, bind); |
| 142 | 144 | ||
| 143 | if (!ovr) | 145 | if (!ovr) |
| 144 | return -EEXIST; | 146 | return -EEXIST; |
| 145 | } | 147 | } |
| 146 | ipt = to_ipt(a); | ||
| 147 | |||
| 148 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); | 148 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); |
| 149 | 149 | ||
| 150 | err = -ENOMEM; | 150 | err = -ENOMEM; |
| @@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
| 163 | if (err < 0) | 163 | if (err < 0) |
| 164 | goto err3; | 164 | goto err3; |
| 165 | 165 | ||
| 166 | ipt = to_ipt(*a); | ||
| 167 | |||
| 166 | spin_lock_bh(&ipt->tcf_lock); | 168 | spin_lock_bh(&ipt->tcf_lock); |
| 167 | if (ret != ACT_P_CREATED) { | 169 | if (ret != ACT_P_CREATED) { |
| 168 | ipt_destroy_target(ipt->tcfi_t); | 170 | ipt_destroy_target(ipt->tcfi_t); |
| @@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | |||
| 174 | ipt->tcfi_hook = hook; | 176 | ipt->tcfi_hook = hook; |
| 175 | spin_unlock_bh(&ipt->tcf_lock); | 177 | spin_unlock_bh(&ipt->tcf_lock); |
| 176 | if (ret == ACT_P_CREATED) | 178 | if (ret == ACT_P_CREATED) |
| 177 | tcf_hash_insert(tn, a); | 179 | tcf_hash_insert(tn, *a); |
| 178 | return ret; | 180 | return ret; |
| 179 | 181 | ||
| 180 | err3: | 182 | err3: |
| @@ -183,33 +185,33 @@ err2: | |||
| 183 | kfree(tname); | 185 | kfree(tname); |
| 184 | err1: | 186 | err1: |
| 185 | if (ret == ACT_P_CREATED) | 187 | if (ret == ACT_P_CREATED) |
| 186 | tcf_hash_cleanup(a, est); | 188 | tcf_hash_cleanup(*a, est); |
| 187 | return err; | 189 | return err; |
| 188 | } | 190 | } |
| 189 | 191 | ||
| 190 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, | 192 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, |
| 191 | struct nlattr *est, struct tc_action *a, int ovr, | 193 | struct nlattr *est, struct tc_action **a, int ovr, |
| 192 | int bind) | 194 | int bind) |
| 193 | { | 195 | { |
| 194 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 196 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
| 195 | 197 | ||
| 196 | return __tcf_ipt_init(tn, nla, est, a, ovr, bind); | 198 | return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind); |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | static int tcf_xt_init(struct net *net, struct nlattr *nla, | 201 | static int tcf_xt_init(struct net *net, struct nlattr *nla, |
| 200 | struct nlattr *est, struct tc_action *a, int ovr, | 202 | struct nlattr *est, struct tc_action **a, int ovr, |
| 201 | int bind) | 203 | int bind) |
| 202 | { | 204 | { |
| 203 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 205 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
| 204 | 206 | ||
| 205 | return __tcf_ipt_init(tn, nla, est, a, ovr, bind); | 207 | return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind); |
| 206 | } | 208 | } |
| 207 | 209 | ||
| 208 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, | 210 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, |
| 209 | struct tcf_result *res) | 211 | struct tcf_result *res) |
| 210 | { | 212 | { |
| 211 | int ret = 0, result = 0; | 213 | int ret = 0, result = 0; |
| 212 | struct tcf_ipt *ipt = a->priv; | 214 | struct tcf_ipt *ipt = to_ipt(a); |
| 213 | struct xt_action_param par; | 215 | struct xt_action_param par; |
| 214 | 216 | ||
| 215 | if (skb_unclone(skb, GFP_ATOMIC)) | 217 | 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 | int ref) | 261 | int ref) |
| 260 | { | 262 | { |
| 261 | unsigned char *b = skb_tail_pointer(skb); | 263 | unsigned char *b = skb_tail_pointer(skb); |
| 262 | struct tcf_ipt *ipt = a->priv; | 264 | struct tcf_ipt *ipt = to_ipt(a); |
| 263 | struct xt_entry_target *t; | 265 | struct xt_entry_target *t; |
| 264 | struct tcf_t tm; | 266 | struct tcf_t tm; |
| 265 | struct tc_cnt c; | 267 | struct tc_cnt c; |
| @@ -299,14 +301,14 @@ nla_put_failure: | |||
| 299 | 301 | ||
| 300 | static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, | 302 | static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, |
| 301 | struct netlink_callback *cb, int type, | 303 | struct netlink_callback *cb, int type, |
| 302 | struct tc_action *a) | 304 | const struct tc_action_ops *ops) |
| 303 | { | 305 | { |
| 304 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 306 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
| 305 | 307 | ||
| 306 | return tcf_generic_walker(tn, skb, cb, type, a); | 308 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 307 | } | 309 | } |
| 308 | 310 | ||
| 309 | static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) | 311 | static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index) |
| 310 | { | 312 | { |
| 311 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 313 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
| 312 | 314 | ||
| @@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = { | |||
| 323 | .init = tcf_ipt_init, | 325 | .init = tcf_ipt_init, |
| 324 | .walk = tcf_ipt_walker, | 326 | .walk = tcf_ipt_walker, |
| 325 | .lookup = tcf_ipt_search, | 327 | .lookup = tcf_ipt_search, |
| 328 | .size = sizeof(struct tcf_ipt), | ||
| 326 | }; | 329 | }; |
| 327 | 330 | ||
| 328 | static __net_init int ipt_init_net(struct net *net) | 331 | static __net_init int ipt_init_net(struct net *net) |
| @@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = { | |||
| 348 | 351 | ||
| 349 | static int tcf_xt_walker(struct net *net, struct sk_buff *skb, | 352 | static int tcf_xt_walker(struct net *net, struct sk_buff *skb, |
| 350 | struct netlink_callback *cb, int type, | 353 | struct netlink_callback *cb, int type, |
| 351 | struct tc_action *a) | 354 | const struct tc_action_ops *ops) |
| 352 | { | 355 | { |
| 353 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 356 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
| 354 | 357 | ||
| 355 | return tcf_generic_walker(tn, skb, cb, type, a); | 358 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 356 | } | 359 | } |
| 357 | 360 | ||
| 358 | static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) | 361 | static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index) |
| 359 | { | 362 | { |
| 360 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 363 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
| 361 | 364 | ||
| @@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = { | |||
| 372 | .init = tcf_xt_init, | 375 | .init = tcf_xt_init, |
| 373 | .walk = tcf_xt_walker, | 376 | .walk = tcf_xt_walker, |
| 374 | .lookup = tcf_xt_search, | 377 | .lookup = tcf_xt_search, |
| 378 | .size = sizeof(struct tcf_ipt), | ||
| 375 | }; | 379 | }; |
| 376 | 380 | ||
| 377 | static __net_init int xt_init_net(struct net *net) | 381 | static __net_init int xt_init_net(struct net *net) |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 70cfbbf96af2..6038c85d92f5 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
| @@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { | |||
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static int mirred_net_id; | 54 | static int mirred_net_id; |
| 55 | static struct tc_action_ops act_mirred_ops; | ||
| 55 | 56 | ||
| 56 | static int tcf_mirred_init(struct net *net, struct nlattr *nla, | 57 | static int tcf_mirred_init(struct net *net, struct nlattr *nla, |
| 57 | struct nlattr *est, struct tc_action *a, int ovr, | 58 | struct nlattr *est, struct tc_action **a, int ovr, |
| 58 | int bind) | 59 | int bind) |
| 59 | { | 60 | { |
| 60 | struct tc_action_net *tn = net_generic(net, mirred_net_id); | 61 | 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 | break; | 85 | break; |
| 85 | default: | 86 | default: |
| 86 | if (exists) | 87 | if (exists) |
| 87 | tcf_hash_release(a, bind); | 88 | tcf_hash_release(*a, bind); |
| 88 | return -EINVAL; | 89 | return -EINVAL; |
| 89 | } | 90 | } |
| 90 | if (parm->ifindex) { | 91 | if (parm->ifindex) { |
| 91 | dev = __dev_get_by_index(net, parm->ifindex); | 92 | dev = __dev_get_by_index(net, parm->ifindex); |
| 92 | if (dev == NULL) { | 93 | if (dev == NULL) { |
| 93 | if (exists) | 94 | if (exists) |
| 94 | tcf_hash_release(a, bind); | 95 | tcf_hash_release(*a, bind); |
| 95 | return -ENODEV; | 96 | return -ENODEV; |
| 96 | } | 97 | } |
| 97 | switch (dev->type) { | 98 | switch (dev->type) { |
| @@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 115 | if (dev == NULL) | 116 | if (dev == NULL) |
| 116 | return -EINVAL; | 117 | return -EINVAL; |
| 117 | ret = tcf_hash_create(tn, parm->index, est, a, | 118 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 118 | sizeof(*m), bind, true); | 119 | &act_mirred_ops, bind, true); |
| 119 | if (ret) | 120 | if (ret) |
| 120 | return ret; | 121 | return ret; |
| 121 | ret = ACT_P_CREATED; | 122 | ret = ACT_P_CREATED; |
| 122 | } else { | 123 | } else { |
| 123 | tcf_hash_release(a, bind); | 124 | tcf_hash_release(*a, bind); |
| 124 | if (!ovr) | 125 | if (!ovr) |
| 125 | return -EEXIST; | 126 | return -EEXIST; |
| 126 | } | 127 | } |
| 127 | m = to_mirred(a); | 128 | m = to_mirred(*a); |
| 128 | 129 | ||
| 129 | ASSERT_RTNL(); | 130 | ASSERT_RTNL(); |
| 130 | m->tcf_action = parm->action; | 131 | m->tcf_action = parm->action; |
| @@ -142,7 +143,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 142 | spin_lock_bh(&mirred_list_lock); | 143 | spin_lock_bh(&mirred_list_lock); |
| 143 | list_add(&m->tcfm_list, &mirred_list); | 144 | list_add(&m->tcfm_list, &mirred_list); |
| 144 | spin_unlock_bh(&mirred_list_lock); | 145 | spin_unlock_bh(&mirred_list_lock); |
| 145 | tcf_hash_insert(tn, a); | 146 | tcf_hash_insert(tn, *a); |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | return ret; | 149 | return ret; |
| @@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 151 | static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, | 152 | static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, |
| 152 | struct tcf_result *res) | 153 | struct tcf_result *res) |
| 153 | { | 154 | { |
| 154 | struct tcf_mirred *m = a->priv; | 155 | struct tcf_mirred *m = to_mirred(a); |
| 155 | struct net_device *dev; | 156 | struct net_device *dev; |
| 156 | struct sk_buff *skb2; | 157 | struct sk_buff *skb2; |
| 157 | int retval, err; | 158 | int retval, err; |
| @@ -206,7 +207,7 @@ out: | |||
| 206 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 207 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
| 207 | { | 208 | { |
| 208 | unsigned char *b = skb_tail_pointer(skb); | 209 | unsigned char *b = skb_tail_pointer(skb); |
| 209 | struct tcf_mirred *m = a->priv; | 210 | struct tcf_mirred *m = to_mirred(a); |
| 210 | struct tc_mirred opt = { | 211 | struct tc_mirred opt = { |
| 211 | .index = m->tcf_index, | 212 | .index = m->tcf_index, |
| 212 | .action = m->tcf_action, | 213 | .action = m->tcf_action, |
| @@ -232,14 +233,14 @@ nla_put_failure: | |||
| 232 | 233 | ||
| 233 | static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, | 234 | static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, |
| 234 | struct netlink_callback *cb, int type, | 235 | struct netlink_callback *cb, int type, |
| 235 | struct tc_action *a) | 236 | const struct tc_action_ops *ops) |
| 236 | { | 237 | { |
| 237 | struct tc_action_net *tn = net_generic(net, mirred_net_id); | 238 | struct tc_action_net *tn = net_generic(net, mirred_net_id); |
| 238 | 239 | ||
| 239 | return tcf_generic_walker(tn, skb, cb, type, a); | 240 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 240 | } | 241 | } |
| 241 | 242 | ||
| 242 | static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index) | 243 | static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index) |
| 243 | { | 244 | { |
| 244 | struct tc_action_net *tn = net_generic(net, mirred_net_id); | 245 | struct tc_action_net *tn = net_generic(net, mirred_net_id); |
| 245 | 246 | ||
| @@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = { | |||
| 284 | .init = tcf_mirred_init, | 285 | .init = tcf_mirred_init, |
| 285 | .walk = tcf_mirred_walker, | 286 | .walk = tcf_mirred_walker, |
| 286 | .lookup = tcf_mirred_search, | 287 | .lookup = tcf_mirred_search, |
| 288 | .size = sizeof(struct tcf_mirred), | ||
| 287 | }; | 289 | }; |
| 288 | 290 | ||
| 289 | static __net_init int mirred_init_net(struct net *net) | 291 | static __net_init int mirred_init_net(struct net *net) |
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 06ccb03f25da..8e8b0cc30704 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
| @@ -32,13 +32,14 @@ | |||
| 32 | #define NAT_TAB_MASK 15 | 32 | #define NAT_TAB_MASK 15 |
| 33 | 33 | ||
| 34 | static int nat_net_id; | 34 | static int nat_net_id; |
| 35 | static struct tc_action_ops act_nat_ops; | ||
| 35 | 36 | ||
| 36 | static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { | 37 | static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { |
| 37 | [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, | 38 | [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | 41 | static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, |
| 41 | struct tc_action *a, int ovr, int bind) | 42 | struct tc_action **a, int ovr, int bind) |
| 42 | { | 43 | { |
| 43 | struct tc_action_net *tn = net_generic(net, nat_net_id); | 44 | struct tc_action_net *tn = net_generic(net, nat_net_id); |
| 44 | struct nlattr *tb[TCA_NAT_MAX + 1]; | 45 | 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 | 60 | ||
| 60 | if (!tcf_hash_check(tn, parm->index, a, bind)) { | 61 | if (!tcf_hash_check(tn, parm->index, a, bind)) { |
| 61 | ret = tcf_hash_create(tn, parm->index, est, a, | 62 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 62 | sizeof(*p), bind, false); | 63 | &act_nat_ops, bind, false); |
| 63 | if (ret) | 64 | if (ret) |
| 64 | return ret; | 65 | return ret; |
| 65 | ret = ACT_P_CREATED; | 66 | ret = ACT_P_CREATED; |
| 66 | } else { | 67 | } else { |
| 67 | if (bind) | 68 | if (bind) |
| 68 | return 0; | 69 | return 0; |
| 69 | tcf_hash_release(a, bind); | 70 | tcf_hash_release(*a, bind); |
| 70 | if (!ovr) | 71 | if (!ovr) |
| 71 | return -EEXIST; | 72 | return -EEXIST; |
| 72 | } | 73 | } |
| 73 | p = to_tcf_nat(a); | 74 | p = to_tcf_nat(*a); |
| 74 | 75 | ||
| 75 | spin_lock_bh(&p->tcf_lock); | 76 | spin_lock_bh(&p->tcf_lock); |
| 76 | p->old_addr = parm->old_addr; | 77 | 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 | spin_unlock_bh(&p->tcf_lock); | 83 | spin_unlock_bh(&p->tcf_lock); |
| 83 | 84 | ||
| 84 | if (ret == ACT_P_CREATED) | 85 | if (ret == ACT_P_CREATED) |
| 85 | tcf_hash_insert(tn, a); | 86 | tcf_hash_insert(tn, *a); |
| 86 | 87 | ||
| 87 | return ret; | 88 | return ret; |
| 88 | } | 89 | } |
| @@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 90 | static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, | 91 | static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, |
| 91 | struct tcf_result *res) | 92 | struct tcf_result *res) |
| 92 | { | 93 | { |
| 93 | struct tcf_nat *p = a->priv; | 94 | struct tcf_nat *p = to_tcf_nat(a); |
| 94 | struct iphdr *iph; | 95 | struct iphdr *iph; |
| 95 | __be32 old_addr; | 96 | __be32 old_addr; |
| 96 | __be32 new_addr; | 97 | __be32 new_addr; |
| @@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 248 | int bind, int ref) | 249 | int bind, int ref) |
| 249 | { | 250 | { |
| 250 | unsigned char *b = skb_tail_pointer(skb); | 251 | unsigned char *b = skb_tail_pointer(skb); |
| 251 | struct tcf_nat *p = a->priv; | 252 | struct tcf_nat *p = to_tcf_nat(a); |
| 252 | struct tc_nat opt = { | 253 | struct tc_nat opt = { |
| 253 | .old_addr = p->old_addr, | 254 | .old_addr = p->old_addr, |
| 254 | .new_addr = p->new_addr, | 255 | .new_addr = p->new_addr, |
| @@ -278,14 +279,14 @@ nla_put_failure: | |||
| 278 | 279 | ||
| 279 | static int tcf_nat_walker(struct net *net, struct sk_buff *skb, | 280 | static int tcf_nat_walker(struct net *net, struct sk_buff *skb, |
| 280 | struct netlink_callback *cb, int type, | 281 | struct netlink_callback *cb, int type, |
| 281 | struct tc_action *a) | 282 | const struct tc_action_ops *ops) |
| 282 | { | 283 | { |
| 283 | struct tc_action_net *tn = net_generic(net, nat_net_id); | 284 | struct tc_action_net *tn = net_generic(net, nat_net_id); |
| 284 | 285 | ||
| 285 | return tcf_generic_walker(tn, skb, cb, type, a); | 286 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index) | 289 | static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index) |
| 289 | { | 290 | { |
| 290 | struct tc_action_net *tn = net_generic(net, nat_net_id); | 291 | struct tc_action_net *tn = net_generic(net, nat_net_id); |
| 291 | 292 | ||
| @@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = { | |||
| 301 | .init = tcf_nat_init, | 302 | .init = tcf_nat_init, |
| 302 | .walk = tcf_nat_walker, | 303 | .walk = tcf_nat_walker, |
| 303 | .lookup = tcf_nat_search, | 304 | .lookup = tcf_nat_search, |
| 305 | .size = sizeof(struct tcf_nat), | ||
| 304 | }; | 306 | }; |
| 305 | 307 | ||
| 306 | static __net_init int nat_init_net(struct net *net) | 308 | static __net_init int nat_init_net(struct net *net) |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 82d3c1479029..b54d56d4959b 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
| @@ -26,13 +26,14 @@ | |||
| 26 | #define PEDIT_TAB_MASK 15 | 26 | #define PEDIT_TAB_MASK 15 |
| 27 | 27 | ||
| 28 | static int pedit_net_id; | 28 | static int pedit_net_id; |
| 29 | static struct tc_action_ops act_pedit_ops; | ||
| 29 | 30 | ||
| 30 | static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { | 31 | static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { |
| 31 | [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, | 32 | [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, |
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 34 | static int tcf_pedit_init(struct net *net, struct nlattr *nla, | 35 | static int tcf_pedit_init(struct net *net, struct nlattr *nla, |
| 35 | struct nlattr *est, struct tc_action *a, | 36 | struct nlattr *est, struct tc_action **a, |
| 36 | int ovr, int bind) | 37 | int ovr, int bind) |
| 37 | { | 38 | { |
| 38 | struct tc_action_net *tn = net_generic(net, pedit_net_id); | 39 | 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 | if (!parm->nkeys) | 62 | if (!parm->nkeys) |
| 62 | return -EINVAL; | 63 | return -EINVAL; |
| 63 | ret = tcf_hash_create(tn, parm->index, est, a, | 64 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 64 | sizeof(*p), bind, false); | 65 | &act_pedit_ops, bind, false); |
| 65 | if (ret) | 66 | if (ret) |
| 66 | return ret; | 67 | return ret; |
| 67 | p = to_pedit(a); | 68 | p = to_pedit(*a); |
| 68 | keys = kmalloc(ksize, GFP_KERNEL); | 69 | keys = kmalloc(ksize, GFP_KERNEL); |
| 69 | if (keys == NULL) { | 70 | if (keys == NULL) { |
| 70 | tcf_hash_cleanup(a, est); | 71 | tcf_hash_cleanup(*a, est); |
| 71 | return -ENOMEM; | 72 | return -ENOMEM; |
| 72 | } | 73 | } |
| 73 | ret = ACT_P_CREATED; | 74 | ret = ACT_P_CREATED; |
| 74 | } else { | 75 | } else { |
| 75 | if (bind) | 76 | if (bind) |
| 76 | return 0; | 77 | return 0; |
| 77 | tcf_hash_release(a, bind); | 78 | tcf_hash_release(*a, bind); |
| 78 | if (!ovr) | 79 | if (!ovr) |
| 79 | return -EEXIST; | 80 | return -EEXIST; |
| 80 | p = to_pedit(a); | 81 | p = to_pedit(*a); |
| 81 | if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { | 82 | if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { |
| 82 | keys = kmalloc(ksize, GFP_KERNEL); | 83 | keys = kmalloc(ksize, GFP_KERNEL); |
| 83 | if (keys == NULL) | 84 | if (keys == NULL) |
| @@ -96,13 +97,13 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 96 | memcpy(p->tcfp_keys, parm->keys, ksize); | 97 | memcpy(p->tcfp_keys, parm->keys, ksize); |
| 97 | spin_unlock_bh(&p->tcf_lock); | 98 | spin_unlock_bh(&p->tcf_lock); |
| 98 | if (ret == ACT_P_CREATED) | 99 | if (ret == ACT_P_CREATED) |
| 99 | tcf_hash_insert(tn, a); | 100 | tcf_hash_insert(tn, *a); |
| 100 | return ret; | 101 | return ret; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | static void tcf_pedit_cleanup(struct tc_action *a, int bind) | 104 | static void tcf_pedit_cleanup(struct tc_action *a, int bind) |
| 104 | { | 105 | { |
| 105 | struct tcf_pedit *p = a->priv; | 106 | struct tcf_pedit *p = to_pedit(a); |
| 106 | struct tc_pedit_key *keys = p->tcfp_keys; | 107 | struct tc_pedit_key *keys = p->tcfp_keys; |
| 107 | kfree(keys); | 108 | kfree(keys); |
| 108 | } | 109 | } |
| @@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind) | |||
| 110 | static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, | 111 | static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, |
| 111 | struct tcf_result *res) | 112 | struct tcf_result *res) |
| 112 | { | 113 | { |
| 113 | struct tcf_pedit *p = a->priv; | 114 | struct tcf_pedit *p = to_pedit(a); |
| 114 | int i; | 115 | int i; |
| 115 | unsigned int off; | 116 | unsigned int off; |
| 116 | 117 | ||
| @@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 177 | int bind, int ref) | 178 | int bind, int ref) |
| 178 | { | 179 | { |
| 179 | unsigned char *b = skb_tail_pointer(skb); | 180 | unsigned char *b = skb_tail_pointer(skb); |
| 180 | struct tcf_pedit *p = a->priv; | 181 | struct tcf_pedit *p = to_pedit(a); |
| 181 | struct tc_pedit *opt; | 182 | struct tc_pedit *opt; |
| 182 | struct tcf_t t; | 183 | struct tcf_t t; |
| 183 | int s; | 184 | int s; |
| @@ -216,14 +217,14 @@ nla_put_failure: | |||
| 216 | 217 | ||
| 217 | static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, | 218 | static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, |
| 218 | struct netlink_callback *cb, int type, | 219 | struct netlink_callback *cb, int type, |
| 219 | struct tc_action *a) | 220 | const struct tc_action_ops *ops) |
| 220 | { | 221 | { |
| 221 | struct tc_action_net *tn = net_generic(net, pedit_net_id); | 222 | struct tc_action_net *tn = net_generic(net, pedit_net_id); |
| 222 | 223 | ||
| 223 | return tcf_generic_walker(tn, skb, cb, type, a); | 224 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 224 | } | 225 | } |
| 225 | 226 | ||
| 226 | static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index) | 227 | static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index) |
| 227 | { | 228 | { |
| 228 | struct tc_action_net *tn = net_generic(net, pedit_net_id); | 229 | struct tc_action_net *tn = net_generic(net, pedit_net_id); |
| 229 | 230 | ||
| @@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = { | |||
| 240 | .init = tcf_pedit_init, | 241 | .init = tcf_pedit_init, |
| 241 | .walk = tcf_pedit_walker, | 242 | .walk = tcf_pedit_walker, |
| 242 | .lookup = tcf_pedit_search, | 243 | .lookup = tcf_pedit_search, |
| 244 | .size = sizeof(struct tcf_pedit), | ||
| 243 | }; | 245 | }; |
| 244 | 246 | ||
| 245 | static __net_init int pedit_init_net(struct net *net) | 247 | static __net_init int pedit_init_net(struct net *net) |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 1e8ede3955f4..123794af55c3 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -37,8 +37,8 @@ struct tcf_police { | |||
| 37 | struct psched_ratecfg peak; | 37 | struct psched_ratecfg peak; |
| 38 | bool peak_present; | 38 | bool peak_present; |
| 39 | }; | 39 | }; |
| 40 | #define to_police(pc) \ | 40 | |
| 41 | container_of(pc->priv, struct tcf_police, common) | 41 | #define to_police(pc) ((struct tcf_police *)pc) |
| 42 | 42 | ||
| 43 | #define POL_TAB_MASK 15 | 43 | #define POL_TAB_MASK 15 |
| 44 | 44 | ||
| @@ -56,15 +56,14 @@ struct tc_police_compat { | |||
| 56 | /* Each policer is serialized by its individual spinlock */ | 56 | /* Each policer is serialized by its individual spinlock */ |
| 57 | 57 | ||
| 58 | static int police_net_id; | 58 | static int police_net_id; |
| 59 | static struct tc_action_ops act_police_ops; | ||
| 59 | 60 | ||
| 60 | static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, | 61 | static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, |
| 61 | struct netlink_callback *cb, int type, | 62 | struct netlink_callback *cb, int type, |
| 62 | struct tc_action *a) | 63 | const struct tc_action_ops *ops) |
| 63 | { | 64 | { |
| 64 | struct tc_action_net *tn = net_generic(net, police_net_id); | 65 | struct tc_action_net *tn = net_generic(net, police_net_id); |
| 65 | struct tcf_hashinfo *hinfo = tn->hinfo; | 66 | struct tcf_hashinfo *hinfo = tn->hinfo; |
| 66 | struct hlist_head *head; | ||
| 67 | struct tcf_common *p; | ||
| 68 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; | 67 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
| 69 | struct nlattr *nest; | 68 | struct nlattr *nest; |
| 70 | 69 | ||
| @@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, | |||
| 73 | s_i = cb->args[0]; | 72 | s_i = cb->args[0]; |
| 74 | 73 | ||
| 75 | for (i = 0; i < (POL_TAB_MASK + 1); i++) { | 74 | for (i = 0; i < (POL_TAB_MASK + 1); i++) { |
| 75 | struct hlist_head *head; | ||
| 76 | struct tcf_common *p; | ||
| 77 | |||
| 76 | head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)]; | 78 | head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)]; |
| 77 | 79 | ||
| 78 | hlist_for_each_entry_rcu(p, head, tcfc_head) { | 80 | hlist_for_each_entry_rcu(p, head, tcfc_head) { |
| 79 | index++; | 81 | index++; |
| 80 | if (index < s_i) | 82 | if (index < s_i) |
| 81 | continue; | 83 | continue; |
| 82 | a->priv = p; | 84 | nest = nla_nest_start(skb, index); |
| 83 | a->order = index; | ||
| 84 | nest = nla_nest_start(skb, a->order); | ||
| 85 | if (nest == NULL) | 85 | if (nest == NULL) |
| 86 | goto nla_put_failure; | 86 | goto nla_put_failure; |
| 87 | if (type == RTM_DELACTION) | 87 | if (type == RTM_DELACTION) |
| 88 | err = tcf_action_dump_1(skb, a, 0, 1); | 88 | err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 1); |
| 89 | else | 89 | else |
| 90 | err = tcf_action_dump_1(skb, a, 0, 0); | 90 | err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 0); |
| 91 | if (err < 0) { | 91 | if (err < 0) { |
| 92 | index--; | 92 | index--; |
| 93 | nla_nest_cancel(skb, nest); | 93 | nla_nest_cancel(skb, nest); |
| @@ -116,7 +116,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { | |||
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | static int tcf_act_police_init(struct net *net, struct nlattr *nla, | 118 | static int tcf_act_police_init(struct net *net, struct nlattr *nla, |
| 119 | struct nlattr *est, struct tc_action *a, | 119 | struct nlattr *est, struct tc_action **a, |
| 120 | int ovr, int bind) | 120 | int ovr, int bind) |
| 121 | { | 121 | { |
| 122 | int ret = 0, err; | 122 | int ret = 0, err; |
| @@ -142,13 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, | |||
| 142 | parm = nla_data(tb[TCA_POLICE_TBF]); | 142 | parm = nla_data(tb[TCA_POLICE_TBF]); |
| 143 | 143 | ||
| 144 | if (parm->index) { | 144 | if (parm->index) { |
| 145 | if (tcf_hash_search(tn, a, parm->index)) { | 145 | if (tcf_hash_check(tn, parm->index, a, bind)) { |
| 146 | police = to_police(a); | ||
| 147 | if (bind) { | ||
| 148 | police->tcf_bindcnt += 1; | ||
| 149 | police->tcf_refcnt += 1; | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | if (ovr) | 146 | if (ovr) |
| 153 | goto override; | 147 | goto override; |
| 154 | /* not replacing */ | 148 | /* not replacing */ |
| @@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla, | |||
| 156 | } | 150 | } |
| 157 | } else { | 151 | } else { |
| 158 | ret = tcf_hash_create(tn, parm->index, NULL, a, | 152 | ret = tcf_hash_create(tn, parm->index, NULL, a, |
| 159 | sizeof(*police), bind, false); | 153 | &act_police_ops, bind, false); |
| 160 | if (ret) | 154 | if (ret) |
| 161 | return ret; | 155 | return ret; |
| 162 | ret = ACT_P_CREATED; | 156 | ret = ACT_P_CREATED; |
| 163 | } | 157 | } |
| 164 | 158 | ||
| 165 | police = to_police(a); | ||
| 166 | override: | 159 | override: |
| 160 | police = to_police(*a); | ||
| 167 | if (parm->rate.rate) { | 161 | if (parm->rate.rate) { |
| 168 | err = -ENOMEM; | 162 | err = -ENOMEM; |
| 169 | R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); | 163 | R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); |
| @@ -235,7 +229,7 @@ override: | |||
| 235 | return ret; | 229 | return ret; |
| 236 | 230 | ||
| 237 | police->tcfp_t_c = ktime_get_ns(); | 231 | police->tcfp_t_c = ktime_get_ns(); |
| 238 | tcf_hash_insert(tn, a); | 232 | tcf_hash_insert(tn, *a); |
| 239 | 233 | ||
| 240 | return ret; | 234 | return ret; |
| 241 | 235 | ||
| @@ -245,14 +239,14 @@ failure: | |||
| 245 | qdisc_put_rtab(P_tab); | 239 | qdisc_put_rtab(P_tab); |
| 246 | qdisc_put_rtab(R_tab); | 240 | qdisc_put_rtab(R_tab); |
| 247 | if (ret == ACT_P_CREATED) | 241 | if (ret == ACT_P_CREATED) |
| 248 | tcf_hash_cleanup(a, est); | 242 | tcf_hash_cleanup(*a, est); |
| 249 | return err; | 243 | return err; |
| 250 | } | 244 | } |
| 251 | 245 | ||
| 252 | static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, | 246 | static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, |
| 253 | struct tcf_result *res) | 247 | struct tcf_result *res) |
| 254 | { | 248 | { |
| 255 | struct tcf_police *police = a->priv; | 249 | struct tcf_police *police = to_police(a); |
| 256 | s64 now; | 250 | s64 now; |
| 257 | s64 toks; | 251 | s64 toks; |
| 258 | s64 ptoks = 0; | 252 | s64 ptoks = 0; |
| @@ -311,7 +305,7 @@ static int | |||
| 311 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 305 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
| 312 | { | 306 | { |
| 313 | unsigned char *b = skb_tail_pointer(skb); | 307 | unsigned char *b = skb_tail_pointer(skb); |
| 314 | struct tcf_police *police = a->priv; | 308 | struct tcf_police *police = to_police(a); |
| 315 | struct tc_police opt = { | 309 | struct tc_police opt = { |
| 316 | .index = police->tcf_index, | 310 | .index = police->tcf_index, |
| 317 | .action = police->tcf_action, | 311 | .action = police->tcf_action, |
| @@ -349,7 +343,7 @@ nla_put_failure: | |||
| 349 | return -1; | 343 | return -1; |
| 350 | } | 344 | } |
| 351 | 345 | ||
| 352 | static int tcf_police_search(struct net *net, struct tc_action *a, u32 index) | 346 | static int tcf_police_search(struct net *net, struct tc_action **a, u32 index) |
| 353 | { | 347 | { |
| 354 | struct tc_action_net *tn = net_generic(net, police_net_id); | 348 | struct tc_action_net *tn = net_generic(net, police_net_id); |
| 355 | 349 | ||
| @@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = { | |||
| 369 | .init = tcf_act_police_init, | 363 | .init = tcf_act_police_init, |
| 370 | .walk = tcf_act_police_walker, | 364 | .walk = tcf_act_police_walker, |
| 371 | .lookup = tcf_police_search, | 365 | .lookup = tcf_police_search, |
| 366 | .size = sizeof(struct tcf_police), | ||
| 372 | }; | 367 | }; |
| 373 | 368 | ||
| 374 | static __net_init int police_init_net(struct net *net) | 369 | static __net_init int police_init_net(struct net *net) |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 318328d34d12..289af6f9bb3b 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
| @@ -27,12 +27,13 @@ | |||
| 27 | #define SIMP_TAB_MASK 7 | 27 | #define SIMP_TAB_MASK 7 |
| 28 | 28 | ||
| 29 | static int simp_net_id; | 29 | static int simp_net_id; |
| 30 | static struct tc_action_ops act_simp_ops; | ||
| 30 | 31 | ||
| 31 | #define SIMP_MAX_DATA 32 | 32 | #define SIMP_MAX_DATA 32 |
| 32 | static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, | 33 | static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, |
| 33 | struct tcf_result *res) | 34 | struct tcf_result *res) |
| 34 | { | 35 | { |
| 35 | struct tcf_defact *d = a->priv; | 36 | struct tcf_defact *d = to_defact(a); |
| 36 | 37 | ||
| 37 | spin_lock(&d->tcf_lock); | 38 | spin_lock(&d->tcf_lock); |
| 38 | tcf_lastuse_update(&d->tcf_tm); | 39 | tcf_lastuse_update(&d->tcf_tm); |
| @@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { | |||
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 81 | static int tcf_simp_init(struct net *net, struct nlattr *nla, | 82 | static int tcf_simp_init(struct net *net, struct nlattr *nla, |
| 82 | struct nlattr *est, struct tc_action *a, | 83 | struct nlattr *est, struct tc_action **a, |
| 83 | int ovr, int bind) | 84 | int ovr, int bind) |
| 84 | { | 85 | { |
| 85 | struct tc_action_net *tn = net_generic(net, simp_net_id); | 86 | 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 | if (tb[TCA_DEF_PARMS] == NULL) | 101 | if (tb[TCA_DEF_PARMS] == NULL) |
| 101 | return -EINVAL; | 102 | return -EINVAL; |
| 102 | 103 | ||
| 103 | |||
| 104 | parm = nla_data(tb[TCA_DEF_PARMS]); | 104 | parm = nla_data(tb[TCA_DEF_PARMS]); |
| 105 | exists = tcf_hash_check(tn, parm->index, a, bind); | 105 | exists = tcf_hash_check(tn, parm->index, a, bind); |
| 106 | if (exists && bind) | 106 | if (exists && bind) |
| @@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 108 | 108 | ||
| 109 | if (tb[TCA_DEF_DATA] == NULL) { | 109 | if (tb[TCA_DEF_DATA] == NULL) { |
| 110 | if (exists) | 110 | if (exists) |
| 111 | tcf_hash_release(a, bind); | 111 | tcf_hash_release(*a, bind); |
| 112 | return -EINVAL; | 112 | return -EINVAL; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| @@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 116 | 116 | ||
| 117 | if (!exists) { | 117 | if (!exists) { |
| 118 | ret = tcf_hash_create(tn, parm->index, est, a, | 118 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 119 | sizeof(*d), bind, false); | 119 | &act_simp_ops, bind, false); |
| 120 | if (ret) | 120 | if (ret) |
| 121 | return ret; | 121 | return ret; |
| 122 | 122 | ||
| 123 | d = to_defact(a); | 123 | d = to_defact(*a); |
| 124 | ret = alloc_defdata(d, defdata); | 124 | ret = alloc_defdata(d, defdata); |
| 125 | if (ret < 0) { | 125 | if (ret < 0) { |
| 126 | tcf_hash_cleanup(a, est); | 126 | tcf_hash_cleanup(*a, est); |
| 127 | return ret; | 127 | return ret; |
| 128 | } | 128 | } |
| 129 | d->tcf_action = parm->action; | 129 | d->tcf_action = parm->action; |
| 130 | ret = ACT_P_CREATED; | 130 | ret = ACT_P_CREATED; |
| 131 | } else { | 131 | } else { |
| 132 | d = to_defact(a); | 132 | d = to_defact(*a); |
| 133 | 133 | ||
| 134 | tcf_hash_release(a, bind); | 134 | tcf_hash_release(*a, bind); |
| 135 | if (!ovr) | 135 | if (!ovr) |
| 136 | return -EEXIST; | 136 | return -EEXIST; |
| 137 | 137 | ||
| @@ -139,7 +139,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | if (ret == ACT_P_CREATED) | 141 | if (ret == ACT_P_CREATED) |
| 142 | tcf_hash_insert(tn, a); | 142 | tcf_hash_insert(tn, *a); |
| 143 | return ret; | 143 | return ret; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 147 | int bind, int ref) | 147 | int bind, int ref) |
| 148 | { | 148 | { |
| 149 | unsigned char *b = skb_tail_pointer(skb); | 149 | unsigned char *b = skb_tail_pointer(skb); |
| 150 | struct tcf_defact *d = a->priv; | 150 | struct tcf_defact *d = to_defact(a); |
| 151 | struct tc_defact opt = { | 151 | struct tc_defact opt = { |
| 152 | .index = d->tcf_index, | 152 | .index = d->tcf_index, |
| 153 | .refcnt = d->tcf_refcnt - ref, | 153 | .refcnt = d->tcf_refcnt - ref, |
| @@ -172,14 +172,14 @@ nla_put_failure: | |||
| 172 | 172 | ||
| 173 | static int tcf_simp_walker(struct net *net, struct sk_buff *skb, | 173 | static int tcf_simp_walker(struct net *net, struct sk_buff *skb, |
| 174 | struct netlink_callback *cb, int type, | 174 | struct netlink_callback *cb, int type, |
| 175 | struct tc_action *a) | 175 | const struct tc_action_ops *ops) |
| 176 | { | 176 | { |
| 177 | struct tc_action_net *tn = net_generic(net, simp_net_id); | 177 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
| 178 | 178 | ||
| 179 | return tcf_generic_walker(tn, skb, cb, type, a); | 179 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index) | 182 | static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index) |
| 183 | { | 183 | { |
| 184 | struct tc_action_net *tn = net_generic(net, simp_net_id); | 184 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
| 185 | 185 | ||
| @@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = { | |||
| 196 | .init = tcf_simp_init, | 196 | .init = tcf_simp_init, |
| 197 | .walk = tcf_simp_walker, | 197 | .walk = tcf_simp_walker, |
| 198 | .lookup = tcf_simp_search, | 198 | .lookup = tcf_simp_search, |
| 199 | .size = sizeof(struct tcf_defact), | ||
| 199 | }; | 200 | }; |
| 200 | 201 | ||
| 201 | static __net_init int simp_init_net(struct net *net) | 202 | static __net_init int simp_init_net(struct net *net) |
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 8e573c0f8742..a133dcb82132 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c | |||
| @@ -30,11 +30,12 @@ | |||
| 30 | #define SKBEDIT_TAB_MASK 15 | 30 | #define SKBEDIT_TAB_MASK 15 |
| 31 | 31 | ||
| 32 | static int skbedit_net_id; | 32 | static int skbedit_net_id; |
| 33 | static struct tc_action_ops act_skbedit_ops; | ||
| 33 | 34 | ||
| 34 | static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, | 35 | static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, |
| 35 | struct tcf_result *res) | 36 | struct tcf_result *res) |
| 36 | { | 37 | { |
| 37 | struct tcf_skbedit *d = a->priv; | 38 | struct tcf_skbedit *d = to_skbedit(a); |
| 38 | 39 | ||
| 39 | spin_lock(&d->tcf_lock); | 40 | spin_lock(&d->tcf_lock); |
| 40 | tcf_lastuse_update(&d->tcf_tm); | 41 | tcf_lastuse_update(&d->tcf_tm); |
| @@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { | |||
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | 66 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, |
| 66 | struct nlattr *est, struct tc_action *a, | 67 | struct nlattr *est, struct tc_action **a, |
| 67 | int ovr, int bind) | 68 | int ovr, int bind) |
| 68 | { | 69 | { |
| 69 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); | 70 | 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 | return 0; | 115 | return 0; |
| 115 | 116 | ||
| 116 | if (!flags) { | 117 | if (!flags) { |
| 117 | tcf_hash_release(a, bind); | 118 | tcf_hash_release(*a, bind); |
| 118 | return -EINVAL; | 119 | return -EINVAL; |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | if (!exists) { | 122 | if (!exists) { |
| 122 | ret = tcf_hash_create(tn, parm->index, est, a, | 123 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 123 | sizeof(*d), bind, false); | 124 | &act_skbedit_ops, bind, false); |
| 124 | if (ret) | 125 | if (ret) |
| 125 | return ret; | 126 | return ret; |
| 126 | 127 | ||
| 127 | d = to_skbedit(a); | 128 | d = to_skbedit(*a); |
| 128 | ret = ACT_P_CREATED; | 129 | ret = ACT_P_CREATED; |
| 129 | } else { | 130 | } else { |
| 130 | d = to_skbedit(a); | 131 | d = to_skbedit(*a); |
| 131 | tcf_hash_release(a, bind); | 132 | tcf_hash_release(*a, bind); |
| 132 | if (!ovr) | 133 | if (!ovr) |
| 133 | return -EEXIST; | 134 | return -EEXIST; |
| 134 | } | 135 | } |
| @@ -150,7 +151,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 150 | spin_unlock_bh(&d->tcf_lock); | 151 | spin_unlock_bh(&d->tcf_lock); |
| 151 | 152 | ||
| 152 | if (ret == ACT_P_CREATED) | 153 | if (ret == ACT_P_CREATED) |
| 153 | tcf_hash_insert(tn, a); | 154 | tcf_hash_insert(tn, *a); |
| 154 | return ret; | 155 | return ret; |
| 155 | } | 156 | } |
| 156 | 157 | ||
| @@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 158 | int bind, int ref) | 159 | int bind, int ref) |
| 159 | { | 160 | { |
| 160 | unsigned char *b = skb_tail_pointer(skb); | 161 | unsigned char *b = skb_tail_pointer(skb); |
| 161 | struct tcf_skbedit *d = a->priv; | 162 | struct tcf_skbedit *d = to_skbedit(a); |
| 162 | struct tc_skbedit opt = { | 163 | struct tc_skbedit opt = { |
| 163 | .index = d->tcf_index, | 164 | .index = d->tcf_index, |
| 164 | .refcnt = d->tcf_refcnt - ref, | 165 | .refcnt = d->tcf_refcnt - ref, |
| @@ -194,14 +195,14 @@ nla_put_failure: | |||
| 194 | 195 | ||
| 195 | static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, | 196 | static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, |
| 196 | struct netlink_callback *cb, int type, | 197 | struct netlink_callback *cb, int type, |
| 197 | struct tc_action *a) | 198 | const struct tc_action_ops *ops) |
| 198 | { | 199 | { |
| 199 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); | 200 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
| 200 | 201 | ||
| 201 | return tcf_generic_walker(tn, skb, cb, type, a); | 202 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 202 | } | 203 | } |
| 203 | 204 | ||
| 204 | static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index) | 205 | static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index) |
| 205 | { | 206 | { |
| 206 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); | 207 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
| 207 | 208 | ||
| @@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = { | |||
| 217 | .init = tcf_skbedit_init, | 218 | .init = tcf_skbedit_init, |
| 218 | .walk = tcf_skbedit_walker, | 219 | .walk = tcf_skbedit_walker, |
| 219 | .lookup = tcf_skbedit_search, | 220 | .lookup = tcf_skbedit_search, |
| 221 | .size = sizeof(struct tcf_skbedit), | ||
| 220 | }; | 222 | }; |
| 221 | 223 | ||
| 222 | static __net_init int skbedit_init_net(struct net *net) | 224 | static __net_init int skbedit_init_net(struct net *net) |
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index db9b7ed570ba..691409de3e1a 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c | |||
| @@ -22,11 +22,12 @@ | |||
| 22 | #define VLAN_TAB_MASK 15 | 22 | #define VLAN_TAB_MASK 15 |
| 23 | 23 | ||
| 24 | static int vlan_net_id; | 24 | static int vlan_net_id; |
| 25 | static struct tc_action_ops act_vlan_ops; | ||
| 25 | 26 | ||
| 26 | static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, | 27 | static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, |
| 27 | struct tcf_result *res) | 28 | struct tcf_result *res) |
| 28 | { | 29 | { |
| 29 | struct tcf_vlan *v = a->priv; | 30 | struct tcf_vlan *v = to_vlan(a); |
| 30 | int action; | 31 | int action; |
| 31 | int err; | 32 | int err; |
| 32 | 33 | ||
| @@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = { | |||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | static int tcf_vlan_init(struct net *net, struct nlattr *nla, | 70 | static int tcf_vlan_init(struct net *net, struct nlattr *nla, |
| 70 | struct nlattr *est, struct tc_action *a, | 71 | struct nlattr *est, struct tc_action **a, |
| 71 | int ovr, int bind) | 72 | int ovr, int bind) |
| 72 | { | 73 | { |
| 73 | struct tc_action_net *tn = net_generic(net, vlan_net_id); | 74 | 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 | case TCA_VLAN_ACT_PUSH: | 101 | case TCA_VLAN_ACT_PUSH: |
| 101 | if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { | 102 | if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { |
| 102 | if (exists) | 103 | if (exists) |
| 103 | tcf_hash_release(a, bind); | 104 | tcf_hash_release(*a, bind); |
| 104 | return -EINVAL; | 105 | return -EINVAL; |
| 105 | } | 106 | } |
| 106 | push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); | 107 | push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); |
| 107 | if (push_vid >= VLAN_VID_MASK) { | 108 | if (push_vid >= VLAN_VID_MASK) { |
| 108 | if (exists) | 109 | if (exists) |
| 109 | tcf_hash_release(a, bind); | 110 | tcf_hash_release(*a, bind); |
| 110 | return -ERANGE; | 111 | return -ERANGE; |
| 111 | } | 112 | } |
| 112 | 113 | ||
| @@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 125 | break; | 126 | break; |
| 126 | default: | 127 | default: |
| 127 | if (exists) | 128 | if (exists) |
| 128 | tcf_hash_release(a, bind); | 129 | tcf_hash_release(*a, bind); |
| 129 | return -EINVAL; | 130 | return -EINVAL; |
| 130 | } | 131 | } |
| 131 | action = parm->v_action; | 132 | action = parm->v_action; |
| 132 | 133 | ||
| 133 | if (!exists) { | 134 | if (!exists) { |
| 134 | ret = tcf_hash_create(tn, parm->index, est, a, | 135 | ret = tcf_hash_create(tn, parm->index, est, a, |
| 135 | sizeof(*v), bind, false); | 136 | &act_vlan_ops, bind, false); |
| 136 | if (ret) | 137 | if (ret) |
| 137 | return ret; | 138 | return ret; |
| 138 | 139 | ||
| 139 | ret = ACT_P_CREATED; | 140 | ret = ACT_P_CREATED; |
| 140 | } else { | 141 | } else { |
| 141 | tcf_hash_release(a, bind); | 142 | tcf_hash_release(*a, bind); |
| 142 | if (!ovr) | 143 | if (!ovr) |
| 143 | return -EEXIST; | 144 | return -EEXIST; |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | v = to_vlan(a); | 147 | v = to_vlan(*a); |
| 147 | 148 | ||
| 148 | spin_lock_bh(&v->tcf_lock); | 149 | spin_lock_bh(&v->tcf_lock); |
| 149 | 150 | ||
| @@ -156,7 +157,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 156 | spin_unlock_bh(&v->tcf_lock); | 157 | spin_unlock_bh(&v->tcf_lock); |
| 157 | 158 | ||
| 158 | if (ret == ACT_P_CREATED) | 159 | if (ret == ACT_P_CREATED) |
| 159 | tcf_hash_insert(tn, a); | 160 | tcf_hash_insert(tn, *a); |
| 160 | return ret; | 161 | return ret; |
| 161 | } | 162 | } |
| 162 | 163 | ||
| @@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 164 | int bind, int ref) | 165 | int bind, int ref) |
| 165 | { | 166 | { |
| 166 | unsigned char *b = skb_tail_pointer(skb); | 167 | unsigned char *b = skb_tail_pointer(skb); |
| 167 | struct tcf_vlan *v = a->priv; | 168 | struct tcf_vlan *v = to_vlan(a); |
| 168 | struct tc_vlan opt = { | 169 | struct tc_vlan opt = { |
| 169 | .index = v->tcf_index, | 170 | .index = v->tcf_index, |
| 170 | .refcnt = v->tcf_refcnt - ref, | 171 | .refcnt = v->tcf_refcnt - ref, |
| @@ -195,14 +196,14 @@ nla_put_failure: | |||
| 195 | 196 | ||
| 196 | static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, | 197 | static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, |
| 197 | struct netlink_callback *cb, int type, | 198 | struct netlink_callback *cb, int type, |
| 198 | struct tc_action *a) | 199 | const struct tc_action_ops *ops) |
| 199 | { | 200 | { |
| 200 | struct tc_action_net *tn = net_generic(net, vlan_net_id); | 201 | struct tc_action_net *tn = net_generic(net, vlan_net_id); |
| 201 | 202 | ||
| 202 | return tcf_generic_walker(tn, skb, cb, type, a); | 203 | return tcf_generic_walker(tn, skb, cb, type, ops); |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index) | 206 | static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index) |
| 206 | { | 207 | { |
| 207 | struct tc_action_net *tn = net_generic(net, vlan_net_id); | 208 | struct tc_action_net *tn = net_generic(net, vlan_net_id); |
| 208 | 209 | ||
| @@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = { | |||
| 218 | .init = tcf_vlan_init, | 219 | .init = tcf_vlan_init, |
| 219 | .walk = tcf_vlan_walker, | 220 | .walk = tcf_vlan_walker, |
| 220 | .lookup = tcf_vlan_search, | 221 | .lookup = tcf_vlan_search, |
| 222 | .size = sizeof(struct tcf_vlan), | ||
| 221 | }; | 223 | }; |
| 222 | 224 | ||
| 223 | static __net_init int vlan_init_net(struct net *net) | 225 | static __net_init int vlan_init_net(struct net *net) |
