5 #include <linux/module.h>
6 #include <linux/slab.h>
9 #include <linux/string.h>
10 #include <linux/errno.h>
12 #include <linux/atmdev.h>
14 #include <linux/rtnetlink.h>
40 #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
82 static int atm_tc_graft(
struct Qdisc *sch,
unsigned long arg,
88 pr_debug(
"atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
89 sch, p, flow,
new, old);
90 if (list_empty(&flow->
list))
101 static struct Qdisc *atm_tc_leaf(
struct Qdisc *sch,
unsigned long cl)
105 pr_debug(
"atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
106 return flow ? flow->
q :
NULL;
109 static unsigned long atm_tc_get(
struct Qdisc *sch,
u32 classid)
114 pr_debug(
"atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
115 flow = lookup_flow(sch, classid);
118 pr_debug(
"atm_tc_get: flow %p\n", flow);
119 return (
unsigned long)flow;
122 static unsigned long atm_tc_bind_filter(
struct Qdisc *sch,
125 return atm_tc_get(sch, classid);
133 static void atm_tc_put(
struct Qdisc *sch,
unsigned long cl)
138 pr_debug(
"atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
141 pr_debug(
"atm_tc_put: destroying\n");
142 list_del_init(&flow->
list);
143 pr_debug(
"atm_tc_put: qdisc %p\n", flow->
q);
147 pr_debug(
"atm_tc_put: f_count %ld\n",
153 atm_tc_put(sch, (
unsigned long)flow->
excess);
154 if (flow != &p->
link)
166 pr_debug(
"sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
168 tasklet_schedule(&p->
task);
171 static const u8 llc_oui_ip[] = {
185 static int atm_tc_change(
struct Qdisc *sch,
u32 classid,
u32 parent,
197 pr_debug(
"atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
198 "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
216 error = nla_parse_nested(tb,
TCA_ATM_MAX, opt, atm_policy);
222 fd = nla_get_u32(tb[TCA_ATM_FD]);
223 pr_debug(
"atm_tc_change: fd %d\n", fd);
225 hdr_len = nla_len(tb[TCA_ATM_HDR]);
226 hdr = nla_data(tb[TCA_ATM_HDR]);
235 atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
239 pr_debug(
"atm_tc_change: type %d, payload %d, hdr_len %d\n",
240 opt->
nla_type, nla_len(opt), hdr_len);
253 pr_debug(
"atm_tc_change: classid mismatch\n");
261 for (i = 1; i < 0x8000; i++) {
263 cl = atm_tc_get(sch, classid);
269 pr_debug(
"atm_tc_change: new id %x\n", classid);
271 pr_debug(
"atm_tc_change: flow %p\n", flow);
280 pr_debug(
"atm_tc_change: qdisc %p\n", flow->
q);
282 flow->
vcc = ATM_SD(sock);
283 flow->
vcc->user_back = flow;
287 flow->
vcc->pop = sch_atm_pop;
291 list_add(&flow->
list, &p->
link.list);
296 memcpy(flow->
hdr, llc_oui_ip,
sizeof(llc_oui_ip));
297 *arg = (
unsigned long)flow;
301 atm_tc_put(sch, (
unsigned long)excess);
306 static int atm_tc_delete(
struct Qdisc *sch,
unsigned long arg)
311 pr_debug(
"atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
312 if (list_empty(&flow->
list))
321 pr_err(
"atm_tc_delete: flow->ref == %d\n", flow->
ref);
326 atm_tc_put(sch, arg);
335 pr_debug(
"atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
340 walker->
fn(sch, (
unsigned long)flow, walker) < 0) {
348 static struct tcf_proto **atm_tc_find_tcf(
struct Qdisc *sch,
unsigned long cl)
353 pr_debug(
"atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
359 static int atm_tc_enqueue(
struct sk_buff *skb,
struct Qdisc *sch)
367 pr_debug(
"atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
381 flow = lookup_flow(sch,
res.classid);
393 ATM_SKB(skb)->atm_options = flow->
vcc->atm_options;
395 #ifdef CONFIG_NET_CLS_ACT
414 ret = qdisc_enqueue(skb, flow->
q);
433 if (flow == &p->
link) {
437 tasklet_schedule(&p->
task);
448 static void sch_atm_dequeue(
unsigned long data)
455 pr_debug(
"sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
457 if (flow == &p->
link)
463 while ((skb = flow->
q->ops->peek(flow->
q))) {
467 skb = qdisc_dequeue_peeked(flow->
q);
471 qdisc_bstats_update(sch, skb);
472 bstats_update(&flow->
bstats, skb);
473 pr_debug(
"atm_tc_dequeue: sending on class %p\n", flow);
475 skb_pull(skb, skb_network_offset(skb));
476 if (skb_headroom(skb) < flow->
hdr_len) {
485 pr_debug(
"sch_atm_dequeue: ip %p, data %p\n",
486 skb_network_header(skb), skb->
data);
491 &sk_atm(flow->
vcc)->sk_wmem_alloc);
493 flow->
vcc->send(flow->
vcc, skb);
498 static struct sk_buff *atm_tc_dequeue(
struct Qdisc *sch)
503 pr_debug(
"atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
504 tasklet_schedule(&p->
task);
505 skb = qdisc_dequeue_peeked(p->
link.q);
515 pr_debug(
"atm_tc_peek(sch %p,[qdisc %p])\n", sch, p);
517 return p->
link.q->ops->peek(p->
link.q);
520 static unsigned int atm_tc_drop(
struct Qdisc *sch)
526 pr_debug(
"atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
528 if (flow->
q->ops->drop && (len = flow->
q->ops->drop(flow->
q)))
534 static int atm_tc_init(
struct Qdisc *sch,
struct nlattr *opt)
538 pr_debug(
"atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
539 INIT_LIST_HEAD(&p->
flows);
540 INIT_LIST_HEAD(&p->
link.list);
543 &pfifo_qdisc_ops, sch->
handle);
556 static void atm_tc_reset(
struct Qdisc *sch)
561 pr_debug(
"atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
572 pr_debug(
"atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
578 pr_err(
"atm_destroy: %p->ref = %d\n", flow, flow->ref);
579 atm_tc_put(sch, (
unsigned long)flow);
584 static int atm_tc_dump_class(
struct Qdisc *sch,
unsigned long cl,
591 pr_debug(
"atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
592 sch, p, flow, skb, tcm);
593 if (list_empty(&flow->
list))
600 goto nla_put_failure;
603 goto nla_put_failure;
609 pvc.sap_addr.itf = flow->
vcc->dev ? flow->
vcc->dev->number : -1;
610 pvc.sap_addr.vpi = flow->
vcc->vpi;
611 pvc.sap_addr.vci = flow->
vcc->vci;
613 goto nla_put_failure;
616 goto nla_put_failure;
619 if (nla_put_u32(skb, TCA_ATM_EXCESS, flow->
classid))
620 goto nla_put_failure;
622 if (nla_put_u32(skb, TCA_ATM_EXCESS, 0))
623 goto nla_put_failure;
625 nla_nest_end(skb, nest);
629 nla_nest_cancel(skb, nest);
633 atm_tc_dump_class_stats(
struct Qdisc *sch,
unsigned long arg,
638 flow->
qstats.qlen = flow->
q->q.qlen;
647 static int atm_tc_dump(
struct Qdisc *sch,
struct sk_buff *skb)
653 .graft = atm_tc_graft,
657 .change = atm_tc_change,
658 .delete = atm_tc_delete,
660 .tcf_chain = atm_tc_find_tcf,
661 .bind_tcf = atm_tc_bind_filter,
662 .unbind_tcf = atm_tc_put,
663 .dump = atm_tc_dump_class,
664 .dump_stats = atm_tc_dump_class_stats,
668 .cl_ops = &atm_class_ops,
671 .enqueue = atm_tc_enqueue,
672 .dequeue = atm_tc_dequeue,
676 .reset = atm_tc_reset,
677 .destroy = atm_tc_destroy,
682 static int __init atm_init(
void)
687 static void __exit atm_exit(
void)