|
@@ -80,10 +80,6 @@ struct cbq_class {
|
|
|
unsigned char priority; /* class priority */
|
|
|
unsigned char priority2; /* priority to be used after overlimit */
|
|
|
unsigned char ewma_log; /* time constant for idle time calculation */
|
|
|
- unsigned char ovl_strategy;
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- unsigned char police;
|
|
|
-#endif
|
|
|
|
|
|
u32 defmap;
|
|
|
|
|
@@ -94,10 +90,6 @@ struct cbq_class {
|
|
|
u32 avpkt;
|
|
|
struct qdisc_rate_table *R_tab;
|
|
|
|
|
|
- /* Overlimit strategy parameters */
|
|
|
- void (*overlimit)(struct cbq_class *cl);
|
|
|
- psched_tdiff_t penalty;
|
|
|
-
|
|
|
/* General scheduler (WRR) parameters */
|
|
|
long allot;
|
|
|
long quantum; /* Allotment per WRR round */
|
|
@@ -382,9 +374,6 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- cl->q->__parent = sch;
|
|
|
-#endif
|
|
|
ret = qdisc_enqueue(skb, cl->q);
|
|
|
if (ret == NET_XMIT_SUCCESS) {
|
|
|
sch->q.qlen++;
|
|
@@ -402,11 +391,8 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* Overlimit actions */
|
|
|
-
|
|
|
-/* TC_CBQ_OVL_CLASSIC: (default) penalize leaf class by adding offtime */
|
|
|
-
|
|
|
-static void cbq_ovl_classic(struct cbq_class *cl)
|
|
|
+/* Overlimit action: penalize leaf class by adding offtime */
|
|
|
+static void cbq_overlimit(struct cbq_class *cl)
|
|
|
{
|
|
|
struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
|
psched_tdiff_t delay = cl->undertime - q->now;
|
|
@@ -456,99 +442,6 @@ static void cbq_ovl_classic(struct cbq_class *cl)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/* TC_CBQ_OVL_RCLASSIC: penalize by offtime classes in hierarchy, when
|
|
|
- * they go overlimit
|
|
|
- */
|
|
|
-
|
|
|
-static void cbq_ovl_rclassic(struct cbq_class *cl)
|
|
|
-{
|
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
|
- struct cbq_class *this = cl;
|
|
|
-
|
|
|
- do {
|
|
|
- if (cl->level > q->toplevel) {
|
|
|
- cl = NULL;
|
|
|
- break;
|
|
|
- }
|
|
|
- } while ((cl = cl->borrow) != NULL);
|
|
|
-
|
|
|
- if (cl == NULL)
|
|
|
- cl = this;
|
|
|
- cbq_ovl_classic(cl);
|
|
|
-}
|
|
|
-
|
|
|
-/* TC_CBQ_OVL_DELAY: delay until it will go to underlimit */
|
|
|
-
|
|
|
-static void cbq_ovl_delay(struct cbq_class *cl)
|
|
|
-{
|
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
|
- psched_tdiff_t delay = cl->undertime - q->now;
|
|
|
-
|
|
|
- if (test_bit(__QDISC_STATE_DEACTIVATED,
|
|
|
- &qdisc_root_sleeping(cl->qdisc)->state))
|
|
|
- return;
|
|
|
-
|
|
|
- if (!cl->delayed) {
|
|
|
- psched_time_t sched = q->now;
|
|
|
- ktime_t expires;
|
|
|
-
|
|
|
- delay += cl->offtime;
|
|
|
- if (cl->avgidle < 0)
|
|
|
- delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log);
|
|
|
- if (cl->avgidle < cl->minidle)
|
|
|
- cl->avgidle = cl->minidle;
|
|
|
- cl->undertime = q->now + delay;
|
|
|
-
|
|
|
- if (delay > 0) {
|
|
|
- sched += delay + cl->penalty;
|
|
|
- cl->penalized = sched;
|
|
|
- cl->cpriority = TC_CBQ_MAXPRIO;
|
|
|
- q->pmask |= (1<<TC_CBQ_MAXPRIO);
|
|
|
-
|
|
|
- expires = ns_to_ktime(PSCHED_TICKS2NS(sched));
|
|
|
- if (hrtimer_try_to_cancel(&q->delay_timer) &&
|
|
|
- ktime_to_ns(ktime_sub(
|
|
|
- hrtimer_get_expires(&q->delay_timer),
|
|
|
- expires)) > 0)
|
|
|
- hrtimer_set_expires(&q->delay_timer, expires);
|
|
|
- hrtimer_restart(&q->delay_timer);
|
|
|
- cl->delayed = 1;
|
|
|
- cl->xstats.overactions++;
|
|
|
- return;
|
|
|
- }
|
|
|
- delay = 1;
|
|
|
- }
|
|
|
- if (q->wd_expires == 0 || q->wd_expires > delay)
|
|
|
- q->wd_expires = delay;
|
|
|
-}
|
|
|
-
|
|
|
-/* TC_CBQ_OVL_LOWPRIO: penalize class by lowering its priority band */
|
|
|
-
|
|
|
-static void cbq_ovl_lowprio(struct cbq_class *cl)
|
|
|
-{
|
|
|
- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
|
|
|
-
|
|
|
- cl->penalized = q->now + cl->penalty;
|
|
|
-
|
|
|
- if (cl->cpriority != cl->priority2) {
|
|
|
- cl->cpriority = cl->priority2;
|
|
|
- q->pmask |= (1<<cl->cpriority);
|
|
|
- cl->xstats.overactions++;
|
|
|
- }
|
|
|
- cbq_ovl_classic(cl);
|
|
|
-}
|
|
|
-
|
|
|
-/* TC_CBQ_OVL_DROP: penalize class by dropping */
|
|
|
-
|
|
|
-static void cbq_ovl_drop(struct cbq_class *cl)
|
|
|
-{
|
|
|
- if (cl->q->ops->drop)
|
|
|
- if (cl->q->ops->drop(cl->q))
|
|
|
- cl->qdisc->q.qlen--;
|
|
|
- cl->xstats.overactions++;
|
|
|
- cbq_ovl_classic(cl);
|
|
|
-}
|
|
|
-
|
|
|
static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio,
|
|
|
psched_time_t now)
|
|
|
{
|
|
@@ -625,40 +518,6 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
|
|
|
return HRTIMER_NORESTART;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
-static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
|
|
|
-{
|
|
|
- struct Qdisc *sch = child->__parent;
|
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
|
- struct cbq_class *cl = q->rx_class;
|
|
|
-
|
|
|
- q->rx_class = NULL;
|
|
|
-
|
|
|
- if (cl && (cl = cbq_reclassify(skb, cl)) != NULL) {
|
|
|
- int ret;
|
|
|
-
|
|
|
- cbq_mark_toplevel(q, cl);
|
|
|
-
|
|
|
- q->rx_class = cl;
|
|
|
- cl->q->__parent = sch;
|
|
|
-
|
|
|
- ret = qdisc_enqueue(skb, cl->q);
|
|
|
- if (ret == NET_XMIT_SUCCESS) {
|
|
|
- sch->q.qlen++;
|
|
|
- if (!cl->next_alive)
|
|
|
- cbq_activate_class(cl);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (net_xmit_drop_count(ret))
|
|
|
- qdisc_qstats_drop(sch);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- qdisc_qstats_drop(sch);
|
|
|
- return -1;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* It is mission critical procedure.
|
|
|
*
|
|
@@ -807,7 +666,7 @@ cbq_under_limit(struct cbq_class *cl)
|
|
|
cl = cl->borrow;
|
|
|
if (!cl) {
|
|
|
this_cl->qstats.overlimits++;
|
|
|
- this_cl->overlimit(this_cl);
|
|
|
+ cbq_overlimit(this_cl);
|
|
|
return NULL;
|
|
|
}
|
|
|
if (cl->level > q->toplevel)
|
|
@@ -1166,31 +1025,6 @@ static void cbq_link_class(struct cbq_class *this)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static unsigned int cbq_drop(struct Qdisc *sch)
|
|
|
-{
|
|
|
- struct cbq_sched_data *q = qdisc_priv(sch);
|
|
|
- struct cbq_class *cl, *cl_head;
|
|
|
- int prio;
|
|
|
- unsigned int len;
|
|
|
-
|
|
|
- for (prio = TC_CBQ_MAXPRIO; prio >= 0; prio--) {
|
|
|
- cl_head = q->active[prio];
|
|
|
- if (!cl_head)
|
|
|
- continue;
|
|
|
-
|
|
|
- cl = cl_head;
|
|
|
- do {
|
|
|
- if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) {
|
|
|
- sch->q.qlen--;
|
|
|
- if (!cl->q->q.qlen)
|
|
|
- cbq_deactivate_class(cl);
|
|
|
- return len;
|
|
|
- }
|
|
|
- } while ((cl = cl->next_alive) != cl_head);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void
|
|
|
cbq_reset(struct Qdisc *sch)
|
|
|
{
|
|
@@ -1280,50 +1114,6 @@ static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl)
|
|
|
-{
|
|
|
- switch (ovl->strategy) {
|
|
|
- case TC_CBQ_OVL_CLASSIC:
|
|
|
- cl->overlimit = cbq_ovl_classic;
|
|
|
- break;
|
|
|
- case TC_CBQ_OVL_DELAY:
|
|
|
- cl->overlimit = cbq_ovl_delay;
|
|
|
- break;
|
|
|
- case TC_CBQ_OVL_LOWPRIO:
|
|
|
- if (ovl->priority2 - 1 >= TC_CBQ_MAXPRIO ||
|
|
|
- ovl->priority2 - 1 <= cl->priority)
|
|
|
- return -EINVAL;
|
|
|
- cl->priority2 = ovl->priority2 - 1;
|
|
|
- cl->overlimit = cbq_ovl_lowprio;
|
|
|
- break;
|
|
|
- case TC_CBQ_OVL_DROP:
|
|
|
- cl->overlimit = cbq_ovl_drop;
|
|
|
- break;
|
|
|
- case TC_CBQ_OVL_RCLASSIC:
|
|
|
- cl->overlimit = cbq_ovl_rclassic;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- cl->penalty = ovl->penalty;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
-static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p)
|
|
|
-{
|
|
|
- cl->police = p->police;
|
|
|
-
|
|
|
- if (cl->q->handle) {
|
|
|
- if (p->police == TC_POLICE_RECLASSIFY)
|
|
|
- cl->q->reshape_fail = cbq_reshape_fail;
|
|
|
- else
|
|
|
- cl->q->reshape_fail = NULL;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
|
|
|
{
|
|
|
cbq_change_defmap(cl, fopt->split, fopt->defmap, fopt->defchange);
|
|
@@ -1375,8 +1165,6 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
|
|
|
q->link.priority = TC_CBQ_MAXPRIO - 1;
|
|
|
q->link.priority2 = TC_CBQ_MAXPRIO - 1;
|
|
|
q->link.cpriority = TC_CBQ_MAXPRIO - 1;
|
|
|
- q->link.ovl_strategy = TC_CBQ_OVL_CLASSIC;
|
|
|
- q->link.overlimit = cbq_ovl_classic;
|
|
|
q->link.allot = psched_mtu(qdisc_dev(sch));
|
|
|
q->link.quantum = q->link.allot;
|
|
|
q->link.weight = q->link.R_tab->rate.rate;
|
|
@@ -1463,24 +1251,6 @@ nla_put_failure:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-static int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
|
|
|
-{
|
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
|
- struct tc_cbq_ovl opt;
|
|
|
-
|
|
|
- opt.strategy = cl->ovl_strategy;
|
|
|
- opt.priority2 = cl->priority2 + 1;
|
|
|
- opt.pad = 0;
|
|
|
- opt.penalty = cl->penalty;
|
|
|
- if (nla_put(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt))
|
|
|
- goto nla_put_failure;
|
|
|
- return skb->len;
|
|
|
-
|
|
|
-nla_put_failure:
|
|
|
- nlmsg_trim(skb, b);
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
|
|
|
{
|
|
|
unsigned char *b = skb_tail_pointer(skb);
|
|
@@ -1500,36 +1270,11 @@ nla_put_failure:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
-static int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
|
|
|
-{
|
|
|
- unsigned char *b = skb_tail_pointer(skb);
|
|
|
- struct tc_cbq_police opt;
|
|
|
-
|
|
|
- if (cl->police) {
|
|
|
- opt.police = cl->police;
|
|
|
- opt.__res1 = 0;
|
|
|
- opt.__res2 = 0;
|
|
|
- if (nla_put(skb, TCA_CBQ_POLICE, sizeof(opt), &opt))
|
|
|
- goto nla_put_failure;
|
|
|
- }
|
|
|
- return skb->len;
|
|
|
-
|
|
|
-nla_put_failure:
|
|
|
- nlmsg_trim(skb, b);
|
|
|
- return -1;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
|
|
|
{
|
|
|
if (cbq_dump_lss(skb, cl) < 0 ||
|
|
|
cbq_dump_rate(skb, cl) < 0 ||
|
|
|
cbq_dump_wrr(skb, cl) < 0 ||
|
|
|
- cbq_dump_ovl(skb, cl) < 0 ||
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- cbq_dump_police(skb, cl) < 0 ||
|
|
|
-#endif
|
|
|
cbq_dump_fopt(skb, cl) < 0)
|
|
|
return -1;
|
|
|
return 0;
|
|
@@ -1619,11 +1364,6 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
|
|
|
&pfifo_qdisc_ops, cl->common.classid);
|
|
|
if (new == NULL)
|
|
|
return -ENOBUFS;
|
|
|
- } else {
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- if (cl->police == TC_POLICE_RECLASSIFY)
|
|
|
- new->reshape_fail = cbq_reshape_fail;
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
*old = qdisc_replace(sch, new, &cl->q);
|
|
@@ -1736,6 +1476,9 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
|
|
|
+ if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE])
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
if (cl) {
|
|
|
/* Check parent */
|
|
|
if (parentid) {
|
|
@@ -1784,14 +1527,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
|
|
cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
|
|
|
}
|
|
|
|
|
|
- if (tb[TCA_CBQ_OVL_STRATEGY])
|
|
|
- cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
|
|
|
-
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- if (tb[TCA_CBQ_POLICE])
|
|
|
- cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
|
|
|
-#endif
|
|
|
-
|
|
|
if (tb[TCA_CBQ_FOPT])
|
|
|
cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
|
|
|
|
|
@@ -1887,13 +1622,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
|
|
cl->maxidle = q->link.maxidle;
|
|
|
if (cl->avpkt == 0)
|
|
|
cl->avpkt = q->link.avpkt;
|
|
|
- cl->overlimit = cbq_ovl_classic;
|
|
|
- if (tb[TCA_CBQ_OVL_STRATEGY])
|
|
|
- cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- if (tb[TCA_CBQ_POLICE])
|
|
|
- cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
|
|
|
-#endif
|
|
|
if (tb[TCA_CBQ_FOPT])
|
|
|
cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
|
|
|
sch_tree_unlock(sch);
|
|
@@ -2038,7 +1766,6 @@ static struct Qdisc_ops cbq_qdisc_ops __read_mostly = {
|
|
|
.enqueue = cbq_enqueue,
|
|
|
.dequeue = cbq_dequeue,
|
|
|
.peek = qdisc_peek_dequeued,
|
|
|
- .drop = cbq_drop,
|
|
|
.init = cbq_init,
|
|
|
.reset = cbq_reset,
|
|
|
.destroy = cbq_destroy,
|