patch-2.1.68 linux/net/rose/rose_out.c
Next file: linux/net/rose/rose_route.c
Previous file: linux/net/rose/rose_link.c
Back to the patch index
Back to the overall index
- Lines: 134
- Date:
Sun Nov 30 14:00:40 1997
- Orig file:
v2.1.67/linux/net/rose/rose_out.c
- Orig date:
Mon Jul 7 08:20:00 1997
diff -u --recursive --new-file v2.1.67/linux/net/rose/rose_out.c linux/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 @@
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 @@
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 @@
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;
@@ -159,16 +129,6 @@
sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
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
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov