patch-2.1.22 linux/net/x25/x25_out.c

Next file: linux/net/x25/x25_route.c
Previous file: linux/net/x25/x25_link.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.21/linux/net/x25/x25_out.c linux/net/x25/x25_out.c
@@ -39,6 +39,19 @@
 #include <linux/interrupt.h>
 #include <net/x25.h>
 
+static int x25_pacsize_to_bytes(unsigned int pacsize)
+{
+	int bytes = 1;
+
+	if (pacsize == 0)
+		return 128;
+
+	while (pacsize-- > 0)
+		bytes *= 2;
+
+	return bytes;
+}
+
 /*
  *	This is where all X.25 information frames pass;
  */
@@ -46,35 +59,33 @@
 {
 	struct sk_buff *skbn;
 	unsigned char header[X25_EXT_MIN_LEN];
-	int err, frontlen, len, min_len;
-	
-	min_len  = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN;
+	int err, frontlen, len, header_len, max_len;
+
+	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);
 
-	if (skb->len - min_len > 128) {		/* XXX */
+	if (skb->len - header_len > max_len) {
 		/* Save a copy of the Header */
-		memcpy(header, skb->data, min_len);
-		skb_pull(skb, min_len);
+		memcpy(header, skb->data, header_len);
+		skb_pull(skb, header_len);
 
 		frontlen = skb_headroom(skb);
 
 		while (skb->len > 0) {
-			if ((skbn = sock_alloc_send_skb(sk, frontlen + 128, 0, 0, &err)) == NULL)	/* XXX */
+			if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL)
 				return;
 
-			skbn->sk   = sk;
-			skbn->arp  = 1;
-
 			skb_reserve(skbn, frontlen);
 
-			len = (128 > skb->len) ? skb->len : 128;	/* XXX */
+			len = (max_len > skb->len) ? skb->len : max_len;
 
 			/* Copy the user data */
 			memcpy(skb_put(skbn, len), skb->data, len);
 			skb_pull(skb, len);
 
 			/* Duplicate the Header */
-			skb_push(skbn, min_len);
-			memcpy(skbn->data, header, min_len);
+			skb_push(skbn, header_len);
+			memcpy(skbn->data, header, header_len);
 
 			if (skb->len > 0) {
 				if (sk->protinfo.x25->neighbour->extended)
@@ -82,17 +93,14 @@
 				else
 					skbn->data[2] |= X25_STD_M_BIT;
 			}
-		
-			skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */
+
+			skb_queue_tail(&sk->write_queue, skbn);
 		}
 		
 		kfree_skb(skb, FREE_WRITE);
 	} else {
-		skb_queue_tail(&sk->write_queue, skb);		/* Throw it on the queue */
+		skb_queue_tail(&sk->write_queue, skb);
 	}
-
-	if (sk->protinfo.x25->state == X25_STATE_3)
-		x25_kick(sk);
 }
 
 /* 
@@ -117,56 +125,46 @@
 
 void x25_kick(struct sock *sk)
 {
-	struct sk_buff *skb, *skbn;
-	int last = 1;
-	unsigned short start, end, next;
+	struct sk_buff *skb;
+	unsigned short end;
 	int modulus;
-	
-	modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
 
 	del_timer(&sk->timer);
 
-	start = (skb_peek(&sk->protinfo.x25->ack_queue) == NULL) ? sk->protinfo.x25->va : sk->protinfo.x25->vs;
-	end   = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.window_size) % modulus;
+	/*
+	 *	Transmit interrupt data.
+	 */
+	if (!sk->protinfo.x25->intflag && skb_peek(&sk->protinfo.x25->interrupt_out_queue) != NULL) {
+		sk->protinfo.x25->intflag = 1;
+		skb = skb_dequeue(&sk->protinfo.x25->interrupt_out_queue);
+		x25_transmit_link(skb, sk->protinfo.x25->neighbour);
+	}
 
+	modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
+	end     = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.winsize_out) % modulus;
+
+	/*
+	 *	Transmit normal stream data.
+	 */
 	if (!(sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) &&
-	    start != end                                           &&
+	    sk->protinfo.x25->vs != end                            &&
 	    skb_peek(&sk->write_queue) != NULL) {
-
-		sk->protinfo.x25->vs = start;
-
 		/*
 		 * Transmit data until either we're out of data to send or
 		 * the window is full.
 		 */
 
-		/*
-		 * Dequeue the frame and copy it.
-		 */
-		skb  = skb_dequeue(&sk->write_queue);
+		skb = skb_dequeue(&sk->write_queue);
 
 		do {
-			if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-				skb_queue_head(&sk->write_queue, skb);
-				break;
-			}
-
-			next = (sk->protinfo.x25->vs + 1) % modulus;
-			last = (next == end);
-
 			/*
-			 * Transmit the frame copy.
+			 * Transmit the frame.
 			 */
-			x25_send_iframe(sk, skbn);
+			x25_send_iframe(sk, skb);
 
-			sk->protinfo.x25->vs = next;
-
-			/*
-			 * Requeue the original data frame.
-			 */
-			skb_queue_tail(&sk->protinfo.x25->ack_queue, skb);
+			sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus;
 
-		} while (!last && (skb = skb_dequeue(&sk->write_queue)) != NULL);
+		} while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
 
 		sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
 		sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;
@@ -196,10 +194,10 @@
 void x25_check_iframes_acked(struct sock *sk, unsigned short nr)
 {
 	if (sk->protinfo.x25->vs == nr) {
-		x25_frames_acked(sk, nr);
+		sk->protinfo.x25->va = nr;
 	} else {
 		if (sk->protinfo.x25->va != nr) {
-			x25_frames_acked(sk, nr);
+			sk->protinfo.x25->va = nr;
 		}
 	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov