fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / sched / sch_atm.c
index ff61f8e..edc7bb0 100644 (file)
@@ -3,7 +3,6 @@
 /* Written 1998-2000 by Werner Almesberger, EPFL ICA */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
@@ -69,7 +68,8 @@ struct atm_flow_data {
        struct socket           *sock;          /* for closing */
        u32                     classid;        /* x:y type ID */
        int                     ref;            /* reference count */
-       struct tc_stats         stats;
+       struct gnet_stats_basic bstats;
+       struct gnet_stats_queue qstats;
        spinlock_t              *stats_lock;
        struct atm_flow_data    *next;
        struct atm_flow_data    *excess;        /* flow for excess traffic;
@@ -254,8 +254,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
         * later.)
         */
        if (flow) return -EBUSY;
-       if (opt == NULL || rtattr_parse(tb,TCA_ATM_MAX,RTA_DATA(opt),
-           RTA_PAYLOAD(opt))) return -EINVAL;
+       if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
+               return -EINVAL;
        if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd))
                return -EINVAL;
        fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]);
@@ -316,7 +316,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
        }
        memset(flow,0,sizeof(*flow));
        flow->filter_list = NULL;
-       if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
+       if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid)))
                flow->q = &noop_qdisc;
        DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
        flow->sock = sock;
@@ -449,14 +449,14 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch)
            result == TC_POLICE_SHOT ||
 #endif
            (ret = flow->q->enqueue(skb,flow->q)) != 0) {
-               sch->stats.drops++;
-               if (flow) flow->stats.drops++;
+               sch->qstats.drops++;
+               if (flow) flow->qstats.drops++;
                return ret;
        }
-       sch->stats.bytes += skb->len;
-       sch->stats.packets++;
-       flow->stats.bytes += skb->len;
-       flow->stats.packets++;
+       sch->bstats.bytes += skb->len;
+       sch->bstats.packets++;
+       flow->bstats.bytes += skb->len;
+       flow->bstats.packets++;
        /*
         * Okay, this may seem weird. We pretend we've dropped the packet if
         * it goes via ATM. The reason for this is that the outer qdisc
@@ -518,7 +518,7 @@ static void sch_atm_dequeue(unsigned long data)
                        memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
                            flow->hdr_len);
                        atomic_add(skb->truesize,
-                                  &flow->vcc->sk->sk_wmem_alloc);
+                                  &sk_atm(flow->vcc)->sk_wmem_alloc);
                        /* atm.atm_options are already set by atm_tc_enqueue */
                        (void) flow->vcc->send(flow->vcc,skb);
                }
@@ -545,10 +545,12 @@ static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch)
 
        D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
        ret = p->link.q->ops->requeue(skb,p->link.q);
-       if (!ret) sch->q.qlen++;
-       else {
-               sch->stats.drops++;
-               p->link.stats.drops++;
+       if (!ret) {
+        sch->q.qlen++;
+        sch->qstats.requeues++;
+    } else {
+               sch->qstats.drops++;
+               p->link.qstats.drops++;
        }
        return ret;
 }
@@ -574,7 +576,8 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
 
        DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
        p->flows = &p->link;
-       if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
+       if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,
+                                          sch->handle)))
                p->link.q = &noop_qdisc;
        DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);
        p->link.filter_list = NULL;
@@ -635,6 +638,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
            sch,p,flow,skb,tcm);
        if (!find_flow(p,flow)) return -EINVAL;
        tcm->tcm_handle = flow->classid;
+       tcm->tcm_info = flow->q->handle;
        rta = (struct rtattr *) b;
        RTA_PUT(skb,TCA_OPTIONS,0,NULL);
        RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);
@@ -664,6 +668,20 @@ rtattr_failure:
        skb_trim(skb,b-skb->data);
        return -1;
 }
+static int
+atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
+       struct gnet_dump *d)
+{
+       struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+
+       flow->qstats.qlen = flow->q->q.qlen;
+
+       if (gnet_stats_copy_basic(d, &flow->bstats) < 0 ||
+           gnet_stats_copy_queue(d, &flow->qstats) < 0)
+               return -1;
+
+       return 0;
+}
 
 static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
@@ -682,6 +700,7 @@ static struct Qdisc_class_ops atm_class_ops = {
        .bind_tcf       =       atm_tc_bind_filter,
        .unbind_tcf     =       atm_tc_put,
        .dump           =       atm_tc_dump_class,
+       .dump_stats     =       atm_tc_dump_class_stats,
 };
 
 static struct Qdisc_ops atm_qdisc_ops = {