diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
commit | 967c65a99059fd459b956c1588ce0ba227912c4e (patch) | |
tree | 8224d013ff5d255420713d05610c7efebd204d2a /net/rose | |
parent | e20c1cc1656a66a2773bca4591a895cbc12696ff (diff) |
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'net/rose')
-rw-r--r-- | net/rose/af_rose.c | 19 | ||||
-rw-r--r-- | net/rose/rose_dev.c | 8 | ||||
-rw-r--r-- | net/rose/rose_in.c | 57 | ||||
-rw-r--r-- | net/rose/rose_link.c | 2 | ||||
-rw-r--r-- | net/rose/rose_out.c | 84 | ||||
-rw-r--r-- | net/rose/rose_route.c | 70 | ||||
-rw-r--r-- | net/rose/rose_subr.c | 43 |
7 files changed, 107 insertions, 176 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 69b77a9f2..5ae64334d 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -548,6 +548,8 @@ static int rose_create(struct socket *sock, int protocol) sock_init_data(sock, sk); + skb_queue_head_init(&rose->ack_queue); + sock->ops = &rose_proto_ops; sk->protocol = protocol; sk->mtu = ROSE_MTU; /* 253 */ @@ -555,8 +557,6 @@ static int rose_create(struct socket *sock, int protocol) init_timer(&rose->timer); init_timer(&rose->idletimer); - skb_queue_head_init(&rose->frag_queue); - rose->t1 = sysctl_rose_call_request_timeout; rose->t2 = sysctl_rose_reset_request_timeout; rose->t3 = sysctl_rose_clear_request_timeout; @@ -583,6 +583,8 @@ static struct sock *rose_make_new(struct sock *osk) sock_init_data(NULL, sk); + skb_queue_head_init(&rose->ack_queue); + sk->type = osk->type; sk->socket = osk->socket; sk->priority = osk->priority; @@ -598,8 +600,6 @@ static struct sock *rose_make_new(struct sock *osk) init_timer(&rose->timer); init_timer(&rose->idletimer); - skb_queue_head_init(&rose->frag_queue); - rose->t1 = osk->protinfo.rose->t1; rose->t2 = osk->protinfo.rose->t2; rose->t3 = osk->protinfo.rose->t3; @@ -1068,7 +1068,9 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, return -ENOTCONN; } - rose_output(sk, skb); /* Shove it onto the queue */ + skb_queue_tail(&sk->write_queue, skb); /* Shove it onto the queue */ + + rose_kick(sk); return len; } @@ -1210,7 +1212,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return 0; } - case SIOCRSL2CALL: + case SIOCRSSL2CALL: if (!suser()) return -EPERM; if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) ax25_listen_release(&rose_callsign, NULL); @@ -1220,6 +1222,11 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ax25_listen_register(&rose_callsign, NULL); return 0; + case SIOCRSGL2CALL: + if (copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address))) + return -EFAULT; + return 0; + case SIOCRSACCEPT: if (sk->protinfo.rose->state == ROSE_STATE_5) { rose_write_internal(sk, ROSE_CALL_ACCEPTED); diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 7861220ee..bc2097cda 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -221,14 +221,6 @@ int rose_init(struct device *dev) /* New-style flags. */ dev->flags = 0; - dev->family = AF_INET; - -#ifdef CONFIG_INET - dev->pa_addr = in_aton("192.168.0.1"); - dev->pa_brdaddr = in_aton("192.168.0.255"); - dev->pa_mask = in_aton("255.255.255.0"); - dev->pa_alen = 4; -#endif if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL) return -ENOMEM; diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index 1ac11528d..de412d3c4 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -19,6 +19,7 @@ * ROSE 001 Jonathan(G4KLX) Cloned from nr_in.c * ROSE 002 Jonathan(G4KLX) Return cause and diagnostic codes from Clear Requests. * ROSE 003 Jonathan(G4KLX) New timer architecture. + * Removed M bit processing. */ #include <linux/config.h> @@ -46,43 +47,6 @@ #include <linux/interrupt.h> #include <net/rose.h> -static int rose_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) -{ - struct sk_buff *skbo, *skbn = skb; - - rose_start_idletimer(sk); - - if (more) { - sk->protinfo.rose->fraglen += skb->len; - skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); - return 0; - } - - if (!more && sk->protinfo.rose->fraglen > 0) { /* End of fragment */ - sk->protinfo.rose->fraglen += skb->len; - skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); - - if ((skbn = alloc_skb(sk->protinfo.rose->fraglen, GFP_ATOMIC)) == NULL) - return 1; - - skbn->h.raw = skbn->data; - - skbo = skb_dequeue(&sk->protinfo.rose->frag_queue); - memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); - kfree_skb(skbo, FREE_READ); - - while ((skbo = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) { - skb_pull(skbo, ROSE_MIN_LEN); - memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); - kfree_skb(skbo, FREE_READ); - } - - sk->protinfo.rose->fraglen = 0; - } - - return sock_queue_rcv_skb(sk, skbn); -} - /* * State machine for state 1, Awaiting Call Accepted State. * The handling of the timer(s) is in file rose_timer.c. @@ -166,6 +130,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->vr = 0; sk->protinfo.rose->va = 0; sk->protinfo.rose->vl = 0; + rose_requeue_frames(sk); break; case ROSE_CLEAR_REQUEST: @@ -191,11 +156,9 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety rose_start_t2timer(sk); rose_stop_idletimer(sk); } else { - if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { - sk->protinfo.rose->va = nr; - } else { - rose_check_iframes_acked(sk, nr); - } + rose_frames_acked(sk, nr); + if (frametype == ROSE_RNR) + rose_requeue_frames(sk); } break; @@ -213,15 +176,12 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety rose_stop_idletimer(sk); break; } - if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { - sk->protinfo.rose->va = nr; - } else { - rose_check_iframes_acked(sk, nr); - } + rose_frames_acked(sk, nr); if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) break; if (ns == sk->protinfo.rose->vr) { - if (rose_queue_rx_frame(sk, skb, m) == 0) { + rose_start_idletimer(sk); + if (sock_queue_rcv_skb(sk, skb) == 0) { sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS; queued = 1; } else { @@ -270,6 +230,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->vs = 0; sk->protinfo.rose->vl = 0; sk->protinfo.rose->state = ROSE_STATE_3; + rose_requeue_frames(sk); break; case ROSE_CLEAR_REQUEST: diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index b481e485f..8ee27147a 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -113,7 +113,7 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) else rose_call = &rose_callsign; - neigh->ax25 = ax25_send_frame(skb, 256, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + neigh->ax25 = ax25_send_frame(skb, 0, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); return (neigh->ax25 != NULL); } diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index 0ed9f7480..aea1d9f68 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c @@ -12,6 +12,7 @@ * History * ROSE 001 Jonathan(G4KLX) Cloned from nr_out.c * ROSE 003 Jonathan(G4KLX) New timer architecture. + * Removed M bit processing. */ #include <linux/config.h> @@ -38,52 +39,6 @@ #include <linux/interrupt.h> #include <net/rose.h> -/* - * This is where all ROSE frames pass; - */ -void rose_output(struct sock *sk, struct sk_buff *skb) -{ - struct sk_buff *skbn; - unsigned char header[ROSE_MIN_LEN]; - int err, frontlen, len; - - if (skb->len - ROSE_MIN_LEN > ROSE_MAX_PACKET_SIZE) { - /* Save a copy of the Header */ - memcpy(header, skb->data, ROSE_MIN_LEN); - skb_pull(skb, ROSE_MIN_LEN); - - frontlen = skb_headroom(skb); - - while (skb->len > 0) { - if ((skbn = sock_alloc_send_skb(sk, frontlen + ROSE_MAX_PACKET_SIZE, 0, 0, &err)) == NULL) - return; - - skb_reserve(skbn, frontlen); - - len = (ROSE_MAX_PACKET_SIZE > skb->len) ? skb->len : ROSE_MAX_PACKET_SIZE; - - /* Copy the user data */ - memcpy(skb_put(skbn, len), skb->data, len); - skb_pull(skb, len); - - /* Duplicate the Header */ - skb_push(skbn, ROSE_MIN_LEN); - memcpy(skbn->data, header, ROSE_MIN_LEN); - - if (skb->len > 0) - skbn->data[2] |= ROSE_M_BIT; - - skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */ - } - - kfree_skb(skb, FREE_WRITE); - } else { - skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */ - } - - rose_kick(sk); -} - /* * This procedure is passed a buffer descriptor for an iframe. It builds * the rest of the control part of the frame and then writes it out. @@ -103,8 +58,8 @@ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) void rose_kick(struct sock *sk) { - struct sk_buff *skb; - unsigned short end; + struct sk_buff *skb, *skbn; + unsigned short start, end; if (sk->protinfo.rose->state != ROSE_STATE_3) return; @@ -115,11 +70,14 @@ void rose_kick(struct sock *sk) if (skb_peek(&sk->write_queue) == NULL) return; - end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS; + start = (skb_peek(&sk->protinfo.rose->ack_queue) == NULL) ? sk->protinfo.rose->va : sk->protinfo.rose->vs; + end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS; - if (sk->protinfo.rose->vs == end) + if (start == end) return; + sk->protinfo.rose->vs = start; + /* * Transmit data until either we're out of data to send or * the window is full. @@ -128,13 +86,25 @@ void rose_kick(struct sock *sk) skb = skb_dequeue(&sk->write_queue); do { + if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { + skb_queue_head(&sk->write_queue, skb); + break; + } + + skb_set_owner_w(skbn, sk); + /* - * Transmit the frame. + * Transmit the frame copy. */ - rose_send_iframe(sk, skb); + rose_send_iframe(sk, skbn); sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; + /* + * Requeue the original data frame. + */ + skb_queue_tail(&sk->protinfo.rose->ack_queue, skb); + } while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); sk->protinfo.rose->vl = sk->protinfo.rose->vr; @@ -161,14 +131,4 @@ void rose_enquiry_response(struct sock *sk) rose_stop_timer(sk); } -void rose_check_iframes_acked(struct sock *sk, unsigned short nr) -{ - if (sk->protinfo.rose->vs == nr) { - sk->protinfo.rose->va = nr; - } else { - if (sk->protinfo.rose->va != nr) - sk->protinfo.rose->va = nr; - } -} - #endif diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 43358644c..d9145cdea 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -63,7 +63,7 @@ static void rose_remove_neigh(struct rose_neigh *); */ static int rose_add_node(struct rose_route_struct *rose_route, struct device *dev) { - struct rose_node *rose_node, *rose_tmpn, *rose_tmpp; + struct rose_node *rose_node; struct rose_neigh *rose_neigh; unsigned long flags; int i; @@ -116,55 +116,18 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de restore_flags(flags); } - /* - * This is a new node to be inserted into the list. Find where it needs - * to be inserted into the list, and insert it. We want to be sure - * to order the list in descending order of mask size to ensure that - * later when we are searching this list the first match will be the - * best match. - */ if (rose_node == NULL) { - rose_tmpn = rose_node_list; - rose_tmpp = NULL; - - while (rose_tmpn != NULL) { - if (rose_tmpn->mask > rose_route->mask) { - rose_tmpp = rose_tmpn; - rose_tmpn = rose_tmpn->next; - } else { - break; - } - } - - /* create new node */ if ((rose_node = kmalloc(sizeof(*rose_node), GFP_ATOMIC)) == NULL) return -ENOMEM; - rose_node->address = rose_route->address; - rose_node->mask = rose_route->mask; - rose_node->count = 1; + rose_node->address = rose_route->address; + rose_node->mask = rose_route->mask; + rose_node->count = 1; rose_node->neighbour[0] = rose_neigh; save_flags(flags); cli(); - - if (rose_tmpn == NULL) { - if (rose_tmpp == NULL) { /* Empty list */ - rose_node_list = rose_node; - rose_node->next = NULL; - } else { - rose_tmpp->next = rose_node; - rose_node->next = NULL; - } - } else { - if (rose_tmpp == NULL) { /* 1st node */ - rose_node->next = rose_node_list; - rose_node_list = rose_node; - } else { - rose_tmpp->next = rose_node; - rose_node->next = rose_tmpn; - } - } - + rose_node->next = rose_node_list; + rose_node_list = rose_node; restore_flags(flags); rose_neigh->count++; @@ -487,20 +450,29 @@ struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neig struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, unsigned char *diagnostic) { struct rose_node *node; + struct rose_neigh *neigh; int failed = 0; + int mask = 0; int i; - for (node = rose_node_list; node != NULL; node = node->next) { + for (neigh = NULL, node = rose_node_list; node != NULL; node = node->next) { if (rosecmpm(addr, &node->address, node->mask) == 0) { - for (i = 0; i < node->count; i++) { - if (!rose_ftimer_running(node->neighbour[i])) - return node->neighbour[i]; - else - failed = 1; + if (node->mask > mask) { + mask = node->mask; + + for (i = 0; i < node->count; i++) { + if (!rose_ftimer_running(node->neighbour[i])) + neigh = node->neighbour[i]; + else + failed = 1; + } } } } + if (neigh != NULL) + return neigh; + if (failed) { *cause = ROSE_OUT_OF_ORDER; *diagnostic = 0; diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index ee710bd6e..e7709726c 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -49,8 +49,47 @@ void rose_clear_queues(struct sock *sk) while ((skb = skb_dequeue(&sk->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - while ((skb = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) - kfree_skb(skb, FREE_READ); + while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) + kfree_skb(skb, FREE_WRITE); +} + +/* + * This routine purges the input queue of those frames that have been + * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the + * SDL diagram. + */ +void rose_frames_acked(struct sock *sk, unsigned short nr) +{ + struct sk_buff *skb; + + /* + * Remove all the ack-ed frames from the ack queue. + */ + if (sk->protinfo.rose->va != nr) { + while (skb_peek(&sk->protinfo.rose->ack_queue) != NULL && sk->protinfo.rose->va != nr) { + skb = skb_dequeue(&sk->protinfo.rose->ack_queue); + kfree_skb(skb, FREE_WRITE); + sk->protinfo.rose->va = (sk->protinfo.rose->va + 1) % ROSE_MODULUS; + } + } +} + +void rose_requeue_frames(struct sock *sk) +{ + struct sk_buff *skb, *skb_prev = NULL; + + /* + * Requeue all the un-ack-ed frames on the output queue to be picked + * up by rose_kick. This arrangement handles the possibility of an + * empty output queue. + */ + while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { + if (skb_prev == NULL) + skb_queue_head(&sk->write_queue, skb); + else + skb_append(skb_prev, skb); + skb_prev = skb; + } } /* |