patch-2.3.43 linux/net/sched/sch_atm.c
Next file: linux/net/sched/sch_cbq.c
Previous file: linux/net/packet/af_packet.c
Back to the patch index
Back to the overall index
- Lines: 108
- Date:
Tue Feb 8 18:23:13 2000
- Orig file:
v2.3.42/linux/net/sched/sch_atm.c
- Orig date:
Fri Sep 10 23:57:38 1999
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_atm.c linux/net/sched/sch_atm.c
@@ -1,6 +1,6 @@
/* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */
-/* Written 1998,1999 by Werner Almesberger, EPFL ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
#include <linux/config.h>
@@ -56,12 +56,14 @@
#define PRIV(sch) ((struct atm_qdisc_data *) (sch)->data)
+#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
struct atm_flow_data {
struct Qdisc *q; /* FIFO, TBF, etc. */
struct tcf_proto *filter_list;
struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
+ void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */
struct socket *sock; /* for closing */
u32 classid; /* x:y type ID */
int ref; /* reference count */
@@ -133,7 +135,7 @@
static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid)
{
- struct atm_qdisc_data *p = PRIV(sch);
+ struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch);
struct atm_flow_data *flow;
DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
@@ -184,6 +186,7 @@
}
if (flow->sock) {
DPRINTK("atm_tc_put: f_count %d\n",file_count(flow->sock->file));
+ flow->vcc->pop = flow->old_pop;
sockfd_put(flow->sock);
}
if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess);
@@ -195,6 +198,13 @@
}
+static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+{
+ VCC2FLOW(vcc)->old_pop(vcc,skb);
+ mark_bh(NET_BH); /* may allow to send more */
+}
+
+
static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
struct rtattr **tca, unsigned long *arg)
{
@@ -289,7 +299,10 @@
DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
flow->sock = sock;
flow->vcc = ATM_SD(sock); /* speedup */
+ flow->vcc->user_back = flow;
DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
+ flow->old_pop = flow->vcc->pop;
+ flow->vcc->pop = sch_atm_pop;
flow->classid = classid;
flow->ref = 1;
flow->excess = excess;
@@ -440,6 +453,10 @@
* little bursts. Otherwise, it may ... @@@
*/
while ((skb = flow->q->dequeue(flow->q))) {
+ if (!atm_may_send(flow->vcc,skb->truesize)) {
+ flow->q->ops->requeue(skb,flow->q);
+ break;
+ }
sch->q.qlen--;
D2PRINTK("atm_tc_deqeueue: sending on class %p\n",flow);
/* remove any LL header somebody else has attached */
@@ -468,6 +485,22 @@
}
+static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch)
+{
+ struct atm_qdisc_data *p = PRIV(sch);
+ int ret;
+
+ 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++;
+ }
+ return ret;
+}
+
+
static int atm_tc_drop(struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
@@ -616,7 +649,7 @@
atm_tc_enqueue, /* enqueue */
atm_tc_dequeue, /* dequeue */
- atm_tc_enqueue, /* requeue; we're cheating a little */
+ atm_tc_requeue, /* requeue */
atm_tc_drop, /* drop */
atm_tc_init, /* init */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)