diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-09 02:54:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-09 02:54:55 +0000 |
commit | 493c987f7a352ca64fdb4dc03a21e24cbaf46f55 (patch) | |
tree | 184cddc0925e082c0500afd042f92e9f340fe890 /net/atm | |
parent | 2d25612a92c62b5708d6d43f38d28c6141173328 (diff) |
Merge with Linux 2.4.0-pre3-test6.
Diffstat (limited to 'net/atm')
-rw-r--r-- | net/atm/Makefile | 2 | ||||
-rw-r--r-- | net/atm/clip.c | 28 | ||||
-rw-r--r-- | net/atm/common.c | 10 | ||||
-rw-r--r-- | net/atm/common.h | 1 | ||||
-rw-r--r-- | net/atm/ipcommon.c | 35 | ||||
-rw-r--r-- | net/atm/ipcommon.h | 4 | ||||
-rw-r--r-- | net/atm/lec.c | 26 | ||||
-rw-r--r-- | net/atm/mpc.c | 2 | ||||
-rw-r--r-- | net/atm/proc.c | 9 | ||||
-rw-r--r-- | net/atm/signaling.c | 27 | ||||
-rw-r--r-- | net/atm/signaling.h | 8 | ||||
-rw-r--r-- | net/atm/svc.c | 13 |
12 files changed, 104 insertions, 61 deletions
diff --git a/net/atm/Makefile b/net/atm/Makefile index a43d790b1..c21cdcad1 100644 --- a/net/atm/Makefile +++ b/net/atm/Makefile @@ -25,7 +25,7 @@ ifeq ($(CONFIG_NET_SCH_ATM),y) NEED_IPCOM = ipcommon.o endif -O_OBJS += $(NEED_IPCOM) +OX_OBJS += $(NEED_IPCOM) ifeq ($(CONFIG_PROC_FS),y) OX_OBJS += proc.o diff --git a/net/atm/clip.c b/net/atm/clip.c index c2b6788c9..ca79e0066 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -274,14 +274,14 @@ static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb) static struct neigh_ops clip_neigh_ops = { - AF_INET, /* family */ - clip_neigh_destroy, /* destructor */ - clip_neigh_solicit, /* solicit */ - clip_neigh_error, /* error_report */ - dev_queue_xmit, /* output */ - dev_queue_xmit, /* connected_output */ - dev_queue_xmit, /* hh_output */ - dev_queue_xmit /* queue_xmit */ + family: AF_INET, + destructor: clip_neigh_destroy, + solicit: clip_neigh_solicit, + error_report: clip_neigh_error, + output: dev_queue_xmit, + connected_output: dev_queue_xmit, + hh_output: dev_queue_xmit, + queue_xmit: dev_queue_xmit, }; @@ -384,6 +384,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) if (!skb->dst) { printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); dev_kfree_skb(skb); + clip_priv->stats.tx_dropped++; return 0; } if (!skb->dst->neighbour) { @@ -395,8 +396,10 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) return 0; } #endif -printk("clip_start_xmit: NO NEIGHBOUR !\n"); -return 0; + printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n"); + dev_kfree_skb(skb); + clip_priv->stats.tx_dropped++; + return 0; } entry = NEIGH2ENTRY(skb->dst->neighbour); if (!entry->vccs) { @@ -440,7 +443,6 @@ return 0; entry->vccs->xoff = 0; return 0; } - if (old) return 0; spin_lock_irqsave(&clip_priv->xoff_lock,flags); netif_stop_queue(dev); /* XOFF -> throttle immediately */ barrier(); @@ -482,6 +484,7 @@ int clip_mkip(struct atm_vcc *vcc,int timeout) clip_vcc->old_pop = vcc->pop; vcc->push = clip_push; vcc->pop = clip_pop; + skb_queue_head_init(©); skb_migrate(&vcc->recvq,©); /* re-process everything received between connection setup and MKIP */ while ((skb = skb_dequeue(©))) @@ -622,7 +625,7 @@ static int clip_device_event(struct notifier_block *this,unsigned long event, DPRINTK("clip_device_event NETDEV_UP\n"); (void) to_atmarpd(act_up,PRIV(dev)->number,0); break; - case NETDEV_DOWN: + case NETDEV_GOING_DOWN: DPRINTK("clip_device_event NETDEV_DOWN\n"); (void) to_atmarpd(act_down,PRIV(dev)->number,0); break; @@ -633,6 +636,7 @@ static int clip_device_event(struct notifier_block *this,unsigned long event, break; case NETDEV_REBOOT: case NETDEV_REGISTER: + case NETDEV_DOWN: DPRINTK("clip_device_event %ld\n",event); /* ignore */ break; diff --git a/net/atm/common.c b/net/atm/common.c index 867085ed8..16a6fb6b4 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -105,6 +105,7 @@ int atm_create(struct socket *sock,int protocol,int family) vcc->callback = NULL; memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); + vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ atomic_set(&vcc->tx_inuse,0); atomic_set(&vcc->rx_inuse,0); vcc->push = NULL; @@ -116,6 +117,7 @@ int atm_create(struct socket *sock,int protocol,int family) init_waitqueue_head(&vcc->sleep); skb_queue_head_init(&vcc->recvq); skb_queue_head_init(&vcc->listenq); + sk->sleep = &vcc->sleep; sock->sk = sk; return 0; } @@ -409,6 +411,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len, return vcc->reply; if (!test_bit(ATM_VF_READY,&vcc->flags)) return -EPIPE; if (!size) return 0; + if (size < 0 || size > vcc->qos.txtp.max_sdu) return -EMSGSIZE; /* verify_area is done by net/socket.c */ eff = (size+3) & ~3; /* align to word boundary */ add_wait_queue(&vcc->sleep,&wait); @@ -750,8 +753,10 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) } -int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) +static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) { + int error; + /* * Don't let the QoS change the already connected AAL type nor the * traffic class. @@ -760,6 +765,9 @@ int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) return -EINVAL; + error = adjust_tp(&qos->txtp,qos->aal); + if (!error) error = adjust_tp(&qos->rxtp,qos->aal); + if (error) return error; if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; if (vcc->family == AF_ATMPVC) return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); diff --git a/net/atm/common.h b/net/atm/common.h index faf1866ac..6330ca31c 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -26,7 +26,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname,char *optval, int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci); void atm_release_vcc_sk(struct sock *sk,int free_sk); -int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); void atm_shutdown_dev(struct atm_dev *dev); int atm_proc_init(void); diff --git a/net/atm/ipcommon.c b/net/atm/ipcommon.c index d7c4a4d3a..707b74fb6 100644 --- a/net/atm/ipcommon.c +++ b/net/atm/ipcommon.c @@ -3,6 +3,7 @@ /* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */ +#include <linux/module.h> #include <linux/string.h> #include <linux/skbuff.h> #include <linux/netdevice.h> @@ -31,7 +32,11 @@ const unsigned char llc_oui[] = { /* - * skb_migrate moves the list at FROM to TO, emptying FROM in the process. + * skb_migrate appends the list at "from" to "to", emptying "from" in the + * process. skb_migrate is atomic with respect to all other skb operations on + * "from" and "to". Note that it locks both lists at the same time, so beware + * of potential deadlocks. + * * This function should live in skbuff.c or skbuff.h. */ @@ -40,18 +45,26 @@ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to) { struct sk_buff *skb; unsigned long flags; + struct sk_buff *skb_from = (struct sk_buff *) from; + struct sk_buff *skb_to = (struct sk_buff *) to; + struct sk_buff *prev; spin_lock_irqsave(&from->lock,flags); - *to = *from; - from->prev = (struct sk_buff *) from; - from->next = (struct sk_buff *) from; + spin_lock(&to->lock); + prev = from->prev; + from->next->prev = to->prev; + prev->next = skb_to; + to->prev->next = from->next; + to->prev = from->prev; + for (skb = from->next; skb != skb_to; skb = skb->next) + skb->list = to; + to->qlen += from->qlen; + spin_unlock(&to->lock); + from->prev = skb_from; + from->next = skb_from; from->qlen = 0; spin_unlock_irqrestore(&from->lock,flags); - spin_lock_init(&to->lock); - for (skb = ((struct sk_buff *) to)->next; - skb != (struct sk_buff *) from; skb = skb->next) skb->list = to; - if (to->next == (struct sk_buff *) from) - to->next = (struct sk_buff *) to; - to->next->prev = (struct sk_buff *) to; - to->prev->next = (struct sk_buff *) to; } + + +EXPORT_SYMBOL(skb_migrate); diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h index 30a5583b0..bc1675eca 100644 --- a/net/atm/ipcommon.h +++ b/net/atm/ipcommon.h @@ -16,8 +16,8 @@ extern struct net_device *clip_devs; /* - * Moves all skbs from "from" to "to". The operation is atomic for "from", but - * not for "to". "to" may only be accessed after skb_migrate finishes. + * Appends all skbs from "from" to "to". The operation is atomic with respect + * to all other skb operations on "from" or "to". */ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to); diff --git a/net/atm/lec.c b/net/atm/lec.c index f9b14dce5..d9921b408 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -332,23 +332,33 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); ATM_SKB(skb2)->vcc = send_vcc; - atomic_add(skb2->truesize, &send_vcc->tx_inuse); ATM_SKB(skb2)->iovcnt = 0; ATM_SKB(skb2)->atm_options = send_vcc->atm_options; DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name, send_vcc->vpi, send_vcc->vci); - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb2->len; - send_vcc->send(send_vcc, skb2); + if (atm_may_send(send_vcc, skb2->len)) { + atomic_add(skb2->truesize, &send_vcc->tx_inuse); + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb2->len; + send_vcc->send(send_vcc, skb2); + } else { + priv->stats.tx_dropped++; + dev_kfree_skb(skb2); + } } ATM_SKB(skb)->vcc = send_vcc; - atomic_add(skb->truesize, &send_vcc->tx_inuse); ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = send_vcc->atm_options; - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; - send_vcc->send(send_vcc, skb); + if (atm_may_send(send_vcc, skb->len)) { + atomic_add(skb->truesize, &send_vcc->tx_inuse); + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + send_vcc->send(send_vcc, skb); + } else { + priv->stats.tx_dropped++; + dev_kfree_skb(skb); + } #if 0 /* Should we wait for card's device driver to notify us? */ diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 1b3e13ad6..68cd8a034 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -239,7 +239,7 @@ void atm_mpoa_disp_qos(char *page, int *len) while (qos != NULL) { ip = (unsigned char *)&qos->ipaddr; sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip)); - *len += sprintf(page + *len, "%%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", + *len += sprintf(page + *len, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", NIPQUAD(ipaddr), qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); diff --git a/net/atm/proc.c b/net/atm/proc.c index 79ab6e045..b2b186ac4 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -104,7 +104,7 @@ static int svc_addr(char *buf,struct sockaddr_atmsvc *addr) strcpy(buf,addr->sas_addr.pub); len = strlen(addr->sas_addr.pub); buf += len; - if (*addr->sas_addr.pub) { + if (*addr->sas_addr.prv) { *buf++ = '+'; len++; } @@ -233,9 +233,10 @@ static void svc_info(struct atm_vcc *vcc,char *buf) int i; if (!vcc->dev) - sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%6s" : "N/A@%p%2s", + sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s", vcc,""); - else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,vcc->vci); + else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi, + vcc->vci); here = strchr(buf,0); here += sprintf(here,"%-10s ",vcc_state(vcc)); here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub, @@ -376,7 +377,7 @@ static int atm_svc_info(loff_t pos,char *buf) int left; if (!pos) - return sprintf(buf,"Itf VPI VCI State Remote\n"); + return sprintf(buf,"Itf VPI VCI State Remote\n"); left = pos-1; for (dev = atm_devs; dev; dev = dev->next) for (vcc = dev->vccs; vcc; vcc = vcc->next) diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 0240aa874..dc7998fd1 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -158,9 +158,9 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) } -void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, +void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type, struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc) + const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply) { struct sk_buff *skb; struct atmsvc_msg *msg; @@ -173,21 +173,26 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, msg->type = type; *(struct atm_vcc **) &msg->vcc = vcc; *(struct atm_vcc **) &msg->listen_vcc = listen_vcc; - msg->reply = 0; /* other ISP applications may use this field */ - if (vcc) { - msg->qos = vcc->qos; - msg->sap = vcc->sap; - } - if (!svc) msg->svc.sas_family = 0; - else msg->svc = *svc; + msg->reply = reply; + if (qos) msg->qos = *qos; + if (vcc) msg->sap = vcc->sap; + if (svc) msg->svc = *svc; if (vcc) msg->local = vcc->local; - if (!pvc) memset(&msg->pvc,0,sizeof(msg->pvc)); - else msg->pvc = *pvc; + if (pvc) msg->pvc = *pvc; sigd_put_skb(skb); if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags); } +void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, + struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc) +{ + sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0); + /* other ISP applications may use "reply" */ +} + + static void purge_vccs(struct atm_vcc *vcc) { while (vcc) { diff --git a/net/atm/signaling.h b/net/atm/signaling.h index 30d5d51d4..3b933ddb7 100644 --- a/net/atm/signaling.h +++ b/net/atm/signaling.h @@ -17,6 +17,14 @@ extern struct atm_vcc *sigd; /* needed in svc_release */ +/* + * sigd_enq is a wrapper for sigd_enq2, covering the more common cases, and + * avoiding huge lists of null values. + */ + +void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type, + struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply); void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, const struct sockaddr_atmsvc *svc); diff --git a/net/atm/svc.c b/net/atm/svc.c index 70fa063cb..bffe7aac5 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -77,8 +77,7 @@ static void svc_disconnect(struct atm_vcc *vcc) as_indicate has been answered */ while ((skb = skb_dequeue(&vcc->listenq))) { DPRINTK("LISTEN REL\n"); - sigd_enq(NULL,as_reject,vcc,NULL,NULL); /* @@@ should include - the reason */ + sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0); dev_kfree_skb(skb); } clear_bit(ATM_VF_REGIS,&vcc->flags); @@ -310,8 +309,8 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) dev_kfree_skb(skb); old_vcc->backlog_quota++; if (error) { - sigd_enq(NULL,as_reject,old_vcc,NULL,NULL); - /* @@@ should include the reason */ + sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL, + &old_vcc->qos,error); return error == -EAGAIN ? -EBUSY : error; } /* wait should be short, so we ignore the non-blocking flag */ @@ -348,13 +347,9 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr, int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) { DECLARE_WAITQUEUE(wait,current); - struct atm_qos save_qos; vcc->reply = WAITING; - save_qos = vcc->qos; /* @@@ really gross hack ... */ - vcc->qos = *qos; - sigd_enq(vcc,as_modify,NULL,NULL,&vcc->local); - vcc->qos = save_qos; + sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); add_wait_queue(&vcc->sleep,&wait); while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { |