diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-11-28 03:58:46 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-11-28 03:58:46 +0000 |
commit | b63ad0882a16a5d28003e57f2b0b81dee3fb322b (patch) | |
tree | 0a343ce219e2b8b38a5d702d66032c57b83d9720 /net/x25 | |
parent | a9d7bff9a84dba79609a0002e5321b74c4d64c64 (diff) |
Merge with 2.4.0-test11.
Diffstat (limited to 'net/x25')
-rw-r--r-- | net/x25/af_x25.c | 41 | ||||
-rw-r--r-- | net/x25/x25_dev.c | 11 | ||||
-rw-r--r-- | net/x25/x25_in.c | 17 | ||||
-rw-r--r-- | net/x25/x25_out.c | 30 |
4 files changed, 81 insertions, 18 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 320722c40..0242b12e5 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -16,13 +16,16 @@ * X.25 001 Jonathan Naylor Started coding. * X.25 002 Jonathan Naylor Centralised disconnect handling. * New timer architecture. - * 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant. - * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of + * 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant. + * 2000-03-22 Daniela Squassoni Allowed disabling/enabling of * facilities negotiation and increased * the throughput upper limit. - * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups - * 2000-04-09 Henner Eisen Set sock->state in x25_accept(). + * 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups + * 2000-09-04 Henner Eisen Set sock->state in x25_accept(). * Fixed x25_output() related skb leakage. + * 2000-10-02 Henner Eisen Made x25_kick() single threaded per socket. + * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation. + * 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN */ #include <linux/config.h> @@ -191,6 +194,7 @@ static void x25_kill_by_device(struct net_device *dev) static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = (struct net_device *)ptr; + struct x25_neigh *neigh; if (dev->type == ARPHRD_X25 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) @@ -201,6 +205,10 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo case NETDEV_UP: x25_link_device_up(dev); break; + case NETDEV_GOING_DOWN: + if ((neigh = x25_get_neigh(dev))) + x25_terminate_link(neigh); + break; case NETDEV_DOWN: x25_kill_by_device(dev); x25_route_device_down(dev); @@ -471,6 +479,7 @@ static int x25_create(struct socket *sock, int protocol) sock->ops = &x25_proto_ops; sk->protocol = protocol; + sk->backlog_rcv = x25_backlog_rcv; x25->t21 = sysctl_x25_call_request_timeout; x25->t22 = sysctl_x25_reset_request_timeout; @@ -905,6 +914,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; + X25_SKB_CB(skb)->flags = msg->msg_flags; skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN); @@ -974,14 +984,31 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if (msg->msg_flags & MSG_OOB) { skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb); } else { - err = x25_output(sk, skb); - if(err){ - len = err; + len = x25_output(sk, skb); + if(len<0){ kfree_skb(skb); + } else { + if(sk->protinfo.x25->qbitincl) len++; } } + /* + * lock_sock() is currently only used to serialize this x25_kick() + * against input-driven x25_kick() calls. It currently only blocks + * incoming packets for this socket and does not protect against + * any other socket state changes and is not called from anywhere + * else. As x25_kick() cannot block and as long as all socket + * operations are BKL-wrapped, we don't need take to care about + * purging the backlog queue in x25_release(). + * + * Using lock_sock() to protect all socket operations entirely + * (and making the whole x25 stack SMP aware) unfortunately would + * require major changes to {send,recv}msg and skb allocation methods. + * -> 2.5 ;) + */ + lock_sock(sk); x25_kick(sk); + release_sock(sk); return len; } diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index d986022fb..fbc781dce 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -68,8 +68,17 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh) * Find an existing socket. */ if ((sk = x25_find_socket(lci, neigh)) != NULL) { + int queued = 1; + skb->h.raw = skb->data; - return x25_process_rx_frame(sk, skb); + bh_lock_sock(sk); + if (!sk->lock.users) { + queued = x25_process_rx_frame(sk, skb); + } else { + sk_add_backlog(sk, skb); + } + bh_unlock_sock(sk); + return queued; } /* diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 5110d327a..bcb5f1cf4 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -16,8 +16,10 @@ * X.25 001 Jonathan Naylor Started coding. * X.25 002 Jonathan Naylor Centralised disconnection code. * New timer architecture. - * mar/20/00 Daniela Squassoni Disabling/enabling of facilities + * 2000-03-20 Daniela Squassoni Disabling/enabling of facilities * negotiation. + * 2000-11-10 Henner Eisen Check and reset for out-of-sequence + * i-frames. */ #include <linux/config.h> @@ -216,7 +218,8 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp case X25_DATA: /* XXX */ sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; - if (!x25_validate_nr(sk, nr)) { + if ((ns!=sk->protinfo.x25->vr) || + !x25_validate_nr(sk, nr)) { x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); @@ -357,4 +360,14 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb) return queued; } +int x25_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + int queued; + + queued = x25_process_rx_frame(sk,skb); + if(!queued) kfree_skb(skb); + + return 0; +} + #endif diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 077f2c0b4..b3ce30477 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c @@ -15,7 +15,10 @@ * History * X.25 001 Jonathan Naylor Started coding. * X.25 002 Jonathan Naylor New timer architecture. - * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage. + * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage. + * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation. + * 2000-11-10 Henner Eisen x25_send_iframe(): re-queued frames + * needed cleaned seq-number fields. */ #include <linux/config.h> @@ -55,13 +58,17 @@ static int x25_pacsize_to_bytes(unsigned int pacsize) } /* - * This is where all X.25 information frames pass; + * This is where all X.25 information frames pass. + * + * Returns the amount of user data bytes sent on success + * or a negative error code on failure. */ int x25_output(struct sock *sk, struct sk_buff *skb) { struct sk_buff *skbn; unsigned char header[X25_EXT_MIN_LEN]; int err, frontlen, len, header_len, max_len; + int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT; header_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN; max_len = x25_pacsize_to_bytes(sk->protinfo.x25->facilities.pacsize_out); @@ -74,11 +81,14 @@ int x25_output(struct sock *sk, struct sk_buff *skb) frontlen = skb_headroom(skb); while (skb->len > 0) { - if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL){ - int unsent = skb->len - header_len; - SOCK_DEBUG(sk, "x25_output: framgent allocation failed, err=%d, %d bytes unsent\n", err, unsent); - return err; + if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, noblock, &err)) == NULL){ + if(err == -EWOULDBLOCK && noblock){ + kfree_skb(skb); + return sent; } + SOCK_DEBUG(sk, "x25_output: fragment allocation failed, err=%d, %d bytes sent\n", err, sent); + return err; + } skb_reserve(skbn, frontlen); @@ -100,13 +110,15 @@ int x25_output(struct sock *sk, struct sk_buff *skb) } skb_queue_tail(&sk->write_queue, skbn); + sent += len; } kfree_skb(skb); } else { skb_queue_tail(&sk->write_queue, skb); + sent = skb->len - header_len; } - return 0; + return sent; } /* @@ -119,9 +131,11 @@ static void x25_send_iframe(struct sock *sk, struct sk_buff *skb) return; if (sk->protinfo.x25->neighbour->extended) { - skb->data[2] |= (sk->protinfo.x25->vs << 1) & 0xFE; + skb->data[2] = (sk->protinfo.x25->vs << 1) & 0xFE; + skb->data[3] &= X25_EXT_M_BIT; skb->data[3] |= (sk->protinfo.x25->vr << 1) & 0xFE; } else { + skb->data[2] &= X25_STD_M_BIT; skb->data[2] |= (sk->protinfo.x25->vs << 1) & 0x0E; skb->data[2] |= (sk->protinfo.x25->vr << 5) & 0xE0; } |