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
- Lines: 180
- Date:
Sun Jan 19 15:47:30 1997
- Orig file:
v2.1.21/linux/net/x25/x25_out.c
- Orig date:
Wed Dec 18 15:59:25 1996
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