diff options
author | Patrick McHardy <kaber@trash.net> | 2007-07-15 03:02:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-07-15 03:02:31 -0400 |
commit | 73ca4918fbb98311421259d82ef4ab44feeace43 (patch) | |
tree | a5ae62e5474b3d28d7205ab3170aa73ff6d5f8ac /net/sched/sch_api.c | |
parent | f6853e2df3de82c1dac8f62ddcf3a8dfa302419e (diff) |
[NET_SCHED]: act_api: qdisc internal reclassify support
The behaviour of NET_CLS_POLICE for TC_POLICE_RECLASSIFY was to return
it to the qdisc, which could handle it internally or ignore it. With
NET_CLS_ACT however, tc_classify starts over at the first classifier
and never returns it to the qdisc. This makes it impossible to support
qdisc-internal reclassification, which in turn makes it impossible to
remove the old NET_CLS_POLICE code without breaking compatibility since
we have two qdiscs (CBQ and ATM) that support this.
This patch adds a tc_classify_compat function that handles
reclassification the old way and changes CBQ and ATM to use it.
This again is of course not fully backwards compatible with the previous
NET_CLS_ACT behaviour. Unfortunately there is no way to fully maintain
compatibility *and* support qdisc internal reclassification with
NET_CLS_ACT, but this seems like the better choice over keeping the two
incompatible options around forever.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 4fd0beca9450..13c09bc32aa3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -1145,47 +1145,57 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1145 | to this qdisc, (optionally) tests for protocol and asks | 1145 | to this qdisc, (optionally) tests for protocol and asks |
1146 | specific classifiers. | 1146 | specific classifiers. |
1147 | */ | 1147 | */ |
1148 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | ||
1149 | struct tcf_result *res) | ||
1150 | { | ||
1151 | __be16 protocol = skb->protocol; | ||
1152 | int err = 0; | ||
1153 | |||
1154 | for (; tp; tp = tp->next) { | ||
1155 | if ((tp->protocol == protocol || | ||
1156 | tp->protocol == htons(ETH_P_ALL)) && | ||
1157 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
1158 | #ifdef CONFIG_NET_CLS_ACT | ||
1159 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) | ||
1160 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); | ||
1161 | #endif | ||
1162 | return err; | ||
1163 | } | ||
1164 | } | ||
1165 | return -1; | ||
1166 | } | ||
1167 | EXPORT_SYMBOL(tc_classify_compat); | ||
1168 | |||
1148 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | 1169 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, |
1149 | struct tcf_result *res) | 1170 | struct tcf_result *res) |
1150 | { | 1171 | { |
1151 | int err = 0; | 1172 | int err = 0; |
1152 | __be16 protocol = skb->protocol; | 1173 | __be16 protocol; |
1153 | #ifdef CONFIG_NET_CLS_ACT | 1174 | #ifdef CONFIG_NET_CLS_ACT |
1154 | struct tcf_proto *otp = tp; | 1175 | struct tcf_proto *otp = tp; |
1155 | reclassify: | 1176 | reclassify: |
1156 | #endif | 1177 | #endif |
1157 | protocol = skb->protocol; | 1178 | protocol = skb->protocol; |
1158 | 1179 | ||
1159 | for ( ; tp; tp = tp->next) { | 1180 | err = tc_classify_compat(skb, tp, res); |
1160 | if ((tp->protocol == protocol || | ||
1161 | tp->protocol == htons(ETH_P_ALL)) && | ||
1162 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
1163 | #ifdef CONFIG_NET_CLS_ACT | 1181 | #ifdef CONFIG_NET_CLS_ACT |
1164 | if ( TC_ACT_RECLASSIFY == err) { | 1182 | if (err == TC_ACT_RECLASSIFY) { |
1165 | __u32 verd = (__u32) G_TC_VERD(skb->tc_verd); | 1183 | u32 verd = G_TC_VERD(skb->tc_verd); |
1166 | tp = otp; | 1184 | tp = otp; |
1167 | 1185 | ||
1168 | if (MAX_REC_LOOP < verd++) { | 1186 | if (verd++ >= MAX_REC_LOOP) { |
1169 | printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n", | 1187 | printk("rule prio %u protocol %02x reclassify loop, " |
1170 | tp->prio&0xffff, ntohs(tp->protocol)); | 1188 | "packet dropped\n", |
1171 | return TC_ACT_SHOT; | 1189 | tp->prio&0xffff, ntohs(tp->protocol)); |
1172 | } | 1190 | return TC_ACT_SHOT; |
1173 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd); | ||
1174 | goto reclassify; | ||
1175 | } else { | ||
1176 | if (skb->tc_verd) | ||
1177 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,0); | ||
1178 | return err; | ||
1179 | } | ||
1180 | #else | ||
1181 | |||
1182 | return err; | ||
1183 | #endif | ||
1184 | } | 1191 | } |
1185 | 1192 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | |
1193 | goto reclassify; | ||
1186 | } | 1194 | } |
1187 | return -1; | 1195 | #endif |
1196 | return err; | ||
1188 | } | 1197 | } |
1198 | EXPORT_SYMBOL(tc_classify); | ||
1189 | 1199 | ||
1190 | void tcf_destroy(struct tcf_proto *tp) | 1200 | void tcf_destroy(struct tcf_proto *tp) |
1191 | { | 1201 | { |
@@ -1252,4 +1262,3 @@ EXPORT_SYMBOL(qdisc_get_rtab); | |||
1252 | EXPORT_SYMBOL(qdisc_put_rtab); | 1262 | EXPORT_SYMBOL(qdisc_put_rtab); |
1253 | EXPORT_SYMBOL(register_qdisc); | 1263 | EXPORT_SYMBOL(register_qdisc); |
1254 | EXPORT_SYMBOL(unregister_qdisc); | 1264 | EXPORT_SYMBOL(unregister_qdisc); |
1255 | EXPORT_SYMBOL(tc_classify); | ||