upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / include / net / pkt_cls.h
1 #ifndef __NET_PKT_CLS_H
2 #define __NET_PKT_CLS_H
3
4 #include <linux/pkt_cls.h>
5 #include <net/sch_generic.h>
6 #include <net/act_api.h>
7
8 /* Basic packet classifier frontend definitions. */
9
10 struct tcf_walker
11 {
12         int     stop;
13         int     skip;
14         int     count;
15         int     (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
16 };
17
18 extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
19 extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
20 extern int ing_filter(struct sk_buff *skb);
21
22 static inline unsigned long
23 __cls_set_class(unsigned long *clp, unsigned long cl)
24 {
25         unsigned long old_cl;
26  
27         old_cl = *clp;
28         *clp = cl;
29         return old_cl;
30 }
31
32 static inline unsigned long
33 cls_set_class(struct tcf_proto *tp, unsigned long *clp, 
34         unsigned long cl)
35 {
36         unsigned long old_cl;
37         
38         tcf_tree_lock(tp);
39         old_cl = __cls_set_class(clp, cl);
40         tcf_tree_unlock(tp);
41  
42         return old_cl;
43 }
44
45 static inline void
46 tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
47 {
48         unsigned long cl;
49
50         cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
51         cl = cls_set_class(tp, &r->class, cl);
52         if (cl)
53                 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
54 }
55
56 static inline void
57 tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
58 {
59         unsigned long cl;
60
61         if ((cl = __cls_set_class(&r->class, 0)) != 0)
62                 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
63 }
64
65 #ifdef CONFIG_NET_CLS_ACT
66 static inline int
67 tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action,
68         struct rtattr *act_police_tlv, struct rtattr *rate_tlv)
69 {
70         int ret;
71         struct tc_action *act;
72
73         act = kmalloc(sizeof(*act), GFP_KERNEL);
74         if (NULL == act)
75                 return -ENOMEM;
76         memset(act, 0, sizeof(*act));
77         
78         ret = tcf_action_init_1(act_police_tlv, rate_tlv, act, "police",
79                 TCA_ACT_NOREPLACE, TCA_ACT_BIND);
80         if (ret < 0) {
81                 tcf_action_destroy(act, TCA_ACT_UNBIND);
82                 return ret;
83         }
84
85         act->type = TCA_OLD_COMPAT;
86
87         if (*action) {
88                 tcf_tree_lock(tp);
89                 act = xchg(action, act);
90                 tcf_tree_unlock(tp);
91
92                 tcf_action_destroy(act, TCA_ACT_UNBIND);
93         } else
94                 *action = act;
95
96         return 0;
97 }
98
99 static inline int
100 tcf_change_act(struct tcf_proto *tp, struct tc_action **action,
101         struct rtattr *act_tlv, struct rtattr *rate_tlv)
102 {
103         int ret;
104         struct tc_action *act;
105
106         act = kmalloc(sizeof(*act), GFP_KERNEL);
107         if (NULL == act)
108                 return -ENOMEM;
109         memset(act, 0, sizeof(*act));
110
111         ret = tcf_action_init(act_tlv, rate_tlv, act, NULL,
112                 TCA_ACT_NOREPLACE, TCA_ACT_BIND);
113         if (ret < 0) {
114                 tcf_action_destroy(act, TCA_ACT_UNBIND);
115                 return ret;
116         }
117
118         if (*action) {
119                 tcf_tree_lock(tp);
120                 act = xchg(action, act);
121                 tcf_tree_unlock(tp);
122
123                 tcf_action_destroy(act, TCA_ACT_UNBIND);
124         } else
125                 *action = act;
126
127         return 0;
128 }
129
130 static inline int
131 tcf_dump_act(struct sk_buff *skb, struct tc_action *action,
132         int act_type, int compat_type)
133 {
134         /*
135          * again for backward compatible mode - we want
136          * to work with both old and new modes of entering
137          * tc data even if iproute2  was newer - jhs
138          */
139         if (action) {
140                 struct rtattr * p_rta = (struct rtattr*) skb->tail;
141
142                 if (action->type != TCA_OLD_COMPAT) {
143                         RTA_PUT(skb, act_type, 0, NULL);
144                         if (tcf_action_dump(skb, action, 0, 0) < 0)
145                                 goto rtattr_failure;
146                 } else {
147                         RTA_PUT(skb, compat_type, 0, NULL);
148                         if (tcf_action_dump_old(skb, action, 0, 0) < 0)
149                                 goto rtattr_failure;
150                 }
151                 
152                 p_rta->rta_len = skb->tail - (u8*)p_rta;
153         }
154         return 0;
155
156 rtattr_failure:
157         return -1;
158 }
159 #endif /* CONFIG_NET_CLS_ACT */
160
161 #ifdef CONFIG_NET_CLS_IND
162 static inline int
163 tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
164 {
165         if (RTA_PAYLOAD(indev_tlv) >= IFNAMSIZ) {
166                 printk("cls: bad indev name %s\n", (char *) RTA_DATA(indev_tlv));
167                 return -EINVAL;
168         }
169
170         memset(indev, 0, IFNAMSIZ);
171         sprintf(indev, "%s", (char *) RTA_DATA(indev_tlv));
172
173         return 0;
174 }
175
176 static inline int
177 tcf_match_indev(struct sk_buff *skb, char *indev)
178 {
179         if (0 != indev[0]) {
180                 if  (NULL == skb->input_dev)
181                         return 0;
182                 else if (0 != strcmp(indev, skb->input_dev->name))
183                         return 0;
184         }
185
186         return 1;
187 }
188 #endif /* CONFIG_NET_CLS_IND */
189
190 #ifdef CONFIG_NET_CLS_POLICE
191 static inline int
192 tcf_change_police(struct tcf_proto *tp, struct tcf_police **police,
193         struct rtattr *police_tlv, struct rtattr *rate_tlv)
194 {
195         struct tcf_police *p = tcf_police_locate(police_tlv, rate_tlv);
196
197         if (*police) {
198                 tcf_tree_lock(tp);
199                 p = xchg(police, p);
200                 tcf_tree_unlock(tp);
201
202                 tcf_police_release(p, TCA_ACT_UNBIND);
203         } else
204                 *police = p;
205
206         return 0;
207 }
208
209 static inline int
210 tcf_dump_police(struct sk_buff *skb, struct tcf_police *police,
211         int police_type)
212 {
213         if (police) {
214                 struct rtattr * p_rta = (struct rtattr*) skb->tail;
215
216                 RTA_PUT(skb, police_type, 0, NULL);
217
218                 if (tcf_police_dump(skb, police) < 0)
219                         goto rtattr_failure;
220
221                 p_rta->rta_len = skb->tail - (u8*)p_rta;
222         }
223         return 0;
224
225 rtattr_failure:
226         return -1;
227 }
228 #endif /* CONFIG_NET_CLS_POLICE */
229
230 #endif