aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@znyx.com>2004-07-05 01:25:34 -0700
committerDavid S. Miller <davem@kernel.bkbits.net>2004-07-05 01:25:34 -0700
commitd2b21b587ae7dffe607851fe9a58186c4242b375 (patch)
tree5809f4bdd673402c4af32e795cf663d36bd75d36 /net
parent07f0a148b27e12aa11086153ca9425d311e20522 (diff)
downloadhistory-d2b21b587ae7dffe607851fe9a58186c4242b375.tar.gz
[PKT_SCHED]: Pass NET_XMIT_* status properly back through classifiers.
Diffstat (limited to 'net')
-rw-r--r--net/sched/sch_cbq.c48
-rw-r--r--net/sched/sch_hfsc.c42
-rw-r--r--net/sched/sch_htb.c53
-rw-r--r--net/sched/sch_prio.c39
4 files changed, 151 insertions, 31 deletions
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 16089ce5924452..66b6ba1aa33910 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -238,7 +238,7 @@ cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
*/
static struct cbq_class *
-cbq_classify(struct sk_buff *skb, struct Qdisc *sch)
+cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
{
struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data;
struct cbq_class *head = &q->link;
@@ -256,7 +256,9 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch)
for (;;) {
int result = 0;
-
+#ifdef CONFIG_NET_CLS_ACT
+ int terminal = 0;
+#endif
defmap = head->defaults;
/*
@@ -275,6 +277,28 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch)
goto fallback;
}
+#ifdef CONFIG_NET_CLS_ACT
+ switch (result) {
+ case TC_ACT_SHOT: /* Stop and kfree */
+ *qres = NET_XMIT_DROP;
+ terminal = 1;
+ break;
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ terminal = 1;
+ break;
+ case TC_ACT_RECLASSIFY: /* Things look good */
+ case TC_ACT_OK:
+ case TC_ACT_UNSPEC:
+ default:
+ break;
+ }
+
+ if (terminal) {
+ kfree_skb(skb);
+ return NULL;
+ }
+#else
#ifdef CONFIG_NET_CLS_POLICE
switch (result) {
case TC_POLICE_RECLASSIFY:
@@ -285,6 +309,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch)
break;
}
#endif
+#endif
if (cl->level == 0)
return cl;
@@ -394,9 +419,9 @@ static int
cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
- struct cbq_class *cl = cbq_classify(skb, sch);
int len = skb->len;
- int ret = NET_XMIT_POLICED;
+ int ret = NET_XMIT_SUCCESS;
+ struct cbq_class *cl = cbq_classify(skb, sch,&ret);
#ifdef CONFIG_NET_CLS_POLICE
q->rx_class = cl;
@@ -405,17 +430,18 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
#ifdef CONFIG_NET_CLS_POLICE
cl->q->__parent = sch;
#endif
- if ((ret = cl->q->enqueue(skb, cl->q)) == 0) {
+ if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
sch->q.qlen++;
sch->stats.packets++;
sch->stats.bytes+=len;
cbq_mark_toplevel(q, cl);
if (!cl->next_alive)
cbq_activate_class(cl);
- return 0;
+ return ret;
}
}
+#ifndef CONFIG_NET_CLS_ACT
sch->stats.drops++;
if (cl == NULL)
kfree_skb(skb);
@@ -423,6 +449,16 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
cbq_mark_toplevel(q, cl);
cl->stats.drops++;
}
+#else
+ if ( NET_XMIT_DROP == ret) {
+ sch->stats.drops++;
+ }
+
+ if (cl != NULL) {
+ cbq_mark_toplevel(q, cl);
+ cl->stats.drops++;
+ }
+#endif
return ret;
}
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index ec0ae43bf67242..35fd5eb6d07c3c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1235,7 +1235,7 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
}
static struct hfsc_class *
-hfsc_classify(struct sk_buff *skb, struct Qdisc *sch)
+hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
{
struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
struct hfsc_class *cl;
@@ -1250,10 +1250,34 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch)
tcf = q->root.filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+ int terminal = 0;
+ switch (result) {
+ case TC_ACT_SHOT:
+ *qres = NET_XMIT_DROP;
+ terminal = 1;
+ break;
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ terminal = 1;
+ break;
+ case TC_ACT_RECLASSIFY:
+ case TC_ACT_OK:
+ case TC_ACT_UNSPEC:
+ default:
+ break;
+ }
+
+ if (terminal) {
+ kfree_skb(skb);
+ return NULL;
+ }
+#else
#ifdef CONFIG_NET_CLS_POLICE
if (result == TC_POLICE_SHOT)
return NULL;
#endif
+#endif
if ((cl = (struct hfsc_class *)res.class) == NULL) {
if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
break; /* filter selected invalid classid */
@@ -1660,15 +1684,26 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
static int
hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- struct hfsc_class *cl = hfsc_classify(skb, sch);
+ int ret = NET_XMIT_SUCCESS;
+ struct hfsc_class *cl = hfsc_classify(skb, sch, &ret);
unsigned int len = skb->len;
int err;
+
+#ifdef CONFIG_NET_CLS_ACT
+ if (cl == NULL) {
+ if (NET_XMIT_DROP == ret) {
+ sch->stats.drops++;
+ }
+ return ret;
+ }
+#else
if (cl == NULL) {
kfree_skb(skb);
sch->stats.drops++;
return NET_XMIT_DROP;
}
+#endif
err = cl->qdisc->enqueue(skb, cl->qdisc);
if (unlikely(err != NET_XMIT_SUCCESS)) {
@@ -1763,6 +1798,9 @@ hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+#ifdef CONFIG_NET_CLS_ACT
+ sch->stats.reqs++;
+#endif
__skb_queue_head(&q->requeue, skb);
sch->q.qlen++;
return NET_XMIT_SUCCESS;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 971320956f365d..03818f1c3b7be1 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -297,7 +297,7 @@ static inline u32 htb_classid(struct htb_class *cl)
return (cl && cl != HTB_DIRECT) ? cl->classid : TC_H_UNSPEC;
}
-static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch)
+static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
{
struct htb_sched *q = (struct htb_sched *)sch->data;
struct htb_class *cl;
@@ -315,10 +315,34 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch)
tcf = q->filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+ int terminal = 0;
+ switch (result) {
+ case TC_ACT_SHOT: /* Stop and kfree */
+ *qres = NET_XMIT_DROP;
+ terminal = 1;
+ break;
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ terminal = 1;
+ break;
+ case TC_ACT_RECLASSIFY: /* Things look good */
+ case TC_ACT_OK:
+ case TC_ACT_UNSPEC:
+ default:
+ break;
+ }
+
+ if (terminal) {
+ kfree_skb(skb);
+ return NULL;
+ }
+#else
#ifdef CONFIG_NET_CLS_POLICE
if (result == TC_POLICE_SHOT)
return NULL;
#endif
+#endif
if ((cl = (void*)res.class) == NULL) {
if (res.classid == sch->handle)
return HTB_DIRECT; /* X:0 (direct flow) */
@@ -686,9 +710,24 @@ htb_deactivate(struct htb_sched *q,struct htb_class *cl)
static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
+ int ret = NET_XMIT_SUCCESS;
struct htb_sched *q = (struct htb_sched *)sch->data;
- struct htb_class *cl = htb_classify(skb,sch);
+ struct htb_class *cl = htb_classify(skb,sch,&ret);
+
+#ifdef CONFIG_NET_CLS_ACT
+ if (cl == HTB_DIRECT ) {
+ if (q->direct_queue.qlen < q->direct_qlen ) {
+ __skb_queue_tail(&q->direct_queue, skb);
+ q->direct_pkts++;
+ }
+ } else if (!cl) {
+ if (NET_XMIT_DROP == ret) {
+ sch->stats.drops++;
+ }
+ return ret;
+ }
+#else
if (cl == HTB_DIRECT || !cl) {
/* enqueue to helper queue */
if (q->direct_queue.qlen < q->direct_qlen && cl) {
@@ -699,7 +738,9 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
sch->stats.drops++;
return NET_XMIT_DROP;
}
- } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
+ }
+#endif
+ else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
sch->stats.drops++;
cl->stats.drops++;
return NET_XMIT_DROP;
@@ -718,9 +759,13 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct htb_sched *q = (struct htb_sched *)sch->data;
- struct htb_class *cl = htb_classify(skb,sch);
+ int ret = NET_XMIT_SUCCESS;
+ struct htb_class *cl = htb_classify(skb,sch, &ret);
struct sk_buff *tskb;
+#ifdef CONFIG_NET_CLS_ACT
+ sch->stats.reqs++;
+#endif
if (cl == HTB_DIRECT || !cl) {
/* enqueue to helper queue */
if (q->direct_queue.qlen < q->direct_qlen && cl) {
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index fa6741d96a2790..ee312bd2229001 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -50,28 +50,33 @@ struct prio_sched_data
struct Qdisc *prio_classify(struct sk_buff *skb, struct Qdisc *sch,int *r)
{
struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
+ u32 band = skb->priority;
struct tcf_result res;
- u32 band;
- int result = 0;
-
- band = skb->priority;
if (TC_H_MAJ(skb->priority) != sch->handle) {
#ifdef CONFIG_NET_CLS_ACT
- *r = result = tc_classify(skb, q->filter_list, &res);
+ int result = 0, terminal = 0;
+ result = tc_classify(skb, q->filter_list, &res);
switch (result) {
case TC_ACT_SHOT:
+ *r = NET_XMIT_DROP;
+ terminal = 1;
+ break;
case TC_ACT_STOLEN:
case TC_ACT_QUEUED:
- kfree_skb(skb);
- return NULL;
+ terminal = 1;
+ break;
case TC_ACT_RECLASSIFY:
case TC_ACT_OK:
case TC_ACT_UNSPEC:
default:
break;
};
+ if (terminal) {
+ kfree_skb(skb);
+ return NULL;
+ }
if (!q->filter_list ) {
#else
@@ -94,35 +99,31 @@ static int
prio_enqueue(struct sk_buff *skb, struct Qdisc* sch)
{
struct Qdisc *qdisc;
- int ret;
-
- /* moving these up here changes things from before
- * packets counted now include everything that was ever
- * seen
- */
- sch->stats.bytes += skb->len;
- sch->stats.packets++;
+ int ret = NET_XMIT_SUCCESS;
+
qdisc = prio_classify(skb, sch, &ret);
+
if (NULL == qdisc)
goto dropped;
- if ((ret = qdisc->enqueue(skb, qdisc)) == 0) {
+ if ((ret = qdisc->enqueue(skb, qdisc)) == NET_XMIT_SUCCESS) {
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
sch->q.qlen++;
return NET_XMIT_SUCCESS;
}
dropped:
#ifdef CONFIG_NET_CLS_ACT
- if (TC_ACT_SHOT == ret || NET_XMIT_DROP == ret) {
+ if (NET_XMIT_DROP == ret) {
#endif
sch->stats.drops++;
- return NET_XMIT_DROP;
#ifdef CONFIG_NET_CLS_ACT
} else {
sch->stats.overlimits++; /* abuse, but noone uses it */
- return NET_XMIT_BYPASS; /* we dont want to confuse TCP */
}
#endif
+ return ret;
}