patch-1.3.14 linux/net/netrom/nr_out.c
Next file: linux/net/netrom/nr_route.c
Previous file: linux/net/netrom/nr_in.c
Back to the patch index
Back to the overall index
- Lines: 118
- Date:
Thu Jul 27 19:36:17 1995
- Orig file:
v1.3.13/linux/net/netrom/nr_out.c
- Orig date:
Fri Jul 7 08:54:58 1995
diff -u --recursive --new-file v1.3.13/linux/net/netrom/nr_out.c linux/net/netrom/nr_out.c
@@ -14,6 +14,7 @@
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_out.c
+ * NET/ROM 003 Jonathan(G4KLX) Added NET/ROM fragmentation.
*/
#include <linux/config.h>
@@ -40,19 +41,64 @@
#include <linux/interrupt.h>
#include <net/netrom.h>
-int nr_output(struct sock *sk, struct sk_buff *skb)
+/*
+ * This is where all NET/ROM frames pass, except for IP-over-NET/ROM which
+ * cannot be fragmented in this manner.
+ */
+void nr_output(struct sock *sk, struct sk_buff *skb)
{
- skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */
+ struct sk_buff *skbn;
+ unsigned char transport[NR_TRANSPORT_LEN];
+ int err, frontlen, len, mtu;
+
+ mtu = sk->nr->device->mtu;
+
+ if (skb->len - NR_TRANSPORT_LEN > mtu) {
+ /* Save a copy of the Transport Header */
+ memcpy(transport, skb->data, NR_TRANSPORT_LEN);
+ skb_pull(skb, NR_TRANSPORT_LEN);
+
+ frontlen = skb_headroom(skb);
+
+ while (skb->len > 0) {
+ if ((skbn = sock_alloc_send_skb(sk, frontlen + mtu, 0, &err)) == NULL)
+ return;
+
+ skbn->sk = sk;
+ skbn->free = 1;
+ skbn->arp = 1;
+
+ skb_reserve(skbn, frontlen);
+
+ len = (mtu > skb->len) ? skb->len : mtu;
+
+ /* Copy the user data */
+ memcpy(skb_put(skbn, len), skb->data, len);
+ skb_pull(skb, len);
+
+ /* Duplicate the Transport Header */
+ skb_push(skbn, NR_TRANSPORT_LEN);
+ memcpy(skbn->data, transport, NR_TRANSPORT_LEN);
+
+ if (skb->len > 0)
+ skbn->data[4] |= NR_MORE_FLAG;
+
+ skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */
+ }
+
+ skb->free = 1;
+ kfree_skb(skb, FREE_WRITE);
+ } else {
+ skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */
+ }
if (sk->nr->state == NR_STATE_3)
nr_kick(sk);
-
- return 0;
}
/*
- * 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.
+ * 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.
*/
static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
{
@@ -62,6 +108,9 @@
skb->data[2] = sk->nr->vs;
skb->data[3] = sk->nr->vr;
+ if (sk->nr->condition & OWN_RX_BUSY_CONDITION)
+ skb->data[4] |= NR_CHOKE_FLAG;
+
nr_transmit_buffer(sk, skb);
}
@@ -154,13 +203,13 @@
memcpy(dptr, &sk->nr->source_addr, sizeof(ax25_address));
dptr[6] &= ~LAPB_C;
dptr[6] &= ~LAPB_E;
- dptr[6] |= SSID_SPARE;
+ dptr[6] |= SSSID_SPARE;
dptr += AX25_ADDR_LEN;
memcpy(dptr, &sk->nr->dest_addr, sizeof(ax25_address));
dptr[6] &= ~LAPB_C;
dptr[6] |= LAPB_E;
- dptr[6] |= SSID_SPARE;
+ dptr[6] |= SSSID_SPARE;
dptr += AX25_ADDR_LEN;
*dptr++ = nr_default.ttl;
@@ -207,10 +256,10 @@
int frametype = NR_INFOACK;
if (sk->nr->condition & OWN_RX_BUSY_CONDITION) {
- frametype += NR_CHOKE_FLAG;
+ frametype |= NR_CHOKE_FLAG;
} else {
if (skb_peek(&sk->nr->reseq_queue) != NULL) {
- frametype += NR_NAK_FLAG;
+ frametype |= NR_NAK_FLAG;
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this