patch-2.4.0-test11 linux/net/x25/x25_out.c

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

diff -u --recursive --new-file v2.4.0-test10/linux/net/x25/x25_out.c linux/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 @@
 }
 
 /*
- *	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 @@
 		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 @@
 			}
 
 			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 @@
 		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;
 	}


FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)