net: ipv6: Do not consider link state for nexthop validation
[cascardo/linux.git] / net / sched / sch_cbq.c
index baafddf..beb554a 100644 (file)
@@ -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 */
@@ -353,7 +345,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
 {
        int toplevel = q->toplevel;
 
-       if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) {
+       if (toplevel > cl->level) {
                psched_time_t now = psched_get_time();
 
                do {
@@ -366,7 +358,8 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
 }
 
 static int
-cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+           struct sk_buff **to_free)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
        int uninitialized_var(ret);
@@ -378,14 +371,11 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (cl == NULL) {
                if (ret & __NET_XMIT_BYPASS)
                        qdisc_qstats_drop(sch);
-               kfree_skb(skb);
+               __qdisc_drop(skb, to_free);
                return ret;
        }
 
-#ifdef CONFIG_NET_CLS_ACT
-       cl->q->__parent = sch;
-#endif
-       ret = qdisc_enqueue(skb, cl->q);
+       ret = qdisc_enqueue(skb, cl->q, to_free);
        if (ret == NET_XMIT_SUCCESS) {
                sch->q.qlen++;
                cbq_mark_toplevel(q, cl);
@@ -402,11 +392,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 +443,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)
 {
@@ -620,45 +514,10 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
                hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS_PINNED);
        }
 
-       qdisc_unthrottled(sch);
        __netif_schedule(qdisc_root(sch));
        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)
@@ -960,7 +819,6 @@ cbq_dequeue(struct Qdisc *sch)
                if (skb) {
                        qdisc_bstats_update(sch, skb);
                        sch->q.qlen--;
-                       qdisc_unthrottled(sch);
                        return skb;
                }
 
@@ -1166,31 +1024,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 +1113,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 +1164,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 +1250,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 +1269,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;
@@ -1600,7 +1344,8 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
        if (cl->undertime != PSCHED_PASTPERFECT)
                cl->xstats.undertime = cl->undertime - q->now;
 
-       if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
+       if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
+                                 d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
            gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->q->q.qlen) < 0)
                return -1;
@@ -1618,11 +1363,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);
@@ -1735,6 +1475,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) {
@@ -1755,7 +1498,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
                if (tca[TCA_RATE]) {
                        err = gen_replace_estimator(&cl->bstats, NULL,
                                                    &cl->rate_est,
-                                                   qdisc_root_sleeping_lock(sch),
+                                                   NULL,
+                                                   qdisc_root_sleeping_running(sch),
                                                    tca[TCA_RATE]);
                        if (err) {
                                qdisc_put_rtab(rtab);
@@ -1782,14 +1526,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]));
 
@@ -1848,7 +1584,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 
        if (tca[TCA_RATE]) {
                err = gen_new_estimator(&cl->bstats, NULL, &cl->rate_est,
-                                       qdisc_root_sleeping_lock(sch),
+                                       NULL,
+                                       qdisc_root_sleeping_running(sch),
                                        tca[TCA_RATE]);
                if (err) {
                        kfree(cl);
@@ -1884,13 +1621,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);
@@ -2035,7 +1765,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,