long deficit; /* Saved deficit for WRR */
unsigned long penalized;
struct tc_stats stats;
+ spinlock_t *stats_lock;
struct tc_cbq_xstats xstats;
struct tcf_proto *filter_list;
*/
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;
for (;;) {
int result = 0;
-
+#ifdef CONFIG_NET_CLS_ACT
+ int terminal = 0;
+#endif
defmap = head->defaults;
/*
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:
default:
break;
}
+#endif
#endif
if (cl->level == 0)
return cl;
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;
#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);
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;
}
q->link.ewma_log = TC_CBQ_DEF_EWMA;
q->link.avpkt = q->link.allot/2;
q->link.minidle = -0x7FFFFFFF;
- q->link.stats.lock = &sch->dev->queue_lock;
+ q->link.stats_lock = &sch->dev->queue_lock;
init_timer(&q->wd_timer);
q->wd_timer.data = (unsigned long)sch;
goto rtattr_failure;
rta->rta_len = skb->tail - b;
cl->stats.qlen = cl->q->q.qlen;
- if (qdisc_copy_stats(skb, &cl->stats))
+ if (qdisc_copy_stats(skb, &cl->stats, cl->stats_lock))
goto rtattr_failure;
spin_lock_bh(&sch->dev->queue_lock);
cl->xstats.avgidle = cl->avgidle;
#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1]) {
qdisc_kill_estimator(&cl->stats);
- qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+ qdisc_new_estimator(&cl->stats, cl->stats_lock,
+ tca[TCA_RATE-1]);
}
#endif
return 0;
cl->allot = parent->allot;
cl->quantum = cl->allot;
cl->weight = cl->R_tab->rate.rate;
- cl->stats.lock = &sch->dev->queue_lock;
+ cl->stats_lock = &sch->dev->queue_lock;
sch_tree_lock(sch);
cbq_link_class(cl);
#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
- qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+ qdisc_new_estimator(&cl->stats, cl->stats_lock,
+ tca[TCA_RATE-1]);
#endif
*arg = (unsigned long)cl;