X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fsched%2Fsch_atm.c;h=edc7bb0b9c8b72f8589b91e5d238f6448eb0ca5d;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=ca08449e7b03e72c2ae38372120f9ac8185de5fc;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index ca08449e7..edc7bb0b9 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -3,7 +3,6 @@ /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ -#include #include #include #include @@ -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; } @@ -573,9 +575,9 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) struct atm_qdisc_data *p = PRIV(sch); DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); - memset(p,0,sizeof(*p)); 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; @@ -636,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); @@ -665,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) { @@ -683,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 = { @@ -715,3 +733,4 @@ static void __exit atm_exit(void) module_init(atm_init) module_exit(atm_exit) +MODULE_LICENSE("GPL");