Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.25-rc7 /net/sched/sch_htb.c

Filename:/net/sched/sch_htb.c
Lines Added:84
Lines Deleted:54
Also changed in: (Previous) 2.6.25-rc6-git8  2.6.25-rc6  2.6.25-rc5  2.6.25-rc4  2.6.25-rc3  2.6.25-rc2 
(Following) 2.6.25-rc8  2.6.25-rc9  2.6.25  2.6.25.4-rc1  2.6.25.4  2.6.25.5 

Location
[  2.6.25-rc7
  [  net
    [  sched
       o  sch_htb.c

Patch

diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 5e608a6..66148cc 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -214,10 +214,6 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
  * then finish and return direct queue.
  */
 #define HTB_DIRECT (struct htb_class*)-1
-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,
                   int *qerr)
@@ -613,14 +609,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 /* TODO: requeuing packet charges it to policers again !! */
 static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
+   int ret;
    struct htb_sched *q = qdisc_priv(sch);
-   int ret = NET_XMIT_SUCCESS;
    struct htb_class *cl = htb_classify(skb, sch, &ret);
    struct sk_buff *tskb;
 
-   if (cl == HTB_DIRECT || !cl) {
+   if (cl == HTB_DIRECT) {
       /* enqueue to helper queue */
-      if (q->direct_queue.qlen < q->direct_qlen && cl) {
+      if (q->direct_queue.qlen < q->direct_qlen) {
          __skb_queue_head(&q->direct_queue, skb);
       } else {
          __skb_queue_head(&q->direct_queue, skb);
@@ -629,6 +625,13 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
          sch->qstats.drops++;
          return NET_XMIT_CN;
       }
+#ifdef CONFIG_NET_CLS_ACT
+   } else if (!cl) {
+      if (ret == NET_XMIT_BYPASS)
+         sch->qstats.drops++;
+      kfree_skb(skb);
+      return ret;
+#endif
    } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) !=
          NET_XMIT_SUCCESS) {
       sch->qstats.drops++;
@@ -708,9 +711,11 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
  */
 static psched_time_t htb_do_events(struct htb_sched *q, int level)
 {
-   int i;
-
-   for (i = 0; i < 500; i++) {
+   /* don't run for longer than 2 jiffies; 2 is used instead of
+      1 to simplify things when jiffy is going to be incremented
+      too soon */
+   unsigned long stop_at = jiffies + 2;
+   while (time_before(jiffies, stop_at)) {
       struct htb_class *cl;
       long diff;
       struct rb_node *p = rb_first(&q->wait_pq[level]);
@@ -728,9 +733,8 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level)
       if (cl->cmode != HTB_CAN_SEND)
          htb_add_to_wait_tree(q, cl, diff);
    }
-   if (net_ratelimit())
-      printk(KERN_WARNING "htb: too many events !\n");
-   return q->now + PSCHED_TICKS_PER_SEC / 10;
+   /* too much load - let's continue on next jiffie */
+   return q->now + PSCHED_TICKS_PER_SEC / HZ;
 }
 
 /* Returns class->node+prio from id-tree where classe's id is >= id. NULL
@@ -996,19 +1000,33 @@ static void htb_reset(struct Qdisc *sch)
       INIT_LIST_HEAD(q->drops + i);
 }
 
-static int htb_init(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
+   [TCA_HTB_PARMS]   = { .len = sizeof(struct tc_htb_opt) },
+   [TCA_HTB_INIT]   = { .len = sizeof(struct tc_htb_glob) },
+   [TCA_HTB_CTAB]   = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+   [TCA_HTB_RTAB]   = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
+static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 {
    struct htb_sched *q = qdisc_priv(sch);
-   struct rtattr *tb[TCA_HTB_INIT];
+   struct nlattr *tb[TCA_HTB_INIT + 1];
    struct tc_htb_glob *gopt;
+   int err;
    int i;
-   if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) ||
-       tb[TCA_HTB_INIT - 1] == NULL ||
-       RTA_PAYLOAD(tb[TCA_HTB_INIT - 1]) < sizeof(*gopt)) {
+
+   if (!opt)
+      return -EINVAL;
+
+   err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
+   if (err < 0)
+      return err;
+
+   if (tb[TCA_HTB_INIT] == NULL) {
       printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
       return -EINVAL;
    }
-   gopt = RTA_DATA(tb[TCA_HTB_INIT - 1]);
+   gopt = nla_data(tb[TCA_HTB_INIT]);
    if (gopt->version != HTB_VER >> 16) {
       printk(KERN_ERR
              "HTB: need tc/htb version %d (minor is %d), you have %d\n",
@@ -1039,25 +1057,29 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
 static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
    struct htb_sched *q = qdisc_priv(sch);
-   unsigned char *b = skb_tail_pointer(skb);
-   struct rtattr *rta;
+   struct nlattr *nest;
    struct tc_htb_glob gopt;
+
    spin_lock_bh(&sch->dev->queue_lock);
-   gopt.direct_pkts = q->direct_pkts;
 
+   gopt.direct_pkts = q->direct_pkts;
    gopt.version = HTB_VER;
    gopt.rate2quantum = q->rate2quantum;
    gopt.defcls = q->defcls;
    gopt.debug = 0;
-   rta = (struct rtattr *)b;
-   RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
-   RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
-   rta->rta_len = skb_tail_pointer(skb) - b;
+
+   nest = nla_nest_start(skb, TCA_OPTIONS);
+   if (nest == NULL)
+      goto nla_put_failure;
+   NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
+   nla_nest_end(skb, nest);
+
    spin_unlock_bh(&sch->dev->queue_lock);
    return skb->len;
-rtattr_failure:
+
+nla_put_failure:
    spin_unlock_bh(&sch->dev->queue_lock);
-   nlmsg_trim(skb, skb_tail_pointer(skb));
+   nla_nest_cancel(skb, nest);
    return -1;
 }
 
@@ -1065,8 +1087,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
            struct sk_buff *skb, struct tcmsg *tcm)
 {
    struct htb_class *cl = (struct htb_class *)arg;
-   unsigned char *b = skb_tail_pointer(skb);
-   struct rtattr *rta;
+   struct nlattr *nest;
    struct tc_htb_opt opt;
 
    spin_lock_bh(&sch->dev->queue_lock);
@@ -1075,8 +1096,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
    if (!cl->level && cl->un.leaf.q)
       tcm->tcm_info = cl->un.leaf.q->handle;
 
-   rta = (struct rtattr *)b;
-   RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+   nest = nla_nest_start(skb, TCA_OPTIONS);
+   if (nest == NULL)
+      goto nla_put_failure;
 
    memset(&opt, 0, sizeof(opt));
 
@@ -1087,13 +1109,15 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
    opt.quantum = cl->un.leaf.quantum;
    opt.prio = cl->un.leaf.prio;
    opt.level = cl->level;
-   RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
-   rta->rta_len = skb_tail_pointer(skb) - b;
+   NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
+
+   nla_nest_end(skb, nest);
    spin_unlock_bh(&sch->dev->queue_lock);
    return skb->len;
-rtattr_failure:
+
+nla_put_failure:
    spin_unlock_bh(&sch->dev->queue_lock);
-   nlmsg_trim(skb, b);
+   nla_nest_cancel(skb, nest);
    return -1;
 }
 
@@ -1294,29 +1318,35 @@ static void htb_put(struct Qdisc *sch, unsigned long arg)
 }
 
 static int htb_change_class(struct Qdisc *sch, u32 classid,
-             u32 parentid, struct rtattr **tca,
+             u32 parentid, struct nlattr **tca,
              unsigned long *arg)
 {
    int err = -EINVAL;
    struct htb_sched *q = qdisc_priv(sch);
    struct htb_class *cl = (struct htb_class *)*arg, *parent;
-   struct rtattr *opt = tca[TCA_OPTIONS - 1];
+   struct nlattr *opt = tca[TCA_OPTIONS];
    struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
-   struct rtattr *tb[TCA_HTB_RTAB];
+   struct nlattr *tb[TCA_HTB_RTAB + 1];
    struct tc_htb_opt *hopt;
 
    /* extract all subattrs from opt attr */
-   if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
-       tb[TCA_HTB_PARMS - 1] == NULL ||
-       RTA_PAYLOAD(tb[TCA_HTB_PARMS - 1]) < sizeof(*hopt))
+   if (!opt)
+      goto failure;
+
+   err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
+   if (err < 0)
+      goto failure;
+
+   err = -EINVAL;
+   if (tb[TCA_HTB_PARMS] == NULL)
       goto failure;
 
    parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
 
-   hopt = RTA_DATA(tb[TCA_HTB_PARMS - 1]);
+   hopt = nla_data(tb[TCA_HTB_PARMS]);
 
-   rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB - 1]);
-   ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB - 1]);
+   rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
+   ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
    if (!rtab || !ctab)
       goto failure;
 
@@ -1324,12 +1354,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
       struct Qdisc *new_q;
       int prio;
       struct {
-         struct rtattr      rta;
+         struct nlattr      nla;
          struct gnet_estimator   opt;
       } est = {
-         .rta = {
-            .rta_len   = RTA_LENGTH(sizeof(est.opt)),
-            .rta_type   = TCA_RATE,
+         .nla = {
+            .nla_len   = nla_attr_size(sizeof(est.opt)),
+            .nla_type   = TCA_RATE,
          },
          .opt = {
             /* 4s interval, 16s averaging constant */
@@ -1354,7 +1384,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 
       gen_new_estimator(&cl->bstats, &cl->rate_est,
               &sch->dev->queue_lock,
-              tca[TCA_RATE-1] ? : &est.rta);
+              tca[TCA_RATE] ? : &est.nla);
       cl->refcnt = 1;
       INIT_LIST_HEAD(&cl->sibling);
       INIT_HLIST_NODE(&cl->hlist);
@@ -1407,10 +1437,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
       list_add_tail(&cl->sibling,
                parent ? &parent->children : &q->root);
    } else {
-      if (tca[TCA_RATE-1])
+      if (tca[TCA_RATE])
          gen_replace_estimator(&cl->bstats, &cl->rate_est,
                      &sch->dev->queue_lock,
-                     tca[TCA_RATE-1]);
+                     tca[TCA_RATE]);
       sch_tree_lock(sch);
    }
 
@@ -1529,7 +1559,7 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
    }
 }
 
-static struct Qdisc_class_ops htb_class_ops = {
+static const struct Qdisc_class_ops htb_class_ops = {
    .graft      =   htb_graft,
    .leaf      =   htb_leaf,
    .qlen_notify   =   htb_qlen_notify,
@@ -1545,7 +1575,7 @@ static struct Qdisc_class_ops htb_class_ops = {
    .dump_stats   =   htb_dump_class_stats,
 };
 
-static struct Qdisc_ops htb_qdisc_ops = {
+static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
    .next      =   NULL,
    .cl_ops      =   &htb_class_ops,
    .id      =   "htb",


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.