diff options
-rw-r--r-- | include/net/act_api.h | 136 | ||||
-rw-r--r-- | include/net/act_generic.h | 142 | ||||
-rw-r--r-- | include/net/pkt_act.h | 273 | ||||
-rw-r--r-- | include/net/tc_act/tc_defact.h | 13 | ||||
-rw-r--r-- | include/net/tc_act/tc_gact.h | 18 | ||||
-rw-r--r-- | include/net/tc_act/tc_ipt.h | 15 | ||||
-rw-r--r-- | include/net/tc_act/tc_mirred.h | 17 | ||||
-rw-r--r-- | include/net/tc_act/tc_pedit.h | 15 | ||||
-rw-r--r-- | net/sched/act_api.c | 246 | ||||
-rw-r--r-- | net/sched/act_gact.c | 142 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 175 | ||||
-rw-r--r-- | net/sched/act_mirred.c | 159 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 166 | ||||
-rw-r--r-- | net/sched/act_police.c | 508 | ||||
-rw-r--r-- | net/sched/act_simple.c | 183 |
15 files changed, 1061 insertions, 1147 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h index 11e9eaf79f5a..8b06c2f3657f 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h | |||
@@ -8,70 +8,110 @@ | |||
8 | #include <net/sch_generic.h> | 8 | #include <net/sch_generic.h> |
9 | #include <net/pkt_sched.h> | 9 | #include <net/pkt_sched.h> |
10 | 10 | ||
11 | #define tca_gen(name) \ | 11 | struct tcf_common { |
12 | struct tcf_##name *next; \ | 12 | struct tcf_common *tcfc_next; |
13 | u32 index; \ | 13 | u32 tcfc_index; |
14 | int refcnt; \ | 14 | int tcfc_refcnt; |
15 | int bindcnt; \ | 15 | int tcfc_bindcnt; |
16 | u32 capab; \ | 16 | u32 tcfc_capab; |
17 | int action; \ | 17 | int tcfc_action; |
18 | struct tcf_t tm; \ | 18 | struct tcf_t tcfc_tm; |
19 | struct gnet_stats_basic bstats; \ | 19 | struct gnet_stats_basic tcfc_bstats; |
20 | struct gnet_stats_queue qstats; \ | 20 | struct gnet_stats_queue tcfc_qstats; |
21 | struct gnet_stats_rate_est rate_est; \ | 21 | struct gnet_stats_rate_est tcfc_rate_est; |
22 | spinlock_t *stats_lock; \ | 22 | spinlock_t *tcfc_stats_lock; |
23 | spinlock_t lock | 23 | spinlock_t tcfc_lock; |
24 | 24 | }; | |
25 | struct tcf_police | 25 | #define tcf_next common.tcfc_next |
26 | { | 26 | #define tcf_index common.tcfc_index |
27 | tca_gen(police); | 27 | #define tcf_refcnt common.tcfc_refcnt |
28 | int result; | 28 | #define tcf_bindcnt common.tcfc_bindcnt |
29 | u32 ewma_rate; | 29 | #define tcf_capab common.tcfc_capab |
30 | u32 burst; | 30 | #define tcf_action common.tcfc_action |
31 | u32 mtu; | 31 | #define tcf_tm common.tcfc_tm |
32 | u32 toks; | 32 | #define tcf_bstats common.tcfc_bstats |
33 | u32 ptoks; | 33 | #define tcf_qstats common.tcfc_qstats |
34 | psched_time_t t_c; | 34 | #define tcf_rate_est common.tcfc_rate_est |
35 | struct qdisc_rate_table *R_tab; | 35 | #define tcf_stats_lock common.tcfc_stats_lock |
36 | struct qdisc_rate_table *P_tab; | 36 | #define tcf_lock common.tcfc_lock |
37 | |||
38 | struct tcf_police { | ||
39 | struct tcf_common common; | ||
40 | int tcfp_result; | ||
41 | u32 tcfp_ewma_rate; | ||
42 | u32 tcfp_burst; | ||
43 | u32 tcfp_mtu; | ||
44 | u32 tcfp_toks; | ||
45 | u32 tcfp_ptoks; | ||
46 | psched_time_t tcfp_t_c; | ||
47 | struct qdisc_rate_table *tcfp_R_tab; | ||
48 | struct qdisc_rate_table *tcfp_P_tab; | ||
37 | }; | 49 | }; |
50 | #define to_police(pc) \ | ||
51 | container_of(pc, struct tcf_police, common) | ||
52 | |||
53 | struct tcf_hashinfo { | ||
54 | struct tcf_common **htab; | ||
55 | unsigned int hmask; | ||
56 | rwlock_t *lock; | ||
57 | }; | ||
58 | |||
59 | static inline unsigned int tcf_hash(u32 index, unsigned int hmask) | ||
60 | { | ||
61 | return index & hmask; | ||
62 | } | ||
38 | 63 | ||
39 | #ifdef CONFIG_NET_CLS_ACT | 64 | #ifdef CONFIG_NET_CLS_ACT |
40 | 65 | ||
41 | #define ACT_P_CREATED 1 | 66 | #define ACT_P_CREATED 1 |
42 | #define ACT_P_DELETED 1 | 67 | #define ACT_P_DELETED 1 |
43 | 68 | ||
44 | struct tcf_act_hdr | 69 | struct tcf_act_hdr { |
45 | { | 70 | struct tcf_common common; |
46 | tca_gen(act_hdr); | ||
47 | }; | 71 | }; |
48 | 72 | ||
49 | struct tc_action | 73 | struct tc_action { |
50 | { | 74 | void *priv; |
51 | void *priv; | 75 | struct tc_action_ops *ops; |
52 | struct tc_action_ops *ops; | 76 | __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ |
53 | __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ | 77 | __u32 order; |
54 | __u32 order; | 78 | struct tc_action *next; |
55 | struct tc_action *next; | ||
56 | }; | 79 | }; |
57 | 80 | ||
58 | #define TCA_CAP_NONE 0 | 81 | #define TCA_CAP_NONE 0 |
59 | struct tc_action_ops | 82 | struct tc_action_ops { |
60 | { | ||
61 | struct tc_action_ops *next; | 83 | struct tc_action_ops *next; |
84 | struct tcf_hashinfo *hinfo; | ||
62 | char kind[IFNAMSIZ]; | 85 | char kind[IFNAMSIZ]; |
63 | __u32 type; /* TBD to match kind */ | 86 | __u32 type; /* TBD to match kind */ |
64 | __u32 capab; /* capabilities includes 4 bit version */ | 87 | __u32 capab; /* capabilities includes 4 bit version */ |
65 | struct module *owner; | 88 | struct module *owner; |
66 | int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); | 89 | int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); |
67 | int (*get_stats)(struct sk_buff *, struct tc_action *); | 90 | int (*get_stats)(struct sk_buff *, struct tc_action *); |
68 | int (*dump)(struct sk_buff *, struct tc_action *,int , int); | 91 | int (*dump)(struct sk_buff *, struct tc_action *, int, int); |
69 | int (*cleanup)(struct tc_action *, int bind); | 92 | int (*cleanup)(struct tc_action *, int bind); |
70 | int (*lookup)(struct tc_action *, u32 ); | 93 | int (*lookup)(struct tc_action *, u32); |
71 | int (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int ); | 94 | int (*init)(struct rtattr *, struct rtattr *, struct tc_action *, int , int); |
72 | int (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *); | 95 | int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *); |
73 | }; | 96 | }; |
74 | 97 | ||
98 | extern struct tcf_common *tcf_hash_lookup(u32 index, | ||
99 | struct tcf_hashinfo *hinfo); | ||
100 | extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo); | ||
101 | extern int tcf_hash_release(struct tcf_common *p, int bind, | ||
102 | struct tcf_hashinfo *hinfo); | ||
103 | extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | ||
104 | int type, struct tc_action *a); | ||
105 | extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo); | ||
106 | extern int tcf_hash_search(struct tc_action *a, u32 index); | ||
107 | extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, | ||
108 | int bind, struct tcf_hashinfo *hinfo); | ||
109 | extern struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, | ||
110 | struct tc_action *a, int size, | ||
111 | int bind, u32 *idx_gen, | ||
112 | struct tcf_hashinfo *hinfo); | ||
113 | extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo); | ||
114 | |||
75 | extern int tcf_register_action(struct tc_action_ops *a); | 115 | extern int tcf_register_action(struct tc_action_ops *a); |
76 | extern int tcf_unregister_action(struct tc_action_ops *a); | 116 | extern int tcf_unregister_action(struct tc_action_ops *a); |
77 | extern void tcf_action_destroy(struct tc_action *a, int bind); | 117 | extern void tcf_action_destroy(struct tc_action *a, int bind); |
@@ -96,17 +136,17 @@ tcf_police_release(struct tcf_police *p, int bind) | |||
96 | int ret = 0; | 136 | int ret = 0; |
97 | #ifdef CONFIG_NET_CLS_ACT | 137 | #ifdef CONFIG_NET_CLS_ACT |
98 | if (p) { | 138 | if (p) { |
99 | if (bind) { | 139 | if (bind) |
100 | p->bindcnt--; | 140 | p->tcf_bindcnt--; |
101 | } | 141 | |
102 | p->refcnt--; | 142 | p->tcf_refcnt--; |
103 | if (p->refcnt <= 0 && !p->bindcnt) { | 143 | if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { |
104 | tcf_police_destroy(p); | 144 | tcf_police_destroy(p); |
105 | ret = 1; | 145 | ret = 1; |
106 | } | 146 | } |
107 | } | 147 | } |
108 | #else | 148 | #else |
109 | if (p && --p->refcnt == 0) | 149 | if (p && --p->tcf_refcnt == 0) |
110 | tcf_police_destroy(p); | 150 | tcf_police_destroy(p); |
111 | 151 | ||
112 | #endif /* CONFIG_NET_CLS_ACT */ | 152 | #endif /* CONFIG_NET_CLS_ACT */ |
diff --git a/include/net/act_generic.h b/include/net/act_generic.h deleted file mode 100644 index c9daa7e52300..000000000000 --- a/include/net/act_generic.h +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * include/net/act_generic.h | ||
3 | * | ||
4 | */ | ||
5 | #ifndef _NET_ACT_GENERIC_H | ||
6 | #define _NET_ACT_GENERIC_H | ||
7 | static inline int tcf_defact_release(struct tcf_defact *p, int bind) | ||
8 | { | ||
9 | int ret = 0; | ||
10 | if (p) { | ||
11 | if (bind) { | ||
12 | p->bindcnt--; | ||
13 | } | ||
14 | p->refcnt--; | ||
15 | if (p->bindcnt <= 0 && p->refcnt <= 0) { | ||
16 | kfree(p->defdata); | ||
17 | tcf_hash_destroy(p); | ||
18 | ret = 1; | ||
19 | } | ||
20 | } | ||
21 | return ret; | ||
22 | } | ||
23 | |||
24 | static inline int | ||
25 | alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) | ||
26 | { | ||
27 | p->defdata = kmalloc(datalen, GFP_KERNEL); | ||
28 | if (p->defdata == NULL) | ||
29 | return -ENOMEM; | ||
30 | p->datalen = datalen; | ||
31 | memcpy(p->defdata, defdata, datalen); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static inline int | ||
36 | realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) | ||
37 | { | ||
38 | /* safer to be just brute force for now */ | ||
39 | kfree(p->defdata); | ||
40 | return alloc_defdata(p, datalen, defdata); | ||
41 | } | ||
42 | |||
43 | static inline int | ||
44 | tcf_defact_init(struct rtattr *rta, struct rtattr *est, | ||
45 | struct tc_action *a, int ovr, int bind) | ||
46 | { | ||
47 | struct rtattr *tb[TCA_DEF_MAX]; | ||
48 | struct tc_defact *parm; | ||
49 | struct tcf_defact *p; | ||
50 | void *defdata; | ||
51 | u32 datalen = 0; | ||
52 | int ret = 0; | ||
53 | |||
54 | if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) | ||
55 | return -EINVAL; | ||
56 | |||
57 | if (tb[TCA_DEF_PARMS - 1] == NULL || | ||
58 | RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); | ||
62 | defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); | ||
63 | if (defdata == NULL) | ||
64 | return -EINVAL; | ||
65 | |||
66 | datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); | ||
67 | if (datalen <= 0) | ||
68 | return -EINVAL; | ||
69 | |||
70 | p = tcf_hash_check(parm->index, a, ovr, bind); | ||
71 | if (p == NULL) { | ||
72 | p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); | ||
73 | if (p == NULL) | ||
74 | return -ENOMEM; | ||
75 | |||
76 | ret = alloc_defdata(p, datalen, defdata); | ||
77 | if (ret < 0) { | ||
78 | kfree(p); | ||
79 | return ret; | ||
80 | } | ||
81 | ret = ACT_P_CREATED; | ||
82 | } else { | ||
83 | if (!ovr) { | ||
84 | tcf_defact_release(p, bind); | ||
85 | return -EEXIST; | ||
86 | } | ||
87 | realloc_defdata(p, datalen, defdata); | ||
88 | } | ||
89 | |||
90 | spin_lock_bh(&p->lock); | ||
91 | p->action = parm->action; | ||
92 | spin_unlock_bh(&p->lock); | ||
93 | if (ret == ACT_P_CREATED) | ||
94 | tcf_hash_insert(p); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static inline int tcf_defact_cleanup(struct tc_action *a, int bind) | ||
99 | { | ||
100 | struct tcf_defact *p = PRIV(a, defact); | ||
101 | |||
102 | if (p != NULL) | ||
103 | return tcf_defact_release(p, bind); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static inline int | ||
108 | tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | ||
109 | { | ||
110 | unsigned char *b = skb->tail; | ||
111 | struct tc_defact opt; | ||
112 | struct tcf_defact *p = PRIV(a, defact); | ||
113 | struct tcf_t t; | ||
114 | |||
115 | opt.index = p->index; | ||
116 | opt.refcnt = p->refcnt - ref; | ||
117 | opt.bindcnt = p->bindcnt - bind; | ||
118 | opt.action = p->action; | ||
119 | RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); | ||
120 | RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata); | ||
121 | t.install = jiffies_to_clock_t(jiffies - p->tm.install); | ||
122 | t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | ||
123 | t.expires = jiffies_to_clock_t(p->tm.expires); | ||
124 | RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); | ||
125 | return skb->len; | ||
126 | |||
127 | rtattr_failure: | ||
128 | skb_trim(skb, b - skb->data); | ||
129 | return -1; | ||
130 | } | ||
131 | |||
132 | #define tca_use_default_ops \ | ||
133 | .dump = tcf_defact_dump, \ | ||
134 | .cleanup = tcf_defact_cleanup, \ | ||
135 | .init = tcf_defact_init, \ | ||
136 | .walk = tcf_generic_walker, \ | ||
137 | |||
138 | #define tca_use_default_defines(name) \ | ||
139 | static u32 idx_gen; \ | ||
140 | static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \ | ||
141 | static DEFINE_RWLOCK(##name_lock); | ||
142 | #endif /* _NET_ACT_GENERIC_H */ | ||
diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h deleted file mode 100644 index cf5e4d2e4c21..000000000000 --- a/include/net/pkt_act.h +++ /dev/null | |||
@@ -1,273 +0,0 @@ | |||
1 | #ifndef __NET_PKT_ACT_H | ||
2 | #define __NET_PKT_ACT_H | ||
3 | |||
4 | #include <asm/uaccess.h> | ||
5 | #include <asm/system.h> | ||
6 | #include <linux/bitops.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/socket.h> | ||
13 | #include <linux/sockios.h> | ||
14 | #include <linux/in.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/rtnetlink.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/proc_fs.h> | ||
22 | #include <net/sock.h> | ||
23 | #include <net/pkt_sched.h> | ||
24 | |||
25 | #define tca_st(val) (struct tcf_##val *) | ||
26 | #define PRIV(a,name) ( tca_st(name) (a)->priv) | ||
27 | |||
28 | #if 0 /* control */ | ||
29 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
30 | #else | ||
31 | #define DPRINTK(format,args...) | ||
32 | #endif | ||
33 | |||
34 | #if 0 /* data */ | ||
35 | #define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
36 | #else | ||
37 | #define D2PRINTK(format,args...) | ||
38 | #endif | ||
39 | |||
40 | static __inline__ unsigned | ||
41 | tcf_hash(u32 index) | ||
42 | { | ||
43 | return index & MY_TAB_MASK; | ||
44 | } | ||
45 | |||
46 | /* probably move this from being inline | ||
47 | * and put into act_generic | ||
48 | */ | ||
49 | static inline void | ||
50 | tcf_hash_destroy(struct tcf_st *p) | ||
51 | { | ||
52 | unsigned h = tcf_hash(p->index); | ||
53 | struct tcf_st **p1p; | ||
54 | |||
55 | for (p1p = &tcf_ht[h]; *p1p; p1p = &(*p1p)->next) { | ||
56 | if (*p1p == p) { | ||
57 | write_lock_bh(&tcf_t_lock); | ||
58 | *p1p = p->next; | ||
59 | write_unlock_bh(&tcf_t_lock); | ||
60 | #ifdef CONFIG_NET_ESTIMATOR | ||
61 | gen_kill_estimator(&p->bstats, &p->rate_est); | ||
62 | #endif | ||
63 | kfree(p); | ||
64 | return; | ||
65 | } | ||
66 | } | ||
67 | BUG_TRAP(0); | ||
68 | } | ||
69 | |||
70 | static inline int | ||
71 | tcf_hash_release(struct tcf_st *p, int bind ) | ||
72 | { | ||
73 | int ret = 0; | ||
74 | if (p) { | ||
75 | if (bind) { | ||
76 | p->bindcnt--; | ||
77 | } | ||
78 | p->refcnt--; | ||
79 | if(p->bindcnt <=0 && p->refcnt <= 0) { | ||
80 | tcf_hash_destroy(p); | ||
81 | ret = 1; | ||
82 | } | ||
83 | } | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static __inline__ int | ||
88 | tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | ||
89 | struct tc_action *a) | ||
90 | { | ||
91 | struct tcf_st *p; | ||
92 | int err =0, index = -1,i= 0, s_i = 0, n_i = 0; | ||
93 | struct rtattr *r ; | ||
94 | |||
95 | read_lock(&tcf_t_lock); | ||
96 | |||
97 | s_i = cb->args[0]; | ||
98 | |||
99 | for (i = 0; i < MY_TAB_SIZE; i++) { | ||
100 | p = tcf_ht[tcf_hash(i)]; | ||
101 | |||
102 | for (; p; p = p->next) { | ||
103 | index++; | ||
104 | if (index < s_i) | ||
105 | continue; | ||
106 | a->priv = p; | ||
107 | a->order = n_i; | ||
108 | r = (struct rtattr*) skb->tail; | ||
109 | RTA_PUT(skb, a->order, 0, NULL); | ||
110 | err = tcf_action_dump_1(skb, a, 0, 0); | ||
111 | if (0 > err) { | ||
112 | index--; | ||
113 | skb_trim(skb, (u8*)r - skb->data); | ||
114 | goto done; | ||
115 | } | ||
116 | r->rta_len = skb->tail - (u8*)r; | ||
117 | n_i++; | ||
118 | if (n_i >= TCA_ACT_MAX_PRIO) { | ||
119 | goto done; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | done: | ||
124 | read_unlock(&tcf_t_lock); | ||
125 | if (n_i) | ||
126 | cb->args[0] += n_i; | ||
127 | return n_i; | ||
128 | |||
129 | rtattr_failure: | ||
130 | skb_trim(skb, (u8*)r - skb->data); | ||
131 | goto done; | ||
132 | } | ||
133 | |||
134 | static __inline__ int | ||
135 | tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | ||
136 | { | ||
137 | struct tcf_st *p, *s_p; | ||
138 | struct rtattr *r ; | ||
139 | int i= 0, n_i = 0; | ||
140 | |||
141 | r = (struct rtattr*) skb->tail; | ||
142 | RTA_PUT(skb, a->order, 0, NULL); | ||
143 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); | ||
144 | for (i = 0; i < MY_TAB_SIZE; i++) { | ||
145 | p = tcf_ht[tcf_hash(i)]; | ||
146 | |||
147 | while (p != NULL) { | ||
148 | s_p = p->next; | ||
149 | if (ACT_P_DELETED == tcf_hash_release(p, 0)) { | ||
150 | module_put(a->ops->owner); | ||
151 | } | ||
152 | n_i++; | ||
153 | p = s_p; | ||
154 | } | ||
155 | } | ||
156 | RTA_PUT(skb, TCA_FCNT, 4, &n_i); | ||
157 | r->rta_len = skb->tail - (u8*)r; | ||
158 | |||
159 | return n_i; | ||
160 | rtattr_failure: | ||
161 | skb_trim(skb, (u8*)r - skb->data); | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | static __inline__ int | ||
166 | tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, | ||
167 | struct tc_action *a) | ||
168 | { | ||
169 | if (type == RTM_DELACTION) { | ||
170 | return tcf_del_walker(skb,a); | ||
171 | } else if (type == RTM_GETACTION) { | ||
172 | return tcf_dump_walker(skb,cb,a); | ||
173 | } else { | ||
174 | printk("tcf_generic_walker: unknown action %d\n",type); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | static __inline__ struct tcf_st * | ||
180 | tcf_hash_lookup(u32 index) | ||
181 | { | ||
182 | struct tcf_st *p; | ||
183 | |||
184 | read_lock(&tcf_t_lock); | ||
185 | for (p = tcf_ht[tcf_hash(index)]; p; p = p->next) { | ||
186 | if (p->index == index) | ||
187 | break; | ||
188 | } | ||
189 | read_unlock(&tcf_t_lock); | ||
190 | return p; | ||
191 | } | ||
192 | |||
193 | static __inline__ u32 | ||
194 | tcf_hash_new_index(void) | ||
195 | { | ||
196 | do { | ||
197 | if (++idx_gen == 0) | ||
198 | idx_gen = 1; | ||
199 | } while (tcf_hash_lookup(idx_gen)); | ||
200 | |||
201 | return idx_gen; | ||
202 | } | ||
203 | |||
204 | |||
205 | static inline int | ||
206 | tcf_hash_search(struct tc_action *a, u32 index) | ||
207 | { | ||
208 | struct tcf_st *p = tcf_hash_lookup(index); | ||
209 | |||
210 | if (p != NULL) { | ||
211 | a->priv = p; | ||
212 | return 1; | ||
213 | } | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | #ifdef CONFIG_NET_ACT_INIT | ||
218 | static inline struct tcf_st * | ||
219 | tcf_hash_check(u32 index, struct tc_action *a, int ovr, int bind) | ||
220 | { | ||
221 | struct tcf_st *p = NULL; | ||
222 | if (index && (p = tcf_hash_lookup(index)) != NULL) { | ||
223 | if (bind) { | ||
224 | p->bindcnt++; | ||
225 | p->refcnt++; | ||
226 | } | ||
227 | a->priv = p; | ||
228 | } | ||
229 | return p; | ||
230 | } | ||
231 | |||
232 | static inline struct tcf_st * | ||
233 | tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind) | ||
234 | { | ||
235 | struct tcf_st *p = NULL; | ||
236 | |||
237 | p = kmalloc(size, GFP_KERNEL); | ||
238 | if (p == NULL) | ||
239 | return p; | ||
240 | |||
241 | memset(p, 0, size); | ||
242 | p->refcnt = 1; | ||
243 | |||
244 | if (bind) { | ||
245 | p->bindcnt = 1; | ||
246 | } | ||
247 | |||
248 | spin_lock_init(&p->lock); | ||
249 | p->stats_lock = &p->lock; | ||
250 | p->index = index ? : tcf_hash_new_index(); | ||
251 | p->tm.install = jiffies; | ||
252 | p->tm.lastuse = jiffies; | ||
253 | #ifdef CONFIG_NET_ESTIMATOR | ||
254 | if (est) | ||
255 | gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); | ||
256 | #endif | ||
257 | a->priv = (void *) p; | ||
258 | return p; | ||
259 | } | ||
260 | |||
261 | static inline void tcf_hash_insert(struct tcf_st *p) | ||
262 | { | ||
263 | unsigned h = tcf_hash(p->index); | ||
264 | |||
265 | write_lock_bh(&tcf_t_lock); | ||
266 | p->next = tcf_ht[h]; | ||
267 | tcf_ht[h] = p; | ||
268 | write_unlock_bh(&tcf_t_lock); | ||
269 | } | ||
270 | |||
271 | #endif | ||
272 | |||
273 | #endif | ||
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h index 463aa671f95d..65f024b80958 100644 --- a/include/net/tc_act/tc_defact.h +++ b/include/net/tc_act/tc_defact.h | |||
@@ -3,11 +3,12 @@ | |||
3 | 3 | ||
4 | #include <net/act_api.h> | 4 | #include <net/act_api.h> |
5 | 5 | ||
6 | struct tcf_defact | 6 | struct tcf_defact { |
7 | { | 7 | struct tcf_common common; |
8 | tca_gen(defact); | 8 | u32 tcfd_datalen; |
9 | u32 datalen; | 9 | void *tcfd_defdata; |
10 | void *defdata; | ||
11 | }; | 10 | }; |
11 | #define to_defact(pc) \ | ||
12 | container_of(pc, struct tcf_defact, common) | ||
12 | 13 | ||
13 | #endif | 14 | #endif /* __NET_TC_DEF_H */ |
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h index 59f0d9628ad1..9e3f6767b80e 100644 --- a/include/net/tc_act/tc_gact.h +++ b/include/net/tc_act/tc_gact.h | |||
@@ -3,15 +3,15 @@ | |||
3 | 3 | ||
4 | #include <net/act_api.h> | 4 | #include <net/act_api.h> |
5 | 5 | ||
6 | struct tcf_gact | 6 | struct tcf_gact { |
7 | { | 7 | struct tcf_common common; |
8 | tca_gen(gact); | ||
9 | #ifdef CONFIG_GACT_PROB | 8 | #ifdef CONFIG_GACT_PROB |
10 | u16 ptype; | 9 | u16 tcfg_ptype; |
11 | u16 pval; | 10 | u16 tcfg_pval; |
12 | int paction; | 11 | int tcfg_paction; |
13 | #endif | 12 | #endif |
14 | |||
15 | }; | 13 | }; |
16 | 14 | #define to_gact(pc) \ | |
17 | #endif | 15 | container_of(pc, struct tcf_gact, common) |
16 | |||
17 | #endif /* __NET_TC_GACT_H */ | ||
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h index cb37ad08427f..f7d25dfcc4b7 100644 --- a/include/net/tc_act/tc_ipt.h +++ b/include/net/tc_act/tc_ipt.h | |||
@@ -5,12 +5,13 @@ | |||
5 | 5 | ||
6 | struct xt_entry_target; | 6 | struct xt_entry_target; |
7 | 7 | ||
8 | struct tcf_ipt | 8 | struct tcf_ipt { |
9 | { | 9 | struct tcf_common common; |
10 | tca_gen(ipt); | 10 | u32 tcfi_hook; |
11 | u32 hook; | 11 | char *tcfi_tname; |
12 | char *tname; | 12 | struct xt_entry_target *tcfi_t; |
13 | struct xt_entry_target *t; | ||
14 | }; | 13 | }; |
14 | #define to_ipt(pc) \ | ||
15 | container_of(pc, struct tcf_ipt, common) | ||
15 | 16 | ||
16 | #endif | 17 | #endif /* __NET_TC_IPT_H */ |
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h index b5c32f65c12c..ceac661cdfd5 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h | |||
@@ -3,13 +3,14 @@ | |||
3 | 3 | ||
4 | #include <net/act_api.h> | 4 | #include <net/act_api.h> |
5 | 5 | ||
6 | struct tcf_mirred | 6 | struct tcf_mirred { |
7 | { | 7 | struct tcf_common common; |
8 | tca_gen(mirred); | 8 | int tcfm_eaction; |
9 | int eaction; | 9 | int tcfm_ifindex; |
10 | int ifindex; | 10 | int tcfm_ok_push; |
11 | int ok_push; | 11 | struct net_device *tcfm_dev; |
12 | struct net_device *dev; | ||
13 | }; | 12 | }; |
13 | #define to_mirred(pc) \ | ||
14 | container_of(pc, struct tcf_mirred, common) | ||
14 | 15 | ||
15 | #endif | 16 | #endif /* __NET_TC_MIR_H */ |
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h index eb21689d759d..e6f6e15956f5 100644 --- a/include/net/tc_act/tc_pedit.h +++ b/include/net/tc_act/tc_pedit.h | |||
@@ -3,12 +3,13 @@ | |||
3 | 3 | ||
4 | #include <net/act_api.h> | 4 | #include <net/act_api.h> |
5 | 5 | ||
6 | struct tcf_pedit | 6 | struct tcf_pedit { |
7 | { | 7 | struct tcf_common common; |
8 | tca_gen(pedit); | 8 | unsigned char tcfp_nkeys; |
9 | unsigned char nkeys; | 9 | unsigned char tcfp_flags; |
10 | unsigned char flags; | 10 | struct tc_pedit_key *tcfp_keys; |
11 | struct tc_pedit_key *keys; | ||
12 | }; | 11 | }; |
12 | #define to_pedit(pc) \ | ||
13 | container_of(pc, struct tcf_pedit, common) | ||
13 | 14 | ||
14 | #endif | 15 | #endif /* __NET_TC_PED_H */ |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 6990747d6d5a..835070e9169c 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -33,16 +33,230 @@ | |||
33 | #include <net/sch_generic.h> | 33 | #include <net/sch_generic.h> |
34 | #include <net/act_api.h> | 34 | #include <net/act_api.h> |
35 | 35 | ||
36 | #if 0 /* control */ | 36 | void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) |
37 | #define DPRINTK(format, args...) printk(KERN_DEBUG format, ##args) | 37 | { |
38 | #else | 38 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); |
39 | #define DPRINTK(format, args...) | 39 | struct tcf_common **p1p; |
40 | |||
41 | for (p1p = &hinfo->htab[h]; *p1p; p1p = &(*p1p)->tcfc_next) { | ||
42 | if (*p1p == p) { | ||
43 | write_lock_bh(hinfo->lock); | ||
44 | *p1p = p->tcfc_next; | ||
45 | write_unlock_bh(hinfo->lock); | ||
46 | #ifdef CONFIG_NET_ESTIMATOR | ||
47 | gen_kill_estimator(&p->tcfc_bstats, | ||
48 | &p->tcfc_rate_est); | ||
40 | #endif | 49 | #endif |
41 | #if 0 /* data */ | 50 | kfree(p); |
42 | #define D2PRINTK(format, args...) printk(KERN_DEBUG format, ##args) | 51 | return; |
43 | #else | 52 | } |
44 | #define D2PRINTK(format, args...) | 53 | } |
54 | BUG_TRAP(0); | ||
55 | } | ||
56 | EXPORT_SYMBOL(tcf_hash_destroy); | ||
57 | |||
58 | int tcf_hash_release(struct tcf_common *p, int bind, | ||
59 | struct tcf_hashinfo *hinfo) | ||
60 | { | ||
61 | int ret = 0; | ||
62 | |||
63 | if (p) { | ||
64 | if (bind) | ||
65 | p->tcfc_bindcnt--; | ||
66 | |||
67 | p->tcfc_refcnt--; | ||
68 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { | ||
69 | tcf_hash_destroy(p, hinfo); | ||
70 | ret = 1; | ||
71 | } | ||
72 | } | ||
73 | return ret; | ||
74 | } | ||
75 | EXPORT_SYMBOL(tcf_hash_release); | ||
76 | |||
77 | static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | ||
78 | struct tc_action *a, struct tcf_hashinfo *hinfo) | ||
79 | { | ||
80 | struct tcf_common *p; | ||
81 | int err = 0, index = -1,i = 0, s_i = 0, n_i = 0; | ||
82 | struct rtattr *r ; | ||
83 | |||
84 | read_lock(hinfo->lock); | ||
85 | |||
86 | s_i = cb->args[0]; | ||
87 | |||
88 | for (i = 0; i < (hinfo->hmask + 1); i++) { | ||
89 | p = hinfo->htab[tcf_hash(i, hinfo->hmask)]; | ||
90 | |||
91 | for (; p; p = p->tcfc_next) { | ||
92 | index++; | ||
93 | if (index < s_i) | ||
94 | continue; | ||
95 | a->priv = p; | ||
96 | a->order = n_i; | ||
97 | r = (struct rtattr*) skb->tail; | ||
98 | RTA_PUT(skb, a->order, 0, NULL); | ||
99 | err = tcf_action_dump_1(skb, a, 0, 0); | ||
100 | if (err < 0) { | ||
101 | index--; | ||
102 | skb_trim(skb, (u8*)r - skb->data); | ||
103 | goto done; | ||
104 | } | ||
105 | r->rta_len = skb->tail - (u8*)r; | ||
106 | n_i++; | ||
107 | if (n_i >= TCA_ACT_MAX_PRIO) | ||
108 | goto done; | ||
109 | } | ||
110 | } | ||
111 | done: | ||
112 | read_unlock(hinfo->lock); | ||
113 | if (n_i) | ||
114 | cb->args[0] += n_i; | ||
115 | return n_i; | ||
116 | |||
117 | rtattr_failure: | ||
118 | skb_trim(skb, (u8*)r - skb->data); | ||
119 | goto done; | ||
120 | } | ||
121 | |||
122 | static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, | ||
123 | struct tcf_hashinfo *hinfo) | ||
124 | { | ||
125 | struct tcf_common *p, *s_p; | ||
126 | struct rtattr *r ; | ||
127 | int i= 0, n_i = 0; | ||
128 | |||
129 | r = (struct rtattr*) skb->tail; | ||
130 | RTA_PUT(skb, a->order, 0, NULL); | ||
131 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); | ||
132 | for (i = 0; i < (hinfo->hmask + 1); i++) { | ||
133 | p = hinfo->htab[tcf_hash(i, hinfo->hmask)]; | ||
134 | |||
135 | while (p != NULL) { | ||
136 | s_p = p->tcfc_next; | ||
137 | if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) | ||
138 | module_put(a->ops->owner); | ||
139 | n_i++; | ||
140 | p = s_p; | ||
141 | } | ||
142 | } | ||
143 | RTA_PUT(skb, TCA_FCNT, 4, &n_i); | ||
144 | r->rta_len = skb->tail - (u8*)r; | ||
145 | |||
146 | return n_i; | ||
147 | rtattr_failure: | ||
148 | skb_trim(skb, (u8*)r - skb->data); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | ||
153 | int type, struct tc_action *a) | ||
154 | { | ||
155 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | ||
156 | |||
157 | if (type == RTM_DELACTION) { | ||
158 | return tcf_del_walker(skb, a, hinfo); | ||
159 | } else if (type == RTM_GETACTION) { | ||
160 | return tcf_dump_walker(skb, cb, a, hinfo); | ||
161 | } else { | ||
162 | printk("tcf_generic_walker: unknown action %d\n", type); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | } | ||
166 | EXPORT_SYMBOL(tcf_generic_walker); | ||
167 | |||
168 | struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) | ||
169 | { | ||
170 | struct tcf_common *p; | ||
171 | |||
172 | read_lock(hinfo->lock); | ||
173 | for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; | ||
174 | p = p->tcfc_next) { | ||
175 | if (p->tcfc_index == index) | ||
176 | break; | ||
177 | } | ||
178 | read_unlock(hinfo->lock); | ||
179 | |||
180 | return p; | ||
181 | } | ||
182 | EXPORT_SYMBOL(tcf_hash_lookup); | ||
183 | |||
184 | u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo) | ||
185 | { | ||
186 | u32 val = *idx_gen; | ||
187 | |||
188 | do { | ||
189 | if (++val == 0) | ||
190 | val = 1; | ||
191 | } while (tcf_hash_lookup(val, hinfo)); | ||
192 | |||
193 | return (*idx_gen = val); | ||
194 | } | ||
195 | EXPORT_SYMBOL(tcf_hash_new_index); | ||
196 | |||
197 | int tcf_hash_search(struct tc_action *a, u32 index) | ||
198 | { | ||
199 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | ||
200 | struct tcf_common *p = tcf_hash_lookup(index, hinfo); | ||
201 | |||
202 | if (p) { | ||
203 | a->priv = p; | ||
204 | return 1; | ||
205 | } | ||
206 | return 0; | ||
207 | } | ||
208 | EXPORT_SYMBOL(tcf_hash_search); | ||
209 | |||
210 | struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind, | ||
211 | struct tcf_hashinfo *hinfo) | ||
212 | { | ||
213 | struct tcf_common *p = NULL; | ||
214 | if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) { | ||
215 | if (bind) { | ||
216 | p->tcfc_bindcnt++; | ||
217 | p->tcfc_refcnt++; | ||
218 | } | ||
219 | a->priv = p; | ||
220 | } | ||
221 | return p; | ||
222 | } | ||
223 | EXPORT_SYMBOL(tcf_hash_check); | ||
224 | |||
225 | struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo) | ||
226 | { | ||
227 | struct tcf_common *p = kzalloc(size, GFP_KERNEL); | ||
228 | |||
229 | if (unlikely(!p)) | ||
230 | return p; | ||
231 | p->tcfc_refcnt = 1; | ||
232 | if (bind) | ||
233 | p->tcfc_bindcnt = 1; | ||
234 | |||
235 | spin_lock_init(&p->tcfc_lock); | ||
236 | p->tcfc_stats_lock = &p->tcfc_lock; | ||
237 | p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); | ||
238 | p->tcfc_tm.install = jiffies; | ||
239 | p->tcfc_tm.lastuse = jiffies; | ||
240 | #ifdef CONFIG_NET_ESTIMATOR | ||
241 | if (est) | ||
242 | gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, | ||
243 | p->tcfc_stats_lock, est); | ||
45 | #endif | 244 | #endif |
245 | a->priv = (void *) p; | ||
246 | return p; | ||
247 | } | ||
248 | EXPORT_SYMBOL(tcf_hash_create); | ||
249 | |||
250 | void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo) | ||
251 | { | ||
252 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); | ||
253 | |||
254 | write_lock_bh(hinfo->lock); | ||
255 | p->tcfc_next = hinfo->htab[h]; | ||
256 | hinfo->htab[h] = p; | ||
257 | write_unlock_bh(hinfo->lock); | ||
258 | } | ||
259 | EXPORT_SYMBOL(tcf_hash_insert); | ||
46 | 260 | ||
47 | static struct tc_action_ops *act_base = NULL; | 261 | static struct tc_action_ops *act_base = NULL; |
48 | static DEFINE_RWLOCK(act_mod_lock); | 262 | static DEFINE_RWLOCK(act_mod_lock); |
@@ -155,9 +369,6 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action *act, | |||
155 | 369 | ||
156 | if (skb->tc_verd & TC_NCLS) { | 370 | if (skb->tc_verd & TC_NCLS) { |
157 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); | 371 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); |
158 | D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n", | ||
159 | skb, skb->input_dev ? skb->input_dev->name : "xxx", | ||
160 | skb->dev->name); | ||
161 | ret = TC_ACT_OK; | 372 | ret = TC_ACT_OK; |
162 | goto exec_done; | 373 | goto exec_done; |
163 | } | 374 | } |
@@ -187,8 +398,6 @@ void tcf_action_destroy(struct tc_action *act, int bind) | |||
187 | 398 | ||
188 | for (a = act; a; a = act) { | 399 | for (a = act; a; a = act) { |
189 | if (a->ops && a->ops->cleanup) { | 400 | if (a->ops && a->ops->cleanup) { |
190 | DPRINTK("tcf_action_destroy destroying %p next %p\n", | ||
191 | a, a->next); | ||
192 | if (a->ops->cleanup(a, bind) == ACT_P_DELETED) | 401 | if (a->ops->cleanup(a, bind) == ACT_P_DELETED) |
193 | module_put(a->ops->owner); | 402 | module_put(a->ops->owner); |
194 | act = act->next; | 403 | act = act->next; |
@@ -331,7 +540,6 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, | |||
331 | if (*err != ACT_P_CREATED) | 540 | if (*err != ACT_P_CREATED) |
332 | module_put(a_o->owner); | 541 | module_put(a_o->owner); |
333 | a->ops = a_o; | 542 | a->ops = a_o; |
334 | DPRINTK("tcf_action_init_1: successfull %s\n", act_name); | ||
335 | 543 | ||
336 | *err = 0; | 544 | *err = 0; |
337 | return a; | 545 | return a; |
@@ -392,12 +600,12 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
392 | if (compat_mode) { | 600 | if (compat_mode) { |
393 | if (a->type == TCA_OLD_COMPAT) | 601 | if (a->type == TCA_OLD_COMPAT) |
394 | err = gnet_stats_start_copy_compat(skb, 0, | 602 | err = gnet_stats_start_copy_compat(skb, 0, |
395 | TCA_STATS, TCA_XSTATS, h->stats_lock, &d); | 603 | TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d); |
396 | else | 604 | else |
397 | return 0; | 605 | return 0; |
398 | } else | 606 | } else |
399 | err = gnet_stats_start_copy(skb, TCA_ACT_STATS, | 607 | err = gnet_stats_start_copy(skb, TCA_ACT_STATS, |
400 | h->stats_lock, &d); | 608 | h->tcf_stats_lock, &d); |
401 | 609 | ||
402 | if (err < 0) | 610 | if (err < 0) |
403 | goto errout; | 611 | goto errout; |
@@ -406,11 +614,11 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
406 | if (a->ops->get_stats(skb, a) < 0) | 614 | if (a->ops->get_stats(skb, a) < 0) |
407 | goto errout; | 615 | goto errout; |
408 | 616 | ||
409 | if (gnet_stats_copy_basic(&d, &h->bstats) < 0 || | 617 | if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 || |
410 | #ifdef CONFIG_NET_ESTIMATOR | 618 | #ifdef CONFIG_NET_ESTIMATOR |
411 | gnet_stats_copy_rate_est(&d, &h->rate_est) < 0 || | 619 | gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 || |
412 | #endif | 620 | #endif |
413 | gnet_stats_copy_queue(&d, &h->qstats) < 0) | 621 | gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0) |
414 | goto errout; | 622 | goto errout; |
415 | 623 | ||
416 | if (gnet_stats_finish_copy(&d) < 0) | 624 | if (gnet_stats_finish_copy(&d) < 0) |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index e75a147ad60f..6cff56696a81 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -34,48 +34,43 @@ | |||
34 | #include <linux/tc_act/tc_gact.h> | 34 | #include <linux/tc_act/tc_gact.h> |
35 | #include <net/tc_act/tc_gact.h> | 35 | #include <net/tc_act/tc_gact.h> |
36 | 36 | ||
37 | /* use generic hash table */ | 37 | #define GACT_TAB_MASK 15 |
38 | #define MY_TAB_SIZE 16 | 38 | static struct tcf_common *tcf_gact_ht[GACT_TAB_MASK + 1]; |
39 | #define MY_TAB_MASK 15 | 39 | static u32 gact_idx_gen; |
40 | |||
41 | static u32 idx_gen; | ||
42 | static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE]; | ||
43 | static DEFINE_RWLOCK(gact_lock); | 40 | static DEFINE_RWLOCK(gact_lock); |
44 | 41 | ||
45 | /* ovewrride the defaults */ | 42 | static struct tcf_hashinfo gact_hash_info = { |
46 | #define tcf_st tcf_gact | 43 | .htab = tcf_gact_ht, |
47 | #define tc_st tc_gact | 44 | .hmask = GACT_TAB_MASK, |
48 | #define tcf_t_lock gact_lock | 45 | .lock = &gact_lock, |
49 | #define tcf_ht tcf_gact_ht | 46 | }; |
50 | |||
51 | #define CONFIG_NET_ACT_INIT 1 | ||
52 | #include <net/pkt_act.h> | ||
53 | 47 | ||
54 | #ifdef CONFIG_GACT_PROB | 48 | #ifdef CONFIG_GACT_PROB |
55 | static int gact_net_rand(struct tcf_gact *p) | 49 | static int gact_net_rand(struct tcf_gact *gact) |
56 | { | 50 | { |
57 | if (net_random()%p->pval) | 51 | if (net_random() % gact->tcfg_pval) |
58 | return p->action; | 52 | return gact->tcf_action; |
59 | return p->paction; | 53 | return gact->tcfg_paction; |
60 | } | 54 | } |
61 | 55 | ||
62 | static int gact_determ(struct tcf_gact *p) | 56 | static int gact_determ(struct tcf_gact *gact) |
63 | { | 57 | { |
64 | if (p->bstats.packets%p->pval) | 58 | if (gact->tcf_bstats.packets % gact->tcfg_pval) |
65 | return p->action; | 59 | return gact->tcf_action; |
66 | return p->paction; | 60 | return gact->tcfg_paction; |
67 | } | 61 | } |
68 | 62 | ||
69 | typedef int (*g_rand)(struct tcf_gact *p); | 63 | typedef int (*g_rand)(struct tcf_gact *gact); |
70 | static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; | 64 | static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; |
71 | #endif | 65 | #endif /* CONFIG_GACT_PROB */ |
72 | 66 | ||
73 | static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, | 67 | static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, |
74 | struct tc_action *a, int ovr, int bind) | 68 | struct tc_action *a, int ovr, int bind) |
75 | { | 69 | { |
76 | struct rtattr *tb[TCA_GACT_MAX]; | 70 | struct rtattr *tb[TCA_GACT_MAX]; |
77 | struct tc_gact *parm; | 71 | struct tc_gact *parm; |
78 | struct tcf_gact *p; | 72 | struct tcf_gact *gact; |
73 | struct tcf_common *pc; | ||
79 | int ret = 0; | 74 | int ret = 0; |
80 | 75 | ||
81 | if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0) | 76 | if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0) |
@@ -94,105 +89,106 @@ static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, | |||
94 | return -EOPNOTSUPP; | 89 | return -EOPNOTSUPP; |
95 | #endif | 90 | #endif |
96 | 91 | ||
97 | p = tcf_hash_check(parm->index, a, ovr, bind); | 92 | pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); |
98 | if (p == NULL) { | 93 | if (!pc) { |
99 | p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); | 94 | pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), |
100 | if (p == NULL) | 95 | bind, &gact_idx_gen, &gact_hash_info); |
96 | if (unlikely(!pc)) | ||
101 | return -ENOMEM; | 97 | return -ENOMEM; |
102 | ret = ACT_P_CREATED; | 98 | ret = ACT_P_CREATED; |
103 | } else { | 99 | } else { |
104 | if (!ovr) { | 100 | if (!ovr) { |
105 | tcf_hash_release(p, bind); | 101 | tcf_hash_release(pc, bind, &gact_hash_info); |
106 | return -EEXIST; | 102 | return -EEXIST; |
107 | } | 103 | } |
108 | } | 104 | } |
109 | 105 | ||
110 | spin_lock_bh(&p->lock); | 106 | gact = to_gact(pc); |
111 | p->action = parm->action; | 107 | |
108 | spin_lock_bh(&gact->tcf_lock); | ||
109 | gact->tcf_action = parm->action; | ||
112 | #ifdef CONFIG_GACT_PROB | 110 | #ifdef CONFIG_GACT_PROB |
113 | if (tb[TCA_GACT_PROB-1] != NULL) { | 111 | if (tb[TCA_GACT_PROB-1] != NULL) { |
114 | struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]); | 112 | struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]); |
115 | p->paction = p_parm->paction; | 113 | gact->tcfg_paction = p_parm->paction; |
116 | p->pval = p_parm->pval; | 114 | gact->tcfg_pval = p_parm->pval; |
117 | p->ptype = p_parm->ptype; | 115 | gact->tcfg_ptype = p_parm->ptype; |
118 | } | 116 | } |
119 | #endif | 117 | #endif |
120 | spin_unlock_bh(&p->lock); | 118 | spin_unlock_bh(&gact->tcf_lock); |
121 | if (ret == ACT_P_CREATED) | 119 | if (ret == ACT_P_CREATED) |
122 | tcf_hash_insert(p); | 120 | tcf_hash_insert(pc, &gact_hash_info); |
123 | return ret; | 121 | return ret; |
124 | } | 122 | } |
125 | 123 | ||
126 | static int | 124 | static int tcf_gact_cleanup(struct tc_action *a, int bind) |
127 | tcf_gact_cleanup(struct tc_action *a, int bind) | ||
128 | { | 125 | { |
129 | struct tcf_gact *p = PRIV(a, gact); | 126 | struct tcf_gact *gact = a->priv; |
130 | 127 | ||
131 | if (p != NULL) | 128 | if (gact) |
132 | return tcf_hash_release(p, bind); | 129 | return tcf_hash_release(&gact->common, bind, &gact_hash_info); |
133 | return 0; | 130 | return 0; |
134 | } | 131 | } |
135 | 132 | ||
136 | static int | 133 | static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) |
137 | tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | ||
138 | { | 134 | { |
139 | struct tcf_gact *p = PRIV(a, gact); | 135 | struct tcf_gact *gact = a->priv; |
140 | int action = TC_ACT_SHOT; | 136 | int action = TC_ACT_SHOT; |
141 | 137 | ||
142 | spin_lock(&p->lock); | 138 | spin_lock(&gact->tcf_lock); |
143 | #ifdef CONFIG_GACT_PROB | 139 | #ifdef CONFIG_GACT_PROB |
144 | if (p->ptype && gact_rand[p->ptype] != NULL) | 140 | if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) |
145 | action = gact_rand[p->ptype](p); | 141 | action = gact_rand[gact->tcfg_ptype](gact); |
146 | else | 142 | else |
147 | action = p->action; | 143 | action = gact->tcf_action; |
148 | #else | 144 | #else |
149 | action = p->action; | 145 | action = gact->tcf_action; |
150 | #endif | 146 | #endif |
151 | p->bstats.bytes += skb->len; | 147 | gact->tcf_bstats.bytes += skb->len; |
152 | p->bstats.packets++; | 148 | gact->tcf_bstats.packets++; |
153 | if (action == TC_ACT_SHOT) | 149 | if (action == TC_ACT_SHOT) |
154 | p->qstats.drops++; | 150 | gact->tcf_qstats.drops++; |
155 | p->tm.lastuse = jiffies; | 151 | gact->tcf_tm.lastuse = jiffies; |
156 | spin_unlock(&p->lock); | 152 | spin_unlock(&gact->tcf_lock); |
157 | 153 | ||
158 | return action; | 154 | return action; |
159 | } | 155 | } |
160 | 156 | ||
161 | static int | 157 | static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
162 | tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | ||
163 | { | 158 | { |
164 | unsigned char *b = skb->tail; | 159 | unsigned char *b = skb->tail; |
165 | struct tc_gact opt; | 160 | struct tc_gact opt; |
166 | struct tcf_gact *p = PRIV(a, gact); | 161 | struct tcf_gact *gact = a->priv; |
167 | struct tcf_t t; | 162 | struct tcf_t t; |
168 | 163 | ||
169 | opt.index = p->index; | 164 | opt.index = gact->tcf_index; |
170 | opt.refcnt = p->refcnt - ref; | 165 | opt.refcnt = gact->tcf_refcnt - ref; |
171 | opt.bindcnt = p->bindcnt - bind; | 166 | opt.bindcnt = gact->tcf_bindcnt - bind; |
172 | opt.action = p->action; | 167 | opt.action = gact->tcf_action; |
173 | RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); | 168 | RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); |
174 | #ifdef CONFIG_GACT_PROB | 169 | #ifdef CONFIG_GACT_PROB |
175 | if (p->ptype) { | 170 | if (gact->tcfg_ptype) { |
176 | struct tc_gact_p p_opt; | 171 | struct tc_gact_p p_opt; |
177 | p_opt.paction = p->paction; | 172 | p_opt.paction = gact->tcfg_paction; |
178 | p_opt.pval = p->pval; | 173 | p_opt.pval = gact->tcfg_pval; |
179 | p_opt.ptype = p->ptype; | 174 | p_opt.ptype = gact->tcfg_ptype; |
180 | RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); | 175 | RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); |
181 | } | 176 | } |
182 | #endif | 177 | #endif |
183 | t.install = jiffies_to_clock_t(jiffies - p->tm.install); | 178 | t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install); |
184 | t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | 179 | t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse); |
185 | t.expires = jiffies_to_clock_t(p->tm.expires); | 180 | t.expires = jiffies_to_clock_t(gact->tcf_tm.expires); |
186 | RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); | 181 | RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); |
187 | return skb->len; | 182 | return skb->len; |
188 | 183 | ||
189 | rtattr_failure: | 184 | rtattr_failure: |
190 | skb_trim(skb, b - skb->data); | 185 | skb_trim(skb, b - skb->data); |
191 | return -1; | 186 | return -1; |
192 | } | 187 | } |
193 | 188 | ||
194 | static struct tc_action_ops act_gact_ops = { | 189 | static struct tc_action_ops act_gact_ops = { |
195 | .kind = "gact", | 190 | .kind = "gact", |
191 | .hinfo = &gact_hash_info, | ||
196 | .type = TCA_ACT_GACT, | 192 | .type = TCA_ACT_GACT, |
197 | .capab = TCA_CAP_NONE, | 193 | .capab = TCA_CAP_NONE, |
198 | .owner = THIS_MODULE, | 194 | .owner = THIS_MODULE, |
@@ -208,8 +204,7 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); | |||
208 | MODULE_DESCRIPTION("Generic Classifier actions"); | 204 | MODULE_DESCRIPTION("Generic Classifier actions"); |
209 | MODULE_LICENSE("GPL"); | 205 | MODULE_LICENSE("GPL"); |
210 | 206 | ||
211 | static int __init | 207 | static int __init gact_init_module(void) |
212 | gact_init_module(void) | ||
213 | { | 208 | { |
214 | #ifdef CONFIG_GACT_PROB | 209 | #ifdef CONFIG_GACT_PROB |
215 | printk("GACT probability on\n"); | 210 | printk("GACT probability on\n"); |
@@ -219,8 +214,7 @@ gact_init_module(void) | |||
219 | return tcf_register_action(&act_gact_ops); | 214 | return tcf_register_action(&act_gact_ops); |
220 | } | 215 | } |
221 | 216 | ||
222 | static void __exit | 217 | static void __exit gact_cleanup_module(void) |
223 | gact_cleanup_module(void) | ||
224 | { | 218 | { |
225 | tcf_unregister_action(&act_gact_ops); | 219 | tcf_unregister_action(&act_gact_ops); |
226 | } | 220 | } |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index d799e01248c4..224c078a398e 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -38,25 +38,19 @@ | |||
38 | 38 | ||
39 | #include <linux/netfilter_ipv4/ip_tables.h> | 39 | #include <linux/netfilter_ipv4/ip_tables.h> |
40 | 40 | ||
41 | /* use generic hash table */ | ||
42 | #define MY_TAB_SIZE 16 | ||
43 | #define MY_TAB_MASK 15 | ||
44 | 41 | ||
45 | static u32 idx_gen; | 42 | #define IPT_TAB_MASK 15 |
46 | static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; | 43 | static struct tcf_common *tcf_ipt_ht[IPT_TAB_MASK + 1]; |
47 | /* ipt hash table lock */ | 44 | static u32 ipt_idx_gen; |
48 | static DEFINE_RWLOCK(ipt_lock); | 45 | static DEFINE_RWLOCK(ipt_lock); |
49 | 46 | ||
50 | /* ovewrride the defaults */ | 47 | static struct tcf_hashinfo ipt_hash_info = { |
51 | #define tcf_st tcf_ipt | 48 | .htab = tcf_ipt_ht, |
52 | #define tcf_t_lock ipt_lock | 49 | .hmask = IPT_TAB_MASK, |
53 | #define tcf_ht tcf_ipt_ht | 50 | .lock = &ipt_lock, |
54 | 51 | }; | |
55 | #define CONFIG_NET_ACT_INIT | ||
56 | #include <net/pkt_act.h> | ||
57 | 52 | ||
58 | static int | 53 | static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) |
59 | ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | ||
60 | { | 54 | { |
61 | struct ipt_target *target; | 55 | struct ipt_target *target; |
62 | int ret = 0; | 56 | int ret = 0; |
@@ -65,7 +59,6 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
65 | if (!target) | 59 | if (!target) |
66 | return -ENOENT; | 60 | return -ENOENT; |
67 | 61 | ||
68 | DPRINTK("ipt_init_target: found %s\n", target->name); | ||
69 | t->u.kernel.target = target; | 62 | t->u.kernel.target = target; |
70 | 63 | ||
71 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), | 64 | ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), |
@@ -78,8 +71,6 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
78 | t->u.kernel.target, t->data, | 71 | t->u.kernel.target, t->data, |
79 | t->u.target_size - sizeof(*t), | 72 | t->u.target_size - sizeof(*t), |
80 | hook)) { | 73 | hook)) { |
81 | DPRINTK("ipt_init_target: check failed for `%s'.\n", | ||
82 | t->u.kernel.target->name); | ||
83 | module_put(t->u.kernel.target->me); | 74 | module_put(t->u.kernel.target->me); |
84 | ret = -EINVAL; | 75 | ret = -EINVAL; |
85 | } | 76 | } |
@@ -87,8 +78,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
87 | return ret; | 78 | return ret; |
88 | } | 79 | } |
89 | 80 | ||
90 | static void | 81 | static void ipt_destroy_target(struct ipt_entry_target *t) |
91 | ipt_destroy_target(struct ipt_entry_target *t) | ||
92 | { | 82 | { |
93 | if (t->u.kernel.target->destroy) | 83 | if (t->u.kernel.target->destroy) |
94 | t->u.kernel.target->destroy(t->u.kernel.target, t->data, | 84 | t->u.kernel.target->destroy(t->u.kernel.target, t->data, |
@@ -96,31 +86,30 @@ ipt_destroy_target(struct ipt_entry_target *t) | |||
96 | module_put(t->u.kernel.target->me); | 86 | module_put(t->u.kernel.target->me); |
97 | } | 87 | } |
98 | 88 | ||
99 | static int | 89 | static int tcf_ipt_release(struct tcf_ipt *ipt, int bind) |
100 | tcf_ipt_release(struct tcf_ipt *p, int bind) | ||
101 | { | 90 | { |
102 | int ret = 0; | 91 | int ret = 0; |
103 | if (p) { | 92 | if (ipt) { |
104 | if (bind) | 93 | if (bind) |
105 | p->bindcnt--; | 94 | ipt->tcf_bindcnt--; |
106 | p->refcnt--; | 95 | ipt->tcf_refcnt--; |
107 | if (p->bindcnt <= 0 && p->refcnt <= 0) { | 96 | if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) { |
108 | ipt_destroy_target(p->t); | 97 | ipt_destroy_target(ipt->tcfi_t); |
109 | kfree(p->tname); | 98 | kfree(ipt->tcfi_tname); |
110 | kfree(p->t); | 99 | kfree(ipt->tcfi_t); |
111 | tcf_hash_destroy(p); | 100 | tcf_hash_destroy(&ipt->common, &ipt_hash_info); |
112 | ret = ACT_P_DELETED; | 101 | ret = ACT_P_DELETED; |
113 | } | 102 | } |
114 | } | 103 | } |
115 | return ret; | 104 | return ret; |
116 | } | 105 | } |
117 | 106 | ||
118 | static int | 107 | static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, |
119 | tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | 108 | struct tc_action *a, int ovr, int bind) |
120 | int ovr, int bind) | ||
121 | { | 109 | { |
122 | struct rtattr *tb[TCA_IPT_MAX]; | 110 | struct rtattr *tb[TCA_IPT_MAX]; |
123 | struct tcf_ipt *p; | 111 | struct tcf_ipt *ipt; |
112 | struct tcf_common *pc; | ||
124 | struct ipt_entry_target *td, *t; | 113 | struct ipt_entry_target *td, *t; |
125 | char *tname; | 114 | char *tname; |
126 | int ret = 0, err; | 115 | int ret = 0, err; |
@@ -144,49 +133,51 @@ tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | |||
144 | RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) | 133 | RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) |
145 | index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); | 134 | index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); |
146 | 135 | ||
147 | p = tcf_hash_check(index, a, ovr, bind); | 136 | pc = tcf_hash_check(index, a, bind, &ipt_hash_info); |
148 | if (p == NULL) { | 137 | if (!pc) { |
149 | p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); | 138 | pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, |
150 | if (p == NULL) | 139 | &ipt_idx_gen, &ipt_hash_info); |
140 | if (unlikely(!pc)) | ||
151 | return -ENOMEM; | 141 | return -ENOMEM; |
152 | ret = ACT_P_CREATED; | 142 | ret = ACT_P_CREATED; |
153 | } else { | 143 | } else { |
154 | if (!ovr) { | 144 | if (!ovr) { |
155 | tcf_ipt_release(p, bind); | 145 | tcf_ipt_release(to_ipt(pc), bind); |
156 | return -EEXIST; | 146 | return -EEXIST; |
157 | } | 147 | } |
158 | } | 148 | } |
149 | ipt = to_ipt(pc); | ||
159 | 150 | ||
160 | hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); | 151 | hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); |
161 | 152 | ||
162 | err = -ENOMEM; | 153 | err = -ENOMEM; |
163 | tname = kmalloc(IFNAMSIZ, GFP_KERNEL); | 154 | tname = kmalloc(IFNAMSIZ, GFP_KERNEL); |
164 | if (tname == NULL) | 155 | if (unlikely(!tname)) |
165 | goto err1; | 156 | goto err1; |
166 | if (tb[TCA_IPT_TABLE - 1] == NULL || | 157 | if (tb[TCA_IPT_TABLE - 1] == NULL || |
167 | rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) | 158 | rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) |
168 | strcpy(tname, "mangle"); | 159 | strcpy(tname, "mangle"); |
169 | 160 | ||
170 | t = kmalloc(td->u.target_size, GFP_KERNEL); | 161 | t = kmalloc(td->u.target_size, GFP_KERNEL); |
171 | if (t == NULL) | 162 | if (unlikely(!t)) |
172 | goto err2; | 163 | goto err2; |
173 | memcpy(t, td, td->u.target_size); | 164 | memcpy(t, td, td->u.target_size); |
174 | 165 | ||
175 | if ((err = ipt_init_target(t, tname, hook)) < 0) | 166 | if ((err = ipt_init_target(t, tname, hook)) < 0) |
176 | goto err3; | 167 | goto err3; |
177 | 168 | ||
178 | spin_lock_bh(&p->lock); | 169 | spin_lock_bh(&ipt->tcf_lock); |
179 | if (ret != ACT_P_CREATED) { | 170 | if (ret != ACT_P_CREATED) { |
180 | ipt_destroy_target(p->t); | 171 | ipt_destroy_target(ipt->tcfi_t); |
181 | kfree(p->tname); | 172 | kfree(ipt->tcfi_tname); |
182 | kfree(p->t); | 173 | kfree(ipt->tcfi_t); |
183 | } | 174 | } |
184 | p->tname = tname; | 175 | ipt->tcfi_tname = tname; |
185 | p->t = t; | 176 | ipt->tcfi_t = t; |
186 | p->hook = hook; | 177 | ipt->tcfi_hook = hook; |
187 | spin_unlock_bh(&p->lock); | 178 | spin_unlock_bh(&ipt->tcf_lock); |
188 | if (ret == ACT_P_CREATED) | 179 | if (ret == ACT_P_CREATED) |
189 | tcf_hash_insert(p); | 180 | tcf_hash_insert(pc, &ipt_hash_info); |
190 | return ret; | 181 | return ret; |
191 | 182 | ||
192 | err3: | 183 | err3: |
@@ -194,33 +185,32 @@ err3: | |||
194 | err2: | 185 | err2: |
195 | kfree(tname); | 186 | kfree(tname); |
196 | err1: | 187 | err1: |
197 | kfree(p); | 188 | kfree(pc); |
198 | return err; | 189 | return err; |
199 | } | 190 | } |
200 | 191 | ||
201 | static int | 192 | static int tcf_ipt_cleanup(struct tc_action *a, int bind) |
202 | tcf_ipt_cleanup(struct tc_action *a, int bind) | ||
203 | { | 193 | { |
204 | struct tcf_ipt *p = PRIV(a, ipt); | 194 | struct tcf_ipt *ipt = a->priv; |
205 | return tcf_ipt_release(p, bind); | 195 | return tcf_ipt_release(ipt, bind); |
206 | } | 196 | } |
207 | 197 | ||
208 | static int | 198 | static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, |
209 | tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | 199 | struct tcf_result *res) |
210 | { | 200 | { |
211 | int ret = 0, result = 0; | 201 | int ret = 0, result = 0; |
212 | struct tcf_ipt *p = PRIV(a, ipt); | 202 | struct tcf_ipt *ipt = a->priv; |
213 | 203 | ||
214 | if (skb_cloned(skb)) { | 204 | if (skb_cloned(skb)) { |
215 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 205 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
216 | return TC_ACT_UNSPEC; | 206 | return TC_ACT_UNSPEC; |
217 | } | 207 | } |
218 | 208 | ||
219 | spin_lock(&p->lock); | 209 | spin_lock(&ipt->tcf_lock); |
220 | 210 | ||
221 | p->tm.lastuse = jiffies; | 211 | ipt->tcf_tm.lastuse = jiffies; |
222 | p->bstats.bytes += skb->len; | 212 | ipt->tcf_bstats.bytes += skb->len; |
223 | p->bstats.packets++; | 213 | ipt->tcf_bstats.packets++; |
224 | 214 | ||
225 | /* yes, we have to worry about both in and out dev | 215 | /* yes, we have to worry about both in and out dev |
226 | worry later - danger - this API seems to have changed | 216 | worry later - danger - this API seems to have changed |
@@ -229,16 +219,17 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
229 | /* iptables targets take a double skb pointer in case the skb | 219 | /* iptables targets take a double skb pointer in case the skb |
230 | * needs to be replaced. We don't own the skb, so this must not | 220 | * needs to be replaced. We don't own the skb, so this must not |
231 | * happen. The pskb_expand_head above should make sure of this */ | 221 | * happen. The pskb_expand_head above should make sure of this */ |
232 | ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, | 222 | ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL, |
233 | p->t->u.kernel.target, p->t->data, | 223 | ipt->tcfi_hook, |
234 | NULL); | 224 | ipt->tcfi_t->u.kernel.target, |
225 | ipt->tcfi_t->data, NULL); | ||
235 | switch (ret) { | 226 | switch (ret) { |
236 | case NF_ACCEPT: | 227 | case NF_ACCEPT: |
237 | result = TC_ACT_OK; | 228 | result = TC_ACT_OK; |
238 | break; | 229 | break; |
239 | case NF_DROP: | 230 | case NF_DROP: |
240 | result = TC_ACT_SHOT; | 231 | result = TC_ACT_SHOT; |
241 | p->qstats.drops++; | 232 | ipt->tcf_qstats.drops++; |
242 | break; | 233 | break; |
243 | case IPT_CONTINUE: | 234 | case IPT_CONTINUE: |
244 | result = TC_ACT_PIPE; | 235 | result = TC_ACT_PIPE; |
@@ -249,53 +240,46 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
249 | result = TC_POLICE_OK; | 240 | result = TC_POLICE_OK; |
250 | break; | 241 | break; |
251 | } | 242 | } |
252 | spin_unlock(&p->lock); | 243 | spin_unlock(&ipt->tcf_lock); |
253 | return result; | 244 | return result; |
254 | 245 | ||
255 | } | 246 | } |
256 | 247 | ||
257 | static int | 248 | static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
258 | tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | ||
259 | { | 249 | { |
250 | unsigned char *b = skb->tail; | ||
251 | struct tcf_ipt *ipt = a->priv; | ||
260 | struct ipt_entry_target *t; | 252 | struct ipt_entry_target *t; |
261 | struct tcf_t tm; | 253 | struct tcf_t tm; |
262 | struct tc_cnt c; | 254 | struct tc_cnt c; |
263 | unsigned char *b = skb->tail; | ||
264 | struct tcf_ipt *p = PRIV(a, ipt); | ||
265 | 255 | ||
266 | /* for simple targets kernel size == user size | 256 | /* for simple targets kernel size == user size |
267 | ** user name = target name | 257 | ** user name = target name |
268 | ** for foolproof you need to not assume this | 258 | ** for foolproof you need to not assume this |
269 | */ | 259 | */ |
270 | 260 | ||
271 | t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); | 261 | t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); |
272 | if (t == NULL) | 262 | if (unlikely(!t)) |
273 | goto rtattr_failure; | 263 | goto rtattr_failure; |
274 | 264 | ||
275 | c.bindcnt = p->bindcnt - bind; | 265 | c.bindcnt = ipt->tcf_bindcnt - bind; |
276 | c.refcnt = p->refcnt - ref; | 266 | c.refcnt = ipt->tcf_refcnt - ref; |
277 | memcpy(t, p->t, p->t->u.user.target_size); | 267 | memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size); |
278 | strcpy(t->u.user.name, p->t->u.kernel.target->name); | 268 | strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); |
279 | 269 | ||
280 | DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, | 270 | RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); |
281 | strlen(p->tname)); | 271 | RTA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index); |
282 | DPRINTK("\tdump target name %s size %d size user %d " | 272 | RTA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook); |
283 | "data[0] %x data[1] %x\n", p->t->u.kernel.target->name, | ||
284 | p->t->u.target_size, p->t->u.user.target_size, | ||
285 | p->t->data[0], p->t->data[1]); | ||
286 | RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t); | ||
287 | RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index); | ||
288 | RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook); | ||
289 | RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); | 273 | RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); |
290 | RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); | 274 | RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname); |
291 | tm.install = jiffies_to_clock_t(jiffies - p->tm.install); | 275 | tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install); |
292 | tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | 276 | tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse); |
293 | tm.expires = jiffies_to_clock_t(p->tm.expires); | 277 | tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires); |
294 | RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); | 278 | RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); |
295 | kfree(t); | 279 | kfree(t); |
296 | return skb->len; | 280 | return skb->len; |
297 | 281 | ||
298 | rtattr_failure: | 282 | rtattr_failure: |
299 | skb_trim(skb, b - skb->data); | 283 | skb_trim(skb, b - skb->data); |
300 | kfree(t); | 284 | kfree(t); |
301 | return -1; | 285 | return -1; |
@@ -303,6 +287,7 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
303 | 287 | ||
304 | static struct tc_action_ops act_ipt_ops = { | 288 | static struct tc_action_ops act_ipt_ops = { |
305 | .kind = "ipt", | 289 | .kind = "ipt", |
290 | .hinfo = &ipt_hash_info, | ||
306 | .type = TCA_ACT_IPT, | 291 | .type = TCA_ACT_IPT, |
307 | .capab = TCA_CAP_NONE, | 292 | .capab = TCA_CAP_NONE, |
308 | .owner = THIS_MODULE, | 293 | .owner = THIS_MODULE, |
@@ -318,14 +303,12 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); | |||
318 | MODULE_DESCRIPTION("Iptables target actions"); | 303 | MODULE_DESCRIPTION("Iptables target actions"); |
319 | MODULE_LICENSE("GPL"); | 304 | MODULE_LICENSE("GPL"); |
320 | 305 | ||
321 | static int __init | 306 | static int __init ipt_init_module(void) |
322 | ipt_init_module(void) | ||
323 | { | 307 | { |
324 | return tcf_register_action(&act_ipt_ops); | 308 | return tcf_register_action(&act_ipt_ops); |
325 | } | 309 | } |
326 | 310 | ||
327 | static void __exit | 311 | static void __exit ipt_cleanup_module(void) |
328 | ipt_cleanup_module(void) | ||
329 | { | 312 | { |
330 | tcf_unregister_action(&act_ipt_ops); | 313 | tcf_unregister_action(&act_ipt_ops); |
331 | } | 314 | } |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fc562047ecc5..483897271f15 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -39,46 +39,39 @@ | |||
39 | #include <linux/etherdevice.h> | 39 | #include <linux/etherdevice.h> |
40 | #include <linux/if_arp.h> | 40 | #include <linux/if_arp.h> |
41 | 41 | ||
42 | 42 | #define MIRRED_TAB_MASK 7 | |
43 | /* use generic hash table */ | 43 | static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1]; |
44 | #define MY_TAB_SIZE 8 | 44 | static u32 mirred_idx_gen; |
45 | #define MY_TAB_MASK (MY_TAB_SIZE - 1) | ||
46 | static u32 idx_gen; | ||
47 | static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE]; | ||
48 | static DEFINE_RWLOCK(mirred_lock); | 45 | static DEFINE_RWLOCK(mirred_lock); |
49 | 46 | ||
50 | /* ovewrride the defaults */ | 47 | static struct tcf_hashinfo mirred_hash_info = { |
51 | #define tcf_st tcf_mirred | 48 | .htab = tcf_mirred_ht, |
52 | #define tc_st tc_mirred | 49 | .hmask = MIRRED_TAB_MASK, |
53 | #define tcf_t_lock mirred_lock | 50 | .lock = &mirred_lock, |
54 | #define tcf_ht tcf_mirred_ht | 51 | }; |
55 | |||
56 | #define CONFIG_NET_ACT_INIT 1 | ||
57 | #include <net/pkt_act.h> | ||
58 | 52 | ||
59 | static inline int | 53 | static inline int tcf_mirred_release(struct tcf_mirred *m, int bind) |
60 | tcf_mirred_release(struct tcf_mirred *p, int bind) | ||
61 | { | 54 | { |
62 | if (p) { | 55 | if (m) { |
63 | if (bind) | 56 | if (bind) |
64 | p->bindcnt--; | 57 | m->tcf_bindcnt--; |
65 | p->refcnt--; | 58 | m->tcf_refcnt--; |
66 | if(!p->bindcnt && p->refcnt <= 0) { | 59 | if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) { |
67 | dev_put(p->dev); | 60 | dev_put(m->tcfm_dev); |
68 | tcf_hash_destroy(p); | 61 | tcf_hash_destroy(&m->common, &mirred_hash_info); |
69 | return 1; | 62 | return 1; |
70 | } | 63 | } |
71 | } | 64 | } |
72 | return 0; | 65 | return 0; |
73 | } | 66 | } |
74 | 67 | ||
75 | static int | 68 | static int tcf_mirred_init(struct rtattr *rta, struct rtattr *est, |
76 | tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | 69 | struct tc_action *a, int ovr, int bind) |
77 | int ovr, int bind) | ||
78 | { | 70 | { |
79 | struct rtattr *tb[TCA_MIRRED_MAX]; | 71 | struct rtattr *tb[TCA_MIRRED_MAX]; |
80 | struct tc_mirred *parm; | 72 | struct tc_mirred *parm; |
81 | struct tcf_mirred *p; | 73 | struct tcf_mirred *m; |
74 | struct tcf_common *pc; | ||
82 | struct net_device *dev = NULL; | 75 | struct net_device *dev = NULL; |
83 | int ret = 0; | 76 | int ret = 0; |
84 | int ok_push = 0; | 77 | int ok_push = 0; |
@@ -110,64 +103,62 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | |||
110 | } | 103 | } |
111 | } | 104 | } |
112 | 105 | ||
113 | p = tcf_hash_check(parm->index, a, ovr, bind); | 106 | pc = tcf_hash_check(parm->index, a, bind, &mirred_hash_info); |
114 | if (p == NULL) { | 107 | if (!pc) { |
115 | if (!parm->ifindex) | 108 | if (!parm->ifindex) |
116 | return -EINVAL; | 109 | return -EINVAL; |
117 | p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); | 110 | pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind, |
118 | if (p == NULL) | 111 | &mirred_idx_gen, &mirred_hash_info); |
112 | if (unlikely(!pc)) | ||
119 | return -ENOMEM; | 113 | return -ENOMEM; |
120 | ret = ACT_P_CREATED; | 114 | ret = ACT_P_CREATED; |
121 | } else { | 115 | } else { |
122 | if (!ovr) { | 116 | if (!ovr) { |
123 | tcf_mirred_release(p, bind); | 117 | tcf_mirred_release(to_mirred(pc), bind); |
124 | return -EEXIST; | 118 | return -EEXIST; |
125 | } | 119 | } |
126 | } | 120 | } |
121 | m = to_mirred(pc); | ||
127 | 122 | ||
128 | spin_lock_bh(&p->lock); | 123 | spin_lock_bh(&m->tcf_lock); |
129 | p->action = parm->action; | 124 | m->tcf_action = parm->action; |
130 | p->eaction = parm->eaction; | 125 | m->tcfm_eaction = parm->eaction; |
131 | if (parm->ifindex) { | 126 | if (parm->ifindex) { |
132 | p->ifindex = parm->ifindex; | 127 | m->tcfm_ifindex = parm->ifindex; |
133 | if (ret != ACT_P_CREATED) | 128 | if (ret != ACT_P_CREATED) |
134 | dev_put(p->dev); | 129 | dev_put(m->tcfm_dev); |
135 | p->dev = dev; | 130 | m->tcfm_dev = dev; |
136 | dev_hold(dev); | 131 | dev_hold(dev); |
137 | p->ok_push = ok_push; | 132 | m->tcfm_ok_push = ok_push; |
138 | } | 133 | } |
139 | spin_unlock_bh(&p->lock); | 134 | spin_unlock_bh(&m->tcf_lock); |
140 | if (ret == ACT_P_CREATED) | 135 | if (ret == ACT_P_CREATED) |
141 | tcf_hash_insert(p); | 136 | tcf_hash_insert(pc, &mirred_hash_info); |
142 | 137 | ||
143 | DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s " | ||
144 | "ifindex %d\n", parm->index, parm->action, parm->eaction, | ||
145 | dev->name, parm->ifindex); | ||
146 | return ret; | 138 | return ret; |
147 | } | 139 | } |
148 | 140 | ||
149 | static int | 141 | static int tcf_mirred_cleanup(struct tc_action *a, int bind) |
150 | tcf_mirred_cleanup(struct tc_action *a, int bind) | ||
151 | { | 142 | { |
152 | struct tcf_mirred *p = PRIV(a, mirred); | 143 | struct tcf_mirred *m = a->priv; |
153 | 144 | ||
154 | if (p != NULL) | 145 | if (m) |
155 | return tcf_mirred_release(p, bind); | 146 | return tcf_mirred_release(m, bind); |
156 | return 0; | 147 | return 0; |
157 | } | 148 | } |
158 | 149 | ||
159 | static int | 150 | static int tcf_mirred(struct sk_buff *skb, struct tc_action *a, |
160 | tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | 151 | struct tcf_result *res) |
161 | { | 152 | { |
162 | struct tcf_mirred *p = PRIV(a, mirred); | 153 | struct tcf_mirred *m = a->priv; |
163 | struct net_device *dev; | 154 | struct net_device *dev; |
164 | struct sk_buff *skb2 = NULL; | 155 | struct sk_buff *skb2 = NULL; |
165 | u32 at = G_TC_AT(skb->tc_verd); | 156 | u32 at = G_TC_AT(skb->tc_verd); |
166 | 157 | ||
167 | spin_lock(&p->lock); | 158 | spin_lock(&m->tcf_lock); |
168 | 159 | ||
169 | dev = p->dev; | 160 | dev = m->tcfm_dev; |
170 | p->tm.lastuse = jiffies; | 161 | m->tcf_tm.lastuse = jiffies; |
171 | 162 | ||
172 | if (!(dev->flags&IFF_UP) ) { | 163 | if (!(dev->flags&IFF_UP) ) { |
173 | if (net_ratelimit()) | 164 | if (net_ratelimit()) |
@@ -176,10 +167,10 @@ tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
176 | bad_mirred: | 167 | bad_mirred: |
177 | if (skb2 != NULL) | 168 | if (skb2 != NULL) |
178 | kfree_skb(skb2); | 169 | kfree_skb(skb2); |
179 | p->qstats.overlimits++; | 170 | m->tcf_qstats.overlimits++; |
180 | p->bstats.bytes += skb->len; | 171 | m->tcf_bstats.bytes += skb->len; |
181 | p->bstats.packets++; | 172 | m->tcf_bstats.packets++; |
182 | spin_unlock(&p->lock); | 173 | spin_unlock(&m->tcf_lock); |
183 | /* should we be asking for packet to be dropped? | 174 | /* should we be asking for packet to be dropped? |
184 | * may make sense for redirect case only | 175 | * may make sense for redirect case only |
185 | */ | 176 | */ |
@@ -189,59 +180,59 @@ bad_mirred: | |||
189 | skb2 = skb_clone(skb, GFP_ATOMIC); | 180 | skb2 = skb_clone(skb, GFP_ATOMIC); |
190 | if (skb2 == NULL) | 181 | if (skb2 == NULL) |
191 | goto bad_mirred; | 182 | goto bad_mirred; |
192 | if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) { | 183 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR && |
184 | m->tcfm_eaction != TCA_EGRESS_REDIR) { | ||
193 | if (net_ratelimit()) | 185 | if (net_ratelimit()) |
194 | printk("tcf_mirred unknown action %d\n", p->eaction); | 186 | printk("tcf_mirred unknown action %d\n", |
187 | m->tcfm_eaction); | ||
195 | goto bad_mirred; | 188 | goto bad_mirred; |
196 | } | 189 | } |
197 | 190 | ||
198 | p->bstats.bytes += skb2->len; | 191 | m->tcf_bstats.bytes += skb2->len; |
199 | p->bstats.packets++; | 192 | m->tcf_bstats.packets++; |
200 | if (!(at & AT_EGRESS)) | 193 | if (!(at & AT_EGRESS)) |
201 | if (p->ok_push) | 194 | if (m->tcfm_ok_push) |
202 | skb_push(skb2, skb2->dev->hard_header_len); | 195 | skb_push(skb2, skb2->dev->hard_header_len); |
203 | 196 | ||
204 | /* mirror is always swallowed */ | 197 | /* mirror is always swallowed */ |
205 | if (p->eaction != TCA_EGRESS_MIRROR) | 198 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR) |
206 | skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); | 199 | skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); |
207 | 200 | ||
208 | skb2->dev = dev; | 201 | skb2->dev = dev; |
209 | skb2->input_dev = skb->dev; | 202 | skb2->input_dev = skb->dev; |
210 | dev_queue_xmit(skb2); | 203 | dev_queue_xmit(skb2); |
211 | spin_unlock(&p->lock); | 204 | spin_unlock(&m->tcf_lock); |
212 | return p->action; | 205 | return m->tcf_action; |
213 | } | 206 | } |
214 | 207 | ||
215 | static int | 208 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
216 | tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | ||
217 | { | 209 | { |
218 | unsigned char *b = skb->tail; | 210 | unsigned char *b = skb->tail; |
211 | struct tcf_mirred *m = a->priv; | ||
219 | struct tc_mirred opt; | 212 | struct tc_mirred opt; |
220 | struct tcf_mirred *p = PRIV(a, mirred); | ||
221 | struct tcf_t t; | 213 | struct tcf_t t; |
222 | 214 | ||
223 | opt.index = p->index; | 215 | opt.index = m->tcf_index; |
224 | opt.action = p->action; | 216 | opt.action = m->tcf_action; |
225 | opt.refcnt = p->refcnt - ref; | 217 | opt.refcnt = m->tcf_refcnt - ref; |
226 | opt.bindcnt = p->bindcnt - bind; | 218 | opt.bindcnt = m->tcf_bindcnt - bind; |
227 | opt.eaction = p->eaction; | 219 | opt.eaction = m->tcfm_eaction; |
228 | opt.ifindex = p->ifindex; | 220 | opt.ifindex = m->tcfm_ifindex; |
229 | DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n", | ||
230 | p->index, p->action, p->eaction, p->ifindex); | ||
231 | RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); | 221 | RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); |
232 | t.install = jiffies_to_clock_t(jiffies - p->tm.install); | 222 | t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install); |
233 | t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | 223 | t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse); |
234 | t.expires = jiffies_to_clock_t(p->tm.expires); | 224 | t.expires = jiffies_to_clock_t(m->tcf_tm.expires); |
235 | RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); | 225 | RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); |
236 | return skb->len; | 226 | return skb->len; |
237 | 227 | ||
238 | rtattr_failure: | 228 | rtattr_failure: |
239 | skb_trim(skb, b - skb->data); | 229 | skb_trim(skb, b - skb->data); |
240 | return -1; | 230 | return -1; |
241 | } | 231 | } |
242 | 232 | ||
243 | static struct tc_action_ops act_mirred_ops = { | 233 | static struct tc_action_ops act_mirred_ops = { |
244 | .kind = "mirred", | 234 | .kind = "mirred", |
235 | .hinfo = &mirred_hash_info, | ||
245 | .type = TCA_ACT_MIRRED, | 236 | .type = TCA_ACT_MIRRED, |
246 | .capab = TCA_CAP_NONE, | 237 | .capab = TCA_CAP_NONE, |
247 | .owner = THIS_MODULE, | 238 | .owner = THIS_MODULE, |
@@ -257,15 +248,13 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002)"); | |||
257 | MODULE_DESCRIPTION("Device Mirror/redirect actions"); | 248 | MODULE_DESCRIPTION("Device Mirror/redirect actions"); |
258 | MODULE_LICENSE("GPL"); | 249 | MODULE_LICENSE("GPL"); |
259 | 250 | ||
260 | static int __init | 251 | static int __init mirred_init_module(void) |
261 | mirred_init_module(void) | ||
262 | { | 252 | { |
263 | printk("Mirror/redirect action on\n"); | 253 | printk("Mirror/redirect action on\n"); |
264 | return tcf_register_action(&act_mirred_ops); | 254 | return tcf_register_action(&act_mirred_ops); |
265 | } | 255 | } |
266 | 256 | ||
267 | static void __exit | 257 | static void __exit mirred_cleanup_module(void) |
268 | mirred_cleanup_module(void) | ||
269 | { | 258 | { |
270 | tcf_unregister_action(&act_mirred_ops); | 259 | tcf_unregister_action(&act_mirred_ops); |
271 | } | 260 | } |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index f257475e0e0c..8ac65c219b98 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -33,32 +33,25 @@ | |||
33 | #include <linux/tc_act/tc_pedit.h> | 33 | #include <linux/tc_act/tc_pedit.h> |
34 | #include <net/tc_act/tc_pedit.h> | 34 | #include <net/tc_act/tc_pedit.h> |
35 | 35 | ||
36 | 36 | #define PEDIT_TAB_MASK 15 | |
37 | #define PEDIT_DEB 1 | 37 | static struct tcf_common *tcf_pedit_ht[PEDIT_TAB_MASK + 1]; |
38 | 38 | static u32 pedit_idx_gen; | |
39 | /* use generic hash table */ | ||
40 | #define MY_TAB_SIZE 16 | ||
41 | #define MY_TAB_MASK 15 | ||
42 | static u32 idx_gen; | ||
43 | static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE]; | ||
44 | static DEFINE_RWLOCK(pedit_lock); | 39 | static DEFINE_RWLOCK(pedit_lock); |
45 | 40 | ||
46 | #define tcf_st tcf_pedit | 41 | static struct tcf_hashinfo pedit_hash_info = { |
47 | #define tc_st tc_pedit | 42 | .htab = tcf_pedit_ht, |
48 | #define tcf_t_lock pedit_lock | 43 | .hmask = PEDIT_TAB_MASK, |
49 | #define tcf_ht tcf_pedit_ht | 44 | .lock = &pedit_lock, |
50 | 45 | }; | |
51 | #define CONFIG_NET_ACT_INIT 1 | ||
52 | #include <net/pkt_act.h> | ||
53 | 46 | ||
54 | static int | 47 | static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est, |
55 | tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | 48 | struct tc_action *a, int ovr, int bind) |
56 | int ovr, int bind) | ||
57 | { | 49 | { |
58 | struct rtattr *tb[TCA_PEDIT_MAX]; | 50 | struct rtattr *tb[TCA_PEDIT_MAX]; |
59 | struct tc_pedit *parm; | 51 | struct tc_pedit *parm; |
60 | int ret = 0; | 52 | int ret = 0; |
61 | struct tcf_pedit *p; | 53 | struct tcf_pedit *p; |
54 | struct tcf_common *pc; | ||
62 | struct tc_pedit_key *keys = NULL; | 55 | struct tc_pedit_key *keys = NULL; |
63 | int ksize; | 56 | int ksize; |
64 | 57 | ||
@@ -73,54 +66,56 @@ tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, | |||
73 | if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize) | 66 | if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize) |
74 | return -EINVAL; | 67 | return -EINVAL; |
75 | 68 | ||
76 | p = tcf_hash_check(parm->index, a, ovr, bind); | 69 | pc = tcf_hash_check(parm->index, a, bind, &pedit_hash_info); |
77 | if (p == NULL) { | 70 | if (!pc) { |
78 | if (!parm->nkeys) | 71 | if (!parm->nkeys) |
79 | return -EINVAL; | 72 | return -EINVAL; |
80 | p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); | 73 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, |
81 | if (p == NULL) | 74 | &pedit_idx_gen, &pedit_hash_info); |
75 | if (unlikely(!pc)) | ||
82 | return -ENOMEM; | 76 | return -ENOMEM; |
77 | p = to_pedit(pc); | ||
83 | keys = kmalloc(ksize, GFP_KERNEL); | 78 | keys = kmalloc(ksize, GFP_KERNEL); |
84 | if (keys == NULL) { | 79 | if (keys == NULL) { |
85 | kfree(p); | 80 | kfree(pc); |
86 | return -ENOMEM; | 81 | return -ENOMEM; |
87 | } | 82 | } |
88 | ret = ACT_P_CREATED; | 83 | ret = ACT_P_CREATED; |
89 | } else { | 84 | } else { |
85 | p = to_pedit(pc); | ||
90 | if (!ovr) { | 86 | if (!ovr) { |
91 | tcf_hash_release(p, bind); | 87 | tcf_hash_release(pc, bind, &pedit_hash_info); |
92 | return -EEXIST; | 88 | return -EEXIST; |
93 | } | 89 | } |
94 | if (p->nkeys && p->nkeys != parm->nkeys) { | 90 | if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { |
95 | keys = kmalloc(ksize, GFP_KERNEL); | 91 | keys = kmalloc(ksize, GFP_KERNEL); |
96 | if (keys == NULL) | 92 | if (keys == NULL) |
97 | return -ENOMEM; | 93 | return -ENOMEM; |
98 | } | 94 | } |
99 | } | 95 | } |
100 | 96 | ||
101 | spin_lock_bh(&p->lock); | 97 | spin_lock_bh(&p->tcf_lock); |
102 | p->flags = parm->flags; | 98 | p->tcfp_flags = parm->flags; |
103 | p->action = parm->action; | 99 | p->tcf_action = parm->action; |
104 | if (keys) { | 100 | if (keys) { |
105 | kfree(p->keys); | 101 | kfree(p->tcfp_keys); |
106 | p->keys = keys; | 102 | p->tcfp_keys = keys; |
107 | p->nkeys = parm->nkeys; | 103 | p->tcfp_nkeys = parm->nkeys; |
108 | } | 104 | } |
109 | memcpy(p->keys, parm->keys, ksize); | 105 | memcpy(p->tcfp_keys, parm->keys, ksize); |
110 | spin_unlock_bh(&p->lock); | 106 | spin_unlock_bh(&p->tcf_lock); |
111 | if (ret == ACT_P_CREATED) | 107 | if (ret == ACT_P_CREATED) |
112 | tcf_hash_insert(p); | 108 | tcf_hash_insert(pc, &pedit_hash_info); |
113 | return ret; | 109 | return ret; |
114 | } | 110 | } |
115 | 111 | ||
116 | static int | 112 | static int tcf_pedit_cleanup(struct tc_action *a, int bind) |
117 | tcf_pedit_cleanup(struct tc_action *a, int bind) | ||
118 | { | 113 | { |
119 | struct tcf_pedit *p = PRIV(a, pedit); | 114 | struct tcf_pedit *p = a->priv; |
120 | 115 | ||
121 | if (p != NULL) { | 116 | if (p) { |
122 | struct tc_pedit_key *keys = p->keys; | 117 | struct tc_pedit_key *keys = p->tcfp_keys; |
123 | if (tcf_hash_release(p, bind)) { | 118 | if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) { |
124 | kfree(keys); | 119 | kfree(keys); |
125 | return 1; | 120 | return 1; |
126 | } | 121 | } |
@@ -128,30 +123,30 @@ tcf_pedit_cleanup(struct tc_action *a, int bind) | |||
128 | return 0; | 123 | return 0; |
129 | } | 124 | } |
130 | 125 | ||
131 | static int | 126 | static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, |
132 | tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | 127 | struct tcf_result *res) |
133 | { | 128 | { |
134 | struct tcf_pedit *p = PRIV(a, pedit); | 129 | struct tcf_pedit *p = a->priv; |
135 | int i, munged = 0; | 130 | int i, munged = 0; |
136 | u8 *pptr; | 131 | u8 *pptr; |
137 | 132 | ||
138 | if (!(skb->tc_verd & TC_OK2MUNGE)) { | 133 | if (!(skb->tc_verd & TC_OK2MUNGE)) { |
139 | /* should we set skb->cloned? */ | 134 | /* should we set skb->cloned? */ |
140 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | 135 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { |
141 | return p->action; | 136 | return p->tcf_action; |
142 | } | 137 | } |
143 | } | 138 | } |
144 | 139 | ||
145 | pptr = skb->nh.raw; | 140 | pptr = skb->nh.raw; |
146 | 141 | ||
147 | spin_lock(&p->lock); | 142 | spin_lock(&p->tcf_lock); |
148 | 143 | ||
149 | p->tm.lastuse = jiffies; | 144 | p->tcf_tm.lastuse = jiffies; |
150 | 145 | ||
151 | if (p->nkeys > 0) { | 146 | if (p->tcfp_nkeys > 0) { |
152 | struct tc_pedit_key *tkey = p->keys; | 147 | struct tc_pedit_key *tkey = p->tcfp_keys; |
153 | 148 | ||
154 | for (i = p->nkeys; i > 0; i--, tkey++) { | 149 | for (i = p->tcfp_nkeys; i > 0; i--, tkey++) { |
155 | u32 *ptr; | 150 | u32 *ptr; |
156 | int offset = tkey->off; | 151 | int offset = tkey->off; |
157 | 152 | ||
@@ -169,7 +164,8 @@ tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
169 | printk("offset must be on 32 bit boundaries\n"); | 164 | printk("offset must be on 32 bit boundaries\n"); |
170 | goto bad; | 165 | goto bad; |
171 | } | 166 | } |
172 | if (skb->len < 0 || (offset > 0 && offset > skb->len)) { | 167 | if (skb->len < 0 || |
168 | (offset > 0 && offset > skb->len)) { | ||
173 | printk("offset %d cant exceed pkt length %d\n", | 169 | printk("offset %d cant exceed pkt length %d\n", |
174 | offset, skb->len); | 170 | offset, skb->len); |
175 | goto bad; | 171 | goto bad; |
@@ -185,63 +181,47 @@ tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
185 | skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); | 181 | skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); |
186 | goto done; | 182 | goto done; |
187 | } else { | 183 | } else { |
188 | printk("pedit BUG: index %d\n",p->index); | 184 | printk("pedit BUG: index %d\n", p->tcf_index); |
189 | } | 185 | } |
190 | 186 | ||
191 | bad: | 187 | bad: |
192 | p->qstats.overlimits++; | 188 | p->tcf_qstats.overlimits++; |
193 | done: | 189 | done: |
194 | p->bstats.bytes += skb->len; | 190 | p->tcf_bstats.bytes += skb->len; |
195 | p->bstats.packets++; | 191 | p->tcf_bstats.packets++; |
196 | spin_unlock(&p->lock); | 192 | spin_unlock(&p->tcf_lock); |
197 | return p->action; | 193 | return p->tcf_action; |
198 | } | 194 | } |
199 | 195 | ||
200 | static int | 196 | static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, |
201 | tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) | 197 | int bind, int ref) |
202 | { | 198 | { |
203 | unsigned char *b = skb->tail; | 199 | unsigned char *b = skb->tail; |
200 | struct tcf_pedit *p = a->priv; | ||
204 | struct tc_pedit *opt; | 201 | struct tc_pedit *opt; |
205 | struct tcf_pedit *p = PRIV(a, pedit); | ||
206 | struct tcf_t t; | 202 | struct tcf_t t; |
207 | int s; | 203 | int s; |
208 | 204 | ||
209 | s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key); | 205 | s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key); |
210 | 206 | ||
211 | /* netlink spinlocks held above us - must use ATOMIC */ | 207 | /* netlink spinlocks held above us - must use ATOMIC */ |
212 | opt = kzalloc(s, GFP_ATOMIC); | 208 | opt = kzalloc(s, GFP_ATOMIC); |
213 | if (opt == NULL) | 209 | if (unlikely(!opt)) |
214 | return -ENOBUFS; | 210 | return -ENOBUFS; |
215 | 211 | ||
216 | memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key)); | 212 | memcpy(opt->keys, p->tcfp_keys, |
217 | opt->index = p->index; | 213 | p->tcfp_nkeys * sizeof(struct tc_pedit_key)); |
218 | opt->nkeys = p->nkeys; | 214 | opt->index = p->tcf_index; |
219 | opt->flags = p->flags; | 215 | opt->nkeys = p->tcfp_nkeys; |
220 | opt->action = p->action; | 216 | opt->flags = p->tcfp_flags; |
221 | opt->refcnt = p->refcnt - ref; | 217 | opt->action = p->tcf_action; |
222 | opt->bindcnt = p->bindcnt - bind; | 218 | opt->refcnt = p->tcf_refcnt - ref; |
223 | 219 | opt->bindcnt = p->tcf_bindcnt - bind; | |
224 | |||
225 | #ifdef PEDIT_DEB | ||
226 | { | ||
227 | /* Debug - get rid of later */ | ||
228 | int i; | ||
229 | struct tc_pedit_key *key = opt->keys; | ||
230 | |||
231 | for (i=0; i<opt->nkeys; i++, key++) { | ||
232 | printk( "\n key #%d",i); | ||
233 | printk( " at %d: val %08x mask %08x", | ||
234 | (unsigned int)key->off, | ||
235 | (unsigned int)key->val, | ||
236 | (unsigned int)key->mask); | ||
237 | } | ||
238 | } | ||
239 | #endif | ||
240 | 220 | ||
241 | RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt); | 221 | RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt); |
242 | t.install = jiffies_to_clock_t(jiffies - p->tm.install); | 222 | t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); |
243 | t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); | 223 | t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); |
244 | t.expires = jiffies_to_clock_t(p->tm.expires); | 224 | t.expires = jiffies_to_clock_t(p->tcf_tm.expires); |
245 | RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); | 225 | RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); |
246 | kfree(opt); | 226 | kfree(opt); |
247 | return skb->len; | 227 | return skb->len; |
@@ -252,9 +232,9 @@ rtattr_failure: | |||
252 | return -1; | 232 | return -1; |
253 | } | 233 | } |
254 | 234 | ||
255 | static | 235 | static struct tc_action_ops act_pedit_ops = { |
256 | struct tc_action_ops act_pedit_ops = { | ||
257 | .kind = "pedit", | 236 | .kind = "pedit", |
237 | .hinfo = &pedit_hash_info, | ||
258 | .type = TCA_ACT_PEDIT, | 238 | .type = TCA_ACT_PEDIT, |
259 | .capab = TCA_CAP_NONE, | 239 | .capab = TCA_CAP_NONE, |
260 | .owner = THIS_MODULE, | 240 | .owner = THIS_MODULE, |
@@ -270,14 +250,12 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); | |||
270 | MODULE_DESCRIPTION("Generic Packet Editor actions"); | 250 | MODULE_DESCRIPTION("Generic Packet Editor actions"); |
271 | MODULE_LICENSE("GPL"); | 251 | MODULE_LICENSE("GPL"); |
272 | 252 | ||
273 | static int __init | 253 | static int __init pedit_init_module(void) |
274 | pedit_init_module(void) | ||
275 | { | 254 | { |
276 | return tcf_register_action(&act_pedit_ops); | 255 | return tcf_register_action(&act_pedit_ops); |
277 | } | 256 | } |
278 | 257 | ||
279 | static void __exit | 258 | static void __exit pedit_cleanup_module(void) |
280 | pedit_cleanup_module(void) | ||
281 | { | 259 | { |
282 | tcf_unregister_action(&act_pedit_ops); | 260 | tcf_unregister_action(&act_pedit_ops); |
283 | } | 261 | } |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index da905d7b4b40..fed47b658837 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -32,43 +32,27 @@ | |||
32 | #include <net/sock.h> | 32 | #include <net/sock.h> |
33 | #include <net/act_api.h> | 33 | #include <net/act_api.h> |
34 | 34 | ||
35 | #define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log]) | 35 | #define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log]) |
36 | #define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log]) | 36 | #define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log]) |
37 | #define PRIV(a) ((struct tcf_police *) (a)->priv) | ||
38 | |||
39 | /* use generic hash table */ | ||
40 | #define MY_TAB_SIZE 16 | ||
41 | #define MY_TAB_MASK 15 | ||
42 | static u32 idx_gen; | ||
43 | static struct tcf_police *tcf_police_ht[MY_TAB_SIZE]; | ||
44 | /* Policer hash table lock */ | ||
45 | static DEFINE_RWLOCK(police_lock); | ||
46 | |||
47 | /* Each policer is serialized by its individual spinlock */ | ||
48 | 37 | ||
49 | static __inline__ unsigned tcf_police_hash(u32 index) | 38 | #define POL_TAB_MASK 15 |
50 | { | 39 | static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; |
51 | return index&0xF; | 40 | static u32 police_idx_gen; |
52 | } | 41 | static DEFINE_RWLOCK(police_lock); |
53 | 42 | ||
54 | static __inline__ struct tcf_police * tcf_police_lookup(u32 index) | 43 | static struct tcf_hashinfo police_hash_info = { |
55 | { | 44 | .htab = tcf_police_ht, |
56 | struct tcf_police *p; | 45 | .hmask = POL_TAB_MASK, |
46 | .lock = &police_lock, | ||
47 | }; | ||
57 | 48 | ||
58 | read_lock(&police_lock); | 49 | /* Each policer is serialized by its individual spinlock */ |
59 | for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) { | ||
60 | if (p->index == index) | ||
61 | break; | ||
62 | } | ||
63 | read_unlock(&police_lock); | ||
64 | return p; | ||
65 | } | ||
66 | 50 | ||
67 | #ifdef CONFIG_NET_CLS_ACT | 51 | #ifdef CONFIG_NET_CLS_ACT |
68 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, | 52 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, |
69 | int type, struct tc_action *a) | 53 | int type, struct tc_action *a) |
70 | { | 54 | { |
71 | struct tcf_police *p; | 55 | struct tcf_common *p; |
72 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; | 56 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
73 | struct rtattr *r; | 57 | struct rtattr *r; |
74 | 58 | ||
@@ -76,10 +60,10 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c | |||
76 | 60 | ||
77 | s_i = cb->args[0]; | 61 | s_i = cb->args[0]; |
78 | 62 | ||
79 | for (i = 0; i < MY_TAB_SIZE; i++) { | 63 | for (i = 0; i < (POL_TAB_MASK + 1); i++) { |
80 | p = tcf_police_ht[tcf_police_hash(i)]; | 64 | p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)]; |
81 | 65 | ||
82 | for (; p; p = p->next) { | 66 | for (; p; p = p->tcfc_next) { |
83 | index++; | 67 | index++; |
84 | if (index < s_i) | 68 | if (index < s_i) |
85 | continue; | 69 | continue; |
@@ -110,48 +94,26 @@ rtattr_failure: | |||
110 | skb_trim(skb, (u8*)r - skb->data); | 94 | skb_trim(skb, (u8*)r - skb->data); |
111 | goto done; | 95 | goto done; |
112 | } | 96 | } |
113 | |||
114 | static inline int | ||
115 | tcf_act_police_hash_search(struct tc_action *a, u32 index) | ||
116 | { | ||
117 | struct tcf_police *p = tcf_police_lookup(index); | ||
118 | |||
119 | if (p != NULL) { | ||
120 | a->priv = p; | ||
121 | return 1; | ||
122 | } else { | ||
123 | return 0; | ||
124 | } | ||
125 | } | ||
126 | #endif | 97 | #endif |
127 | 98 | ||
128 | static inline u32 tcf_police_new_index(void) | ||
129 | { | ||
130 | do { | ||
131 | if (++idx_gen == 0) | ||
132 | idx_gen = 1; | ||
133 | } while (tcf_police_lookup(idx_gen)); | ||
134 | |||
135 | return idx_gen; | ||
136 | } | ||
137 | |||
138 | void tcf_police_destroy(struct tcf_police *p) | 99 | void tcf_police_destroy(struct tcf_police *p) |
139 | { | 100 | { |
140 | unsigned h = tcf_police_hash(p->index); | 101 | unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); |
141 | struct tcf_police **p1p; | 102 | struct tcf_common **p1p; |
142 | 103 | ||
143 | for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) { | 104 | for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) { |
144 | if (*p1p == p) { | 105 | if (*p1p == &p->common) { |
145 | write_lock_bh(&police_lock); | 106 | write_lock_bh(&police_lock); |
146 | *p1p = p->next; | 107 | *p1p = p->tcf_next; |
147 | write_unlock_bh(&police_lock); | 108 | write_unlock_bh(&police_lock); |
148 | #ifdef CONFIG_NET_ESTIMATOR | 109 | #ifdef CONFIG_NET_ESTIMATOR |
149 | gen_kill_estimator(&p->bstats, &p->rate_est); | 110 | gen_kill_estimator(&p->tcf_bstats, |
111 | &p->tcf_rate_est); | ||
150 | #endif | 112 | #endif |
151 | if (p->R_tab) | 113 | if (p->tcfp_R_tab) |
152 | qdisc_put_rtab(p->R_tab); | 114 | qdisc_put_rtab(p->tcfp_R_tab); |
153 | if (p->P_tab) | 115 | if (p->tcfp_P_tab) |
154 | qdisc_put_rtab(p->P_tab); | 116 | qdisc_put_rtab(p->tcfp_P_tab); |
155 | kfree(p); | 117 | kfree(p); |
156 | return; | 118 | return; |
157 | } | 119 | } |
@@ -167,7 +129,7 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, | |||
167 | int ret = 0, err; | 129 | int ret = 0, err; |
168 | struct rtattr *tb[TCA_POLICE_MAX]; | 130 | struct rtattr *tb[TCA_POLICE_MAX]; |
169 | struct tc_police *parm; | 131 | struct tc_police *parm; |
170 | struct tcf_police *p; | 132 | struct tcf_police *police; |
171 | struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; | 133 | struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; |
172 | 134 | ||
173 | if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) | 135 | if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) |
@@ -185,27 +147,32 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, | |||
185 | RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) | 147 | RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) |
186 | return -EINVAL; | 148 | return -EINVAL; |
187 | 149 | ||
188 | if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { | 150 | if (parm->index) { |
189 | a->priv = p; | 151 | struct tcf_common *pc; |
190 | if (bind) { | 152 | |
191 | p->bindcnt += 1; | 153 | pc = tcf_hash_lookup(parm->index, &police_hash_info); |
192 | p->refcnt += 1; | 154 | if (pc != NULL) { |
155 | a->priv = pc; | ||
156 | police = to_police(pc); | ||
157 | if (bind) { | ||
158 | police->tcf_bindcnt += 1; | ||
159 | police->tcf_refcnt += 1; | ||
160 | } | ||
161 | if (ovr) | ||
162 | goto override; | ||
163 | return ret; | ||
193 | } | 164 | } |
194 | if (ovr) | ||
195 | goto override; | ||
196 | return ret; | ||
197 | } | 165 | } |
198 | 166 | ||
199 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 167 | police = kzalloc(sizeof(*police), GFP_KERNEL); |
200 | if (p == NULL) | 168 | if (police == NULL) |
201 | return -ENOMEM; | 169 | return -ENOMEM; |
202 | |||
203 | ret = ACT_P_CREATED; | 170 | ret = ACT_P_CREATED; |
204 | p->refcnt = 1; | 171 | police->tcf_refcnt = 1; |
205 | spin_lock_init(&p->lock); | 172 | spin_lock_init(&police->tcf_lock); |
206 | p->stats_lock = &p->lock; | 173 | police->tcf_stats_lock = &police->tcf_lock; |
207 | if (bind) | 174 | if (bind) |
208 | p->bindcnt = 1; | 175 | police->tcf_bindcnt = 1; |
209 | override: | 176 | override: |
210 | if (parm->rate.rate) { | 177 | if (parm->rate.rate) { |
211 | err = -ENOMEM; | 178 | err = -ENOMEM; |
@@ -215,67 +182,71 @@ override: | |||
215 | if (parm->peakrate.rate) { | 182 | if (parm->peakrate.rate) { |
216 | P_tab = qdisc_get_rtab(&parm->peakrate, | 183 | P_tab = qdisc_get_rtab(&parm->peakrate, |
217 | tb[TCA_POLICE_PEAKRATE-1]); | 184 | tb[TCA_POLICE_PEAKRATE-1]); |
218 | if (p->P_tab == NULL) { | 185 | if (P_tab == NULL) { |
219 | qdisc_put_rtab(R_tab); | 186 | qdisc_put_rtab(R_tab); |
220 | goto failure; | 187 | goto failure; |
221 | } | 188 | } |
222 | } | 189 | } |
223 | } | 190 | } |
224 | /* No failure allowed after this point */ | 191 | /* No failure allowed after this point */ |
225 | spin_lock_bh(&p->lock); | 192 | spin_lock_bh(&police->tcf_lock); |
226 | if (R_tab != NULL) { | 193 | if (R_tab != NULL) { |
227 | qdisc_put_rtab(p->R_tab); | 194 | qdisc_put_rtab(police->tcfp_R_tab); |
228 | p->R_tab = R_tab; | 195 | police->tcfp_R_tab = R_tab; |
229 | } | 196 | } |
230 | if (P_tab != NULL) { | 197 | if (P_tab != NULL) { |
231 | qdisc_put_rtab(p->P_tab); | 198 | qdisc_put_rtab(police->tcfp_P_tab); |
232 | p->P_tab = P_tab; | 199 | police->tcfp_P_tab = P_tab; |
233 | } | 200 | } |
234 | 201 | ||
235 | if (tb[TCA_POLICE_RESULT-1]) | 202 | if (tb[TCA_POLICE_RESULT-1]) |
236 | p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); | 203 | police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); |
237 | p->toks = p->burst = parm->burst; | 204 | police->tcfp_toks = police->tcfp_burst = parm->burst; |
238 | p->mtu = parm->mtu; | 205 | police->tcfp_mtu = parm->mtu; |
239 | if (p->mtu == 0) { | 206 | if (police->tcfp_mtu == 0) { |
240 | p->mtu = ~0; | 207 | police->tcfp_mtu = ~0; |
241 | if (p->R_tab) | 208 | if (police->tcfp_R_tab) |
242 | p->mtu = 255<<p->R_tab->rate.cell_log; | 209 | police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; |
243 | } | 210 | } |
244 | if (p->P_tab) | 211 | if (police->tcfp_P_tab) |
245 | p->ptoks = L2T_P(p, p->mtu); | 212 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); |
246 | p->action = parm->action; | 213 | police->tcf_action = parm->action; |
247 | 214 | ||
248 | #ifdef CONFIG_NET_ESTIMATOR | 215 | #ifdef CONFIG_NET_ESTIMATOR |
249 | if (tb[TCA_POLICE_AVRATE-1]) | 216 | if (tb[TCA_POLICE_AVRATE-1]) |
250 | p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | 217 | police->tcfp_ewma_rate = |
218 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | ||
251 | if (est) | 219 | if (est) |
252 | gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); | 220 | gen_replace_estimator(&police->tcf_bstats, |
221 | &police->tcf_rate_est, | ||
222 | police->tcf_stats_lock, est); | ||
253 | #endif | 223 | #endif |
254 | 224 | ||
255 | spin_unlock_bh(&p->lock); | 225 | spin_unlock_bh(&police->tcf_lock); |
256 | if (ret != ACT_P_CREATED) | 226 | if (ret != ACT_P_CREATED) |
257 | return ret; | 227 | return ret; |
258 | 228 | ||
259 | PSCHED_GET_TIME(p->t_c); | 229 | PSCHED_GET_TIME(police->tcfp_t_c); |
260 | p->index = parm->index ? : tcf_police_new_index(); | 230 | police->tcf_index = parm->index ? parm->index : |
261 | h = tcf_police_hash(p->index); | 231 | tcf_hash_new_index(&police_idx_gen, &police_hash_info); |
232 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | ||
262 | write_lock_bh(&police_lock); | 233 | write_lock_bh(&police_lock); |
263 | p->next = tcf_police_ht[h]; | 234 | police->tcf_next = tcf_police_ht[h]; |
264 | tcf_police_ht[h] = p; | 235 | tcf_police_ht[h] = &police->common; |
265 | write_unlock_bh(&police_lock); | 236 | write_unlock_bh(&police_lock); |
266 | 237 | ||
267 | a->priv = p; | 238 | a->priv = police; |
268 | return ret; | 239 | return ret; |
269 | 240 | ||
270 | failure: | 241 | failure: |
271 | if (ret == ACT_P_CREATED) | 242 | if (ret == ACT_P_CREATED) |
272 | kfree(p); | 243 | kfree(police); |
273 | return err; | 244 | return err; |
274 | } | 245 | } |
275 | 246 | ||
276 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) | 247 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) |
277 | { | 248 | { |
278 | struct tcf_police *p = PRIV(a); | 249 | struct tcf_police *p = a->priv; |
279 | 250 | ||
280 | if (p != NULL) | 251 | if (p != NULL) |
281 | return tcf_police_release(p, bind); | 252 | return tcf_police_release(p, bind); |
@@ -285,86 +256,87 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind) | |||
285 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | 256 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, |
286 | struct tcf_result *res) | 257 | struct tcf_result *res) |
287 | { | 258 | { |
259 | struct tcf_police *police = a->priv; | ||
288 | psched_time_t now; | 260 | psched_time_t now; |
289 | struct tcf_police *p = PRIV(a); | ||
290 | long toks; | 261 | long toks; |
291 | long ptoks = 0; | 262 | long ptoks = 0; |
292 | 263 | ||
293 | spin_lock(&p->lock); | 264 | spin_lock(&police->tcf_lock); |
294 | 265 | ||
295 | p->bstats.bytes += skb->len; | 266 | police->tcf_bstats.bytes += skb->len; |
296 | p->bstats.packets++; | 267 | police->tcf_bstats.packets++; |
297 | 268 | ||
298 | #ifdef CONFIG_NET_ESTIMATOR | 269 | #ifdef CONFIG_NET_ESTIMATOR |
299 | if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { | 270 | if (police->tcfp_ewma_rate && |
300 | p->qstats.overlimits++; | 271 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { |
301 | spin_unlock(&p->lock); | 272 | police->tcf_qstats.overlimits++; |
302 | return p->action; | 273 | spin_unlock(&police->tcf_lock); |
274 | return police->tcf_action; | ||
303 | } | 275 | } |
304 | #endif | 276 | #endif |
305 | 277 | ||
306 | if (skb->len <= p->mtu) { | 278 | if (skb->len <= police->tcfp_mtu) { |
307 | if (p->R_tab == NULL) { | 279 | if (police->tcfp_R_tab == NULL) { |
308 | spin_unlock(&p->lock); | 280 | spin_unlock(&police->tcf_lock); |
309 | return p->result; | 281 | return police->tcfp_result; |
310 | } | 282 | } |
311 | 283 | ||
312 | PSCHED_GET_TIME(now); | 284 | PSCHED_GET_TIME(now); |
313 | 285 | ||
314 | toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); | 286 | toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, |
315 | 287 | police->tcfp_burst); | |
316 | if (p->P_tab) { | 288 | if (police->tcfp_P_tab) { |
317 | ptoks = toks + p->ptoks; | 289 | ptoks = toks + police->tcfp_ptoks; |
318 | if (ptoks > (long)L2T_P(p, p->mtu)) | 290 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) |
319 | ptoks = (long)L2T_P(p, p->mtu); | 291 | ptoks = (long)L2T_P(police, police->tcfp_mtu); |
320 | ptoks -= L2T_P(p, skb->len); | 292 | ptoks -= L2T_P(police, skb->len); |
321 | } | 293 | } |
322 | toks += p->toks; | 294 | toks += police->tcfp_toks; |
323 | if (toks > (long)p->burst) | 295 | if (toks > (long)police->tcfp_burst) |
324 | toks = p->burst; | 296 | toks = police->tcfp_burst; |
325 | toks -= L2T(p, skb->len); | 297 | toks -= L2T(police, skb->len); |
326 | |||
327 | if ((toks|ptoks) >= 0) { | 298 | if ((toks|ptoks) >= 0) { |
328 | p->t_c = now; | 299 | police->tcfp_t_c = now; |
329 | p->toks = toks; | 300 | police->tcfp_toks = toks; |
330 | p->ptoks = ptoks; | 301 | police->tcfp_ptoks = ptoks; |
331 | spin_unlock(&p->lock); | 302 | spin_unlock(&police->tcf_lock); |
332 | return p->result; | 303 | return police->tcfp_result; |
333 | } | 304 | } |
334 | } | 305 | } |
335 | 306 | ||
336 | p->qstats.overlimits++; | 307 | police->tcf_qstats.overlimits++; |
337 | spin_unlock(&p->lock); | 308 | spin_unlock(&police->tcf_lock); |
338 | return p->action; | 309 | return police->tcf_action; |
339 | } | 310 | } |
340 | 311 | ||
341 | static int | 312 | static int |
342 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 313 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
343 | { | 314 | { |
344 | unsigned char *b = skb->tail; | 315 | unsigned char *b = skb->tail; |
316 | struct tcf_police *police = a->priv; | ||
345 | struct tc_police opt; | 317 | struct tc_police opt; |
346 | struct tcf_police *p = PRIV(a); | 318 | |
347 | 319 | opt.index = police->tcf_index; | |
348 | opt.index = p->index; | 320 | opt.action = police->tcf_action; |
349 | opt.action = p->action; | 321 | opt.mtu = police->tcfp_mtu; |
350 | opt.mtu = p->mtu; | 322 | opt.burst = police->tcfp_burst; |
351 | opt.burst = p->burst; | 323 | opt.refcnt = police->tcf_refcnt - ref; |
352 | opt.refcnt = p->refcnt - ref; | 324 | opt.bindcnt = police->tcf_bindcnt - bind; |
353 | opt.bindcnt = p->bindcnt - bind; | 325 | if (police->tcfp_R_tab) |
354 | if (p->R_tab) | 326 | opt.rate = police->tcfp_R_tab->rate; |
355 | opt.rate = p->R_tab->rate; | ||
356 | else | 327 | else |
357 | memset(&opt.rate, 0, sizeof(opt.rate)); | 328 | memset(&opt.rate, 0, sizeof(opt.rate)); |
358 | if (p->P_tab) | 329 | if (police->tcfp_P_tab) |
359 | opt.peakrate = p->P_tab->rate; | 330 | opt.peakrate = police->tcfp_P_tab->rate; |
360 | else | 331 | else |
361 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | 332 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); |
362 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); | 333 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); |
363 | if (p->result) | 334 | if (police->tcfp_result) |
364 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); | 335 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), |
336 | &police->tcfp_result); | ||
365 | #ifdef CONFIG_NET_ESTIMATOR | 337 | #ifdef CONFIG_NET_ESTIMATOR |
366 | if (p->ewma_rate) | 338 | if (police->tcfp_ewma_rate) |
367 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); | 339 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); |
368 | #endif | 340 | #endif |
369 | return skb->len; | 341 | return skb->len; |
370 | 342 | ||
@@ -379,13 +351,14 @@ MODULE_LICENSE("GPL"); | |||
379 | 351 | ||
380 | static struct tc_action_ops act_police_ops = { | 352 | static struct tc_action_ops act_police_ops = { |
381 | .kind = "police", | 353 | .kind = "police", |
354 | .hinfo = &police_hash_info, | ||
382 | .type = TCA_ID_POLICE, | 355 | .type = TCA_ID_POLICE, |
383 | .capab = TCA_CAP_NONE, | 356 | .capab = TCA_CAP_NONE, |
384 | .owner = THIS_MODULE, | 357 | .owner = THIS_MODULE, |
385 | .act = tcf_act_police, | 358 | .act = tcf_act_police, |
386 | .dump = tcf_act_police_dump, | 359 | .dump = tcf_act_police_dump, |
387 | .cleanup = tcf_act_police_cleanup, | 360 | .cleanup = tcf_act_police_cleanup, |
388 | .lookup = tcf_act_police_hash_search, | 361 | .lookup = tcf_hash_search, |
389 | .init = tcf_act_police_locate, | 362 | .init = tcf_act_police_locate, |
390 | .walk = tcf_act_police_walker | 363 | .walk = tcf_act_police_walker |
391 | }; | 364 | }; |
@@ -407,10 +380,39 @@ module_exit(police_cleanup_module); | |||
407 | 380 | ||
408 | #else /* CONFIG_NET_CLS_ACT */ | 381 | #else /* CONFIG_NET_CLS_ACT */ |
409 | 382 | ||
410 | struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) | 383 | static struct tcf_common *tcf_police_lookup(u32 index) |
411 | { | 384 | { |
412 | unsigned h; | 385 | struct tcf_hashinfo *hinfo = &police_hash_info; |
413 | struct tcf_police *p; | 386 | struct tcf_common *p; |
387 | |||
388 | read_lock(hinfo->lock); | ||
389 | for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; | ||
390 | p = p->tcfc_next) { | ||
391 | if (p->tcfc_index == index) | ||
392 | break; | ||
393 | } | ||
394 | read_unlock(hinfo->lock); | ||
395 | |||
396 | return p; | ||
397 | } | ||
398 | |||
399 | static u32 tcf_police_new_index(void) | ||
400 | { | ||
401 | u32 *idx_gen = &police_idx_gen; | ||
402 | u32 val = *idx_gen; | ||
403 | |||
404 | do { | ||
405 | if (++val == 0) | ||
406 | val = 1; | ||
407 | } while (tcf_police_lookup(val)); | ||
408 | |||
409 | return (*idx_gen = val); | ||
410 | } | ||
411 | |||
412 | struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) | ||
413 | { | ||
414 | unsigned int h; | ||
415 | struct tcf_police *police; | ||
414 | struct rtattr *tb[TCA_POLICE_MAX]; | 416 | struct rtattr *tb[TCA_POLICE_MAX]; |
415 | struct tc_police *parm; | 417 | struct tc_police *parm; |
416 | 418 | ||
@@ -423,149 +425,158 @@ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) | |||
423 | 425 | ||
424 | parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); | 426 | parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); |
425 | 427 | ||
426 | if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { | 428 | if (parm->index) { |
427 | p->refcnt++; | 429 | struct tcf_common *pc; |
428 | return p; | ||
429 | } | ||
430 | 430 | ||
431 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 431 | pc = tcf_police_lookup(parm->index); |
432 | if (p == NULL) | 432 | if (pc) { |
433 | police = to_police(pc); | ||
434 | police->tcf_refcnt++; | ||
435 | return police; | ||
436 | } | ||
437 | } | ||
438 | police = kzalloc(sizeof(*police), GFP_KERNEL); | ||
439 | if (unlikely(!police)) | ||
433 | return NULL; | 440 | return NULL; |
434 | 441 | ||
435 | p->refcnt = 1; | 442 | police->tcf_refcnt = 1; |
436 | spin_lock_init(&p->lock); | 443 | spin_lock_init(&police->tcf_lock); |
437 | p->stats_lock = &p->lock; | 444 | police->tcf_stats_lock = &police->tcf_lock; |
438 | if (parm->rate.rate) { | 445 | if (parm->rate.rate) { |
439 | p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); | 446 | police->tcfp_R_tab = |
440 | if (p->R_tab == NULL) | 447 | qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); |
448 | if (police->tcfp_R_tab == NULL) | ||
441 | goto failure; | 449 | goto failure; |
442 | if (parm->peakrate.rate) { | 450 | if (parm->peakrate.rate) { |
443 | p->P_tab = qdisc_get_rtab(&parm->peakrate, | 451 | police->tcfp_P_tab = |
444 | tb[TCA_POLICE_PEAKRATE-1]); | 452 | qdisc_get_rtab(&parm->peakrate, |
445 | if (p->P_tab == NULL) | 453 | tb[TCA_POLICE_PEAKRATE-1]); |
454 | if (police->tcfp_P_tab == NULL) | ||
446 | goto failure; | 455 | goto failure; |
447 | } | 456 | } |
448 | } | 457 | } |
449 | if (tb[TCA_POLICE_RESULT-1]) { | 458 | if (tb[TCA_POLICE_RESULT-1]) { |
450 | if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) | 459 | if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) |
451 | goto failure; | 460 | goto failure; |
452 | p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); | 461 | police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); |
453 | } | 462 | } |
454 | #ifdef CONFIG_NET_ESTIMATOR | 463 | #ifdef CONFIG_NET_ESTIMATOR |
455 | if (tb[TCA_POLICE_AVRATE-1]) { | 464 | if (tb[TCA_POLICE_AVRATE-1]) { |
456 | if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) | 465 | if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) |
457 | goto failure; | 466 | goto failure; |
458 | p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | 467 | police->tcfp_ewma_rate = |
468 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | ||
459 | } | 469 | } |
460 | #endif | 470 | #endif |
461 | p->toks = p->burst = parm->burst; | 471 | police->tcfp_toks = police->tcfp_burst = parm->burst; |
462 | p->mtu = parm->mtu; | 472 | police->tcfp_mtu = parm->mtu; |
463 | if (p->mtu == 0) { | 473 | if (police->tcfp_mtu == 0) { |
464 | p->mtu = ~0; | 474 | police->tcfp_mtu = ~0; |
465 | if (p->R_tab) | 475 | if (police->tcfp_R_tab) |
466 | p->mtu = 255<<p->R_tab->rate.cell_log; | 476 | police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; |
467 | } | 477 | } |
468 | if (p->P_tab) | 478 | if (police->tcfp_P_tab) |
469 | p->ptoks = L2T_P(p, p->mtu); | 479 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); |
470 | PSCHED_GET_TIME(p->t_c); | 480 | PSCHED_GET_TIME(police->tcfp_t_c); |
471 | p->index = parm->index ? : tcf_police_new_index(); | 481 | police->tcf_index = parm->index ? parm->index : |
472 | p->action = parm->action; | 482 | tcf_police_new_index(); |
483 | police->tcf_action = parm->action; | ||
473 | #ifdef CONFIG_NET_ESTIMATOR | 484 | #ifdef CONFIG_NET_ESTIMATOR |
474 | if (est) | 485 | if (est) |
475 | gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); | 486 | gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, |
487 | police->tcf_stats_lock, est); | ||
476 | #endif | 488 | #endif |
477 | h = tcf_police_hash(p->index); | 489 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); |
478 | write_lock_bh(&police_lock); | 490 | write_lock_bh(&police_lock); |
479 | p->next = tcf_police_ht[h]; | 491 | police->tcf_next = tcf_police_ht[h]; |
480 | tcf_police_ht[h] = p; | 492 | tcf_police_ht[h] = &police->common; |
481 | write_unlock_bh(&police_lock); | 493 | write_unlock_bh(&police_lock); |
482 | return p; | 494 | return police; |
483 | 495 | ||
484 | failure: | 496 | failure: |
485 | if (p->R_tab) | 497 | if (police->tcfp_R_tab) |
486 | qdisc_put_rtab(p->R_tab); | 498 | qdisc_put_rtab(police->tcfp_R_tab); |
487 | kfree(p); | 499 | kfree(police); |
488 | return NULL; | 500 | return NULL; |
489 | } | 501 | } |
490 | 502 | ||
491 | int tcf_police(struct sk_buff *skb, struct tcf_police *p) | 503 | int tcf_police(struct sk_buff *skb, struct tcf_police *police) |
492 | { | 504 | { |
493 | psched_time_t now; | 505 | psched_time_t now; |
494 | long toks; | 506 | long toks; |
495 | long ptoks = 0; | 507 | long ptoks = 0; |
496 | 508 | ||
497 | spin_lock(&p->lock); | 509 | spin_lock(&police->tcf_lock); |
498 | 510 | ||
499 | p->bstats.bytes += skb->len; | 511 | police->tcf_bstats.bytes += skb->len; |
500 | p->bstats.packets++; | 512 | police->tcf_bstats.packets++; |
501 | 513 | ||
502 | #ifdef CONFIG_NET_ESTIMATOR | 514 | #ifdef CONFIG_NET_ESTIMATOR |
503 | if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { | 515 | if (police->tcfp_ewma_rate && |
504 | p->qstats.overlimits++; | 516 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { |
505 | spin_unlock(&p->lock); | 517 | police->tcf_qstats.overlimits++; |
506 | return p->action; | 518 | spin_unlock(&police->tcf_lock); |
519 | return police->tcf_action; | ||
507 | } | 520 | } |
508 | #endif | 521 | #endif |
509 | 522 | if (skb->len <= police->tcfp_mtu) { | |
510 | if (skb->len <= p->mtu) { | 523 | if (police->tcfp_R_tab == NULL) { |
511 | if (p->R_tab == NULL) { | 524 | spin_unlock(&police->tcf_lock); |
512 | spin_unlock(&p->lock); | 525 | return police->tcfp_result; |
513 | return p->result; | ||
514 | } | 526 | } |
515 | 527 | ||
516 | PSCHED_GET_TIME(now); | 528 | PSCHED_GET_TIME(now); |
517 | 529 | toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, | |
518 | toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); | 530 | police->tcfp_burst); |
519 | 531 | if (police->tcfp_P_tab) { | |
520 | if (p->P_tab) { | 532 | ptoks = toks + police->tcfp_ptoks; |
521 | ptoks = toks + p->ptoks; | 533 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) |
522 | if (ptoks > (long)L2T_P(p, p->mtu)) | 534 | ptoks = (long)L2T_P(police, police->tcfp_mtu); |
523 | ptoks = (long)L2T_P(p, p->mtu); | 535 | ptoks -= L2T_P(police, skb->len); |
524 | ptoks -= L2T_P(p, skb->len); | ||
525 | } | 536 | } |
526 | toks += p->toks; | 537 | toks += police->tcfp_toks; |
527 | if (toks > (long)p->burst) | 538 | if (toks > (long)police->tcfp_burst) |
528 | toks = p->burst; | 539 | toks = police->tcfp_burst; |
529 | toks -= L2T(p, skb->len); | 540 | toks -= L2T(police, skb->len); |
530 | |||
531 | if ((toks|ptoks) >= 0) { | 541 | if ((toks|ptoks) >= 0) { |
532 | p->t_c = now; | 542 | police->tcfp_t_c = now; |
533 | p->toks = toks; | 543 | police->tcfp_toks = toks; |
534 | p->ptoks = ptoks; | 544 | police->tcfp_ptoks = ptoks; |
535 | spin_unlock(&p->lock); | 545 | spin_unlock(&police->tcf_lock); |
536 | return p->result; | 546 | return police->tcfp_result; |
537 | } | 547 | } |
538 | } | 548 | } |
539 | 549 | ||
540 | p->qstats.overlimits++; | 550 | police->tcf_qstats.overlimits++; |
541 | spin_unlock(&p->lock); | 551 | spin_unlock(&police->tcf_lock); |
542 | return p->action; | 552 | return police->tcf_action; |
543 | } | 553 | } |
544 | EXPORT_SYMBOL(tcf_police); | 554 | EXPORT_SYMBOL(tcf_police); |
545 | 555 | ||
546 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) | 556 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) |
547 | { | 557 | { |
548 | unsigned char *b = skb->tail; | 558 | unsigned char *b = skb->tail; |
549 | struct tc_police opt; | 559 | struct tc_police opt; |
550 | 560 | ||
551 | opt.index = p->index; | 561 | opt.index = police->tcf_index; |
552 | opt.action = p->action; | 562 | opt.action = police->tcf_action; |
553 | opt.mtu = p->mtu; | 563 | opt.mtu = police->tcfp_mtu; |
554 | opt.burst = p->burst; | 564 | opt.burst = police->tcfp_burst; |
555 | if (p->R_tab) | 565 | if (police->tcfp_R_tab) |
556 | opt.rate = p->R_tab->rate; | 566 | opt.rate = police->tcfp_R_tab->rate; |
557 | else | 567 | else |
558 | memset(&opt.rate, 0, sizeof(opt.rate)); | 568 | memset(&opt.rate, 0, sizeof(opt.rate)); |
559 | if (p->P_tab) | 569 | if (police->tcfp_P_tab) |
560 | opt.peakrate = p->P_tab->rate; | 570 | opt.peakrate = police->tcfp_P_tab->rate; |
561 | else | 571 | else |
562 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | 572 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); |
563 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); | 573 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); |
564 | if (p->result) | 574 | if (police->tcfp_result) |
565 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); | 575 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), |
576 | &police->tcfp_result); | ||
566 | #ifdef CONFIG_NET_ESTIMATOR | 577 | #ifdef CONFIG_NET_ESTIMATOR |
567 | if (p->ewma_rate) | 578 | if (police->tcfp_ewma_rate) |
568 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); | 579 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); |
569 | #endif | 580 | #endif |
570 | return skb->len; | 581 | return skb->len; |
571 | 582 | ||
@@ -574,19 +585,20 @@ rtattr_failure: | |||
574 | return -1; | 585 | return -1; |
575 | } | 586 | } |
576 | 587 | ||
577 | int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p) | 588 | int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) |
578 | { | 589 | { |
579 | struct gnet_dump d; | 590 | struct gnet_dump d; |
580 | 591 | ||
581 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, | 592 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, |
582 | TCA_XSTATS, p->stats_lock, &d) < 0) | 593 | TCA_XSTATS, police->tcf_stats_lock, |
594 | &d) < 0) | ||
583 | goto errout; | 595 | goto errout; |
584 | 596 | ||
585 | if (gnet_stats_copy_basic(&d, &p->bstats) < 0 || | 597 | if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 || |
586 | #ifdef CONFIG_NET_ESTIMATOR | 598 | #ifdef CONFIG_NET_ESTIMATOR |
587 | gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 || | 599 | gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 || |
588 | #endif | 600 | #endif |
589 | gnet_stats_copy_queue(&d, &p->qstats) < 0) | 601 | gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0) |
590 | goto errout; | 602 | goto errout; |
591 | 603 | ||
592 | if (gnet_stats_finish_copy(&d) < 0) | 604 | if (gnet_stats_finish_copy(&d) < 0) |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 17105c82537f..8c1ab8ad8fa6 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -20,54 +20,175 @@ | |||
20 | 20 | ||
21 | #define TCA_ACT_SIMP 22 | 21 | #define TCA_ACT_SIMP 22 |
22 | 22 | ||
23 | /* XXX: Hide all these common elements under some macro | ||
24 | * probably | ||
25 | */ | ||
26 | #include <linux/tc_act/tc_defact.h> | 23 | #include <linux/tc_act/tc_defact.h> |
27 | #include <net/tc_act/tc_defact.h> | 24 | #include <net/tc_act/tc_defact.h> |
28 | 25 | ||
29 | /* use generic hash table with 8 buckets */ | 26 | #define SIMP_TAB_MASK 7 |
30 | #define MY_TAB_SIZE 8 | 27 | static struct tcf_common *tcf_simp_ht[SIMP_TAB_MASK + 1]; |
31 | #define MY_TAB_MASK (MY_TAB_SIZE - 1) | 28 | static u32 simp_idx_gen; |
32 | static u32 idx_gen; | ||
33 | static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE]; | ||
34 | static DEFINE_RWLOCK(simp_lock); | 29 | static DEFINE_RWLOCK(simp_lock); |
35 | 30 | ||
36 | /* override the defaults */ | 31 | struct tcf_hashinfo simp_hash_info = { |
37 | #define tcf_st tcf_defact | 32 | .htab = tcf_simp_ht, |
38 | #define tc_st tc_defact | 33 | .hmask = SIMP_TAB_MASK, |
39 | #define tcf_t_lock simp_lock | 34 | .lock = &simp_lock, |
40 | #define tcf_ht tcf_simp_ht | 35 | }; |
41 | |||
42 | #define CONFIG_NET_ACT_INIT 1 | ||
43 | #include <net/pkt_act.h> | ||
44 | #include <net/act_generic.h> | ||
45 | 36 | ||
46 | static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | 37 | static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) |
47 | { | 38 | { |
48 | struct tcf_defact *p = PRIV(a, defact); | 39 | struct tcf_defact *d = a->priv; |
49 | 40 | ||
50 | spin_lock(&p->lock); | 41 | spin_lock(&d->tcf_lock); |
51 | p->tm.lastuse = jiffies; | 42 | d->tcf_tm.lastuse = jiffies; |
52 | p->bstats.bytes += skb->len; | 43 | d->tcf_bstats.bytes += skb->len; |
53 | p->bstats.packets++; | 44 | d->tcf_bstats.packets++; |
54 | 45 | ||
55 | /* print policy string followed by _ then packet count | 46 | /* print policy string followed by _ then packet count |
56 | * Example if this was the 3rd packet and the string was "hello" | 47 | * Example if this was the 3rd packet and the string was "hello" |
57 | * then it would look like "hello_3" (without quotes) | 48 | * then it would look like "hello_3" (without quotes) |
58 | **/ | 49 | **/ |
59 | printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets); | 50 | printk("simple: %s_%d\n", |
60 | spin_unlock(&p->lock); | 51 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); |
61 | return p->action; | 52 | spin_unlock(&d->tcf_lock); |
53 | return d->tcf_action; | ||
54 | } | ||
55 | |||
56 | static int tcf_simp_release(struct tcf_defact *d, int bind) | ||
57 | { | ||
58 | int ret = 0; | ||
59 | if (d) { | ||
60 | if (bind) | ||
61 | d->tcf_bindcnt--; | ||
62 | d->tcf_refcnt--; | ||
63 | if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) { | ||
64 | kfree(d->tcfd_defdata); | ||
65 | tcf_hash_destroy(&d->common, &simp_hash_info); | ||
66 | ret = 1; | ||
67 | } | ||
68 | } | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) | ||
73 | { | ||
74 | d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL); | ||
75 | if (unlikely(!d->tcfd_defdata)) | ||
76 | return -ENOMEM; | ||
77 | d->tcfd_datalen = datalen; | ||
78 | memcpy(d->tcfd_defdata, defdata, datalen); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) | ||
83 | { | ||
84 | kfree(d->tcfd_defdata); | ||
85 | return alloc_defdata(d, datalen, defdata); | ||
86 | } | ||
87 | |||
88 | static int tcf_simp_init(struct rtattr *rta, struct rtattr *est, | ||
89 | struct tc_action *a, int ovr, int bind) | ||
90 | { | ||
91 | struct rtattr *tb[TCA_DEF_MAX]; | ||
92 | struct tc_defact *parm; | ||
93 | struct tcf_defact *d; | ||
94 | struct tcf_common *pc; | ||
95 | void *defdata; | ||
96 | u32 datalen = 0; | ||
97 | int ret = 0; | ||
98 | |||
99 | if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) | ||
100 | return -EINVAL; | ||
101 | |||
102 | if (tb[TCA_DEF_PARMS - 1] == NULL || | ||
103 | RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) | ||
104 | return -EINVAL; | ||
105 | |||
106 | parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); | ||
107 | defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); | ||
108 | if (defdata == NULL) | ||
109 | return -EINVAL; | ||
110 | |||
111 | datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); | ||
112 | if (datalen <= 0) | ||
113 | return -EINVAL; | ||
114 | |||
115 | pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info); | ||
116 | if (!pc) { | ||
117 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, | ||
118 | &simp_idx_gen, &simp_hash_info); | ||
119 | if (unlikely(!pc)) | ||
120 | return -ENOMEM; | ||
121 | |||
122 | d = to_defact(pc); | ||
123 | ret = alloc_defdata(d, datalen, defdata); | ||
124 | if (ret < 0) { | ||
125 | kfree(pc); | ||
126 | return ret; | ||
127 | } | ||
128 | ret = ACT_P_CREATED; | ||
129 | } else { | ||
130 | d = to_defact(pc); | ||
131 | if (!ovr) { | ||
132 | tcf_simp_release(d, bind); | ||
133 | return -EEXIST; | ||
134 | } | ||
135 | realloc_defdata(d, datalen, defdata); | ||
136 | } | ||
137 | |||
138 | spin_lock_bh(&d->tcf_lock); | ||
139 | d->tcf_action = parm->action; | ||
140 | spin_unlock_bh(&d->tcf_lock); | ||
141 | |||
142 | if (ret == ACT_P_CREATED) | ||
143 | tcf_hash_insert(pc, &simp_hash_info); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static inline int tcf_simp_cleanup(struct tc_action *a, int bind) | ||
148 | { | ||
149 | struct tcf_defact *d = a->priv; | ||
150 | |||
151 | if (d) | ||
152 | return tcf_simp_release(d, bind); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | ||
157 | int bind, int ref) | ||
158 | { | ||
159 | unsigned char *b = skb->tail; | ||
160 | struct tcf_defact *d = a->priv; | ||
161 | struct tc_defact opt; | ||
162 | struct tcf_t t; | ||
163 | |||
164 | opt.index = d->tcf_index; | ||
165 | opt.refcnt = d->tcf_refcnt - ref; | ||
166 | opt.bindcnt = d->tcf_bindcnt - bind; | ||
167 | opt.action = d->tcf_action; | ||
168 | RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); | ||
169 | RTA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata); | ||
170 | t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); | ||
171 | t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); | ||
172 | t.expires = jiffies_to_clock_t(d->tcf_tm.expires); | ||
173 | RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); | ||
174 | return skb->len; | ||
175 | |||
176 | rtattr_failure: | ||
177 | skb_trim(skb, b - skb->data); | ||
178 | return -1; | ||
62 | } | 179 | } |
63 | 180 | ||
64 | static struct tc_action_ops act_simp_ops = { | 181 | static struct tc_action_ops act_simp_ops = { |
65 | .kind = "simple", | 182 | .kind = "simple", |
66 | .type = TCA_ACT_SIMP, | 183 | .hinfo = &simp_hash_info, |
67 | .capab = TCA_CAP_NONE, | 184 | .type = TCA_ACT_SIMP, |
68 | .owner = THIS_MODULE, | 185 | .capab = TCA_CAP_NONE, |
69 | .act = tcf_simp, | 186 | .owner = THIS_MODULE, |
70 | tca_use_default_ops | 187 | .act = tcf_simp, |
188 | .dump = tcf_simp_dump, | ||
189 | .cleanup = tcf_simp_cleanup, | ||
190 | .init = tcf_simp_init, | ||
191 | .walk = tcf_generic_walker, | ||
71 | }; | 192 | }; |
72 | 193 | ||
73 | MODULE_AUTHOR("Jamal Hadi Salim(2005)"); | 194 | MODULE_AUTHOR("Jamal Hadi Salim(2005)"); |