patch-2.0.36 linux/net/rose/rose_out.c

Next file: linux/net/rose/rose_route.c
Previous file: linux/net/rose/rose_loopback.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.35/linux/net/rose/rose_out.c linux/net/rose/rose_out.c
@@ -11,7 +11,6 @@
  *
  *	History
  *	ROSE 001	Jonathan(G4KLX)	Cloned from nr_out.c
- *	ROSE 003	Jonathan(G4KLX)	Removed M bit processing.
  */
 
 #include <linux/config.h>
@@ -55,39 +54,56 @@
 
 void rose_kick(struct sock *sk)
 {
-	struct sk_buff *skb;
-	unsigned short end;
+	struct sk_buff *skb, *skbn;
+	unsigned short start, end;
 
-	del_timer(&sk->timer);
+	if (sk->protinfo.rose->state != ROSE_STATE_3)
+		return;
 
-	end = (sk->protinfo.rose->va + sysctl_rose_window_size) % ROSE_MODULUS;
+	if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY)
+		return;
 
-	if (!(sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) &&
-	    sk->protinfo.rose->vs != end                             &&
-	    skb_peek(&sk->write_queue) != NULL) {
-		/*
-		 * Transmit data until either we're out of data to send or
-		 * the window is full.
-		 */
+	if (skb_peek(&sk->write_queue) == NULL)
+		return;
 
-		skb  = skb_dequeue(&sk->write_queue);
+	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;
 
-		do {
-			/*
-			 * Transmit the frame.
-			 */
-			rose_send_iframe(sk, skb);
+	if (start == end)
+		return;
 
-			sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS;
+	sk->protinfo.rose->vs = start;
 
-		} while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
+	/*
+	 * Transmit data until either we're out of data to send or
+	 * the window is full.
+	 */
+
+	skb  = skb_dequeue(&sk->write_queue);
+
+	do {
+		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+			skb_queue_head(&sk->write_queue, skb);
+			break;
+		}
 
-		sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
-		sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
-		sk->protinfo.rose->timer      = 0;
-	}
+		/*
+		 * Transmit the frame copy.
+		 */
+		rose_send_iframe(sk, skbn);
 
-	rose_set_timer(sk);
+		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;
+	sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
+	sk->protinfo.rose->timer      = 0;
 }
 
 /*
@@ -105,16 +121,6 @@
 	sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
 	sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
 	sk->protinfo.rose->timer      = 0;
-}
-
-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