root/net/netrom/nr_out.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nr_output
  2. nr_send_iframe
  3. nr_send_nak_frame
  4. nr_kick
  5. nr_transmit_buffer
  6. nr_nr_error_recovery
  7. nr_establish_data_link
  8. nr_enquiry_response
  9. nr_check_iframes_acked

   1 /*
   2  *      NET/ROM release 003
   3  *
   4  *      This is ALPHA test software. This code may break your machine, randomly fail to work with new 
   5  *      releases, misbehave and/or generally screw up. It might even work. 
   6  *
   7  *      This code REQUIRES 1.2.1 or higher/ NET3.029
   8  *
   9  *      This module:
  10  *              This module is free software; you can redistribute it and/or
  11  *              modify it under the terms of the GNU General Public License
  12  *              as published by the Free Software Foundation; either version
  13  *              2 of the License, or (at your option) any later version.
  14  *
  15  *      History
  16  *      NET/ROM 001     Jonathan(G4KLX) Cloned from ax25_out.c
  17  *      NET/ROM 003     Jonathan(G4KLX) Added NET/ROM fragmentation.
  18  */
  19 
  20 #include <linux/config.h>
  21 #ifdef CONFIG_NETROM
  22 #include <linux/errno.h>
  23 #include <linux/types.h>
  24 #include <linux/socket.h>
  25 #include <linux/in.h>
  26 #include <linux/kernel.h>
  27 #include <linux/sched.h>
  28 #include <linux/timer.h>
  29 #include <linux/string.h>
  30 #include <linux/sockios.h>
  31 #include <linux/net.h>
  32 #include <net/ax25.h>
  33 #include <linux/inet.h>
  34 #include <linux/netdevice.h>
  35 #include <linux/skbuff.h>
  36 #include <net/sock.h>
  37 #include <asm/segment.h>
  38 #include <asm/system.h>
  39 #include <linux/fcntl.h>
  40 #include <linux/mm.h>
  41 #include <linux/interrupt.h>
  42 #include <net/netrom.h>
  43 
  44 /*
  45  *      This is where all NET/ROM frames pass, except for IP-over-NET/ROM which
  46  *      cannot be fragmented in this manner.
  47  */
  48 void nr_output(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         struct sk_buff *skbn;
  51         unsigned char transport[NR_TRANSPORT_LEN];
  52         int err, frontlen, len, mtu;
  53 
  54         mtu = sk->nr->device->mtu;
  55         
  56         if (skb->len - NR_TRANSPORT_LEN > mtu) {
  57                 /* Save a copy of the Transport Header */
  58                 memcpy(transport, skb->data, NR_TRANSPORT_LEN);
  59                 skb_pull(skb, NR_TRANSPORT_LEN);
  60 
  61                 frontlen = skb_headroom(skb);
  62 
  63                 while (skb->len > 0) {
  64                         if ((skbn = sock_alloc_send_skb(sk, frontlen + mtu, 0, 0, &err)) == NULL)
  65                                 return;
  66 
  67                         skbn->sk   = sk;
  68                         skbn->free = 1;
  69                         skbn->arp  = 1;
  70 
  71                         skb_reserve(skbn, frontlen);
  72 
  73                         len = (mtu > skb->len) ? skb->len : mtu;
  74 
  75                         /* Copy the user data */
  76                         memcpy(skb_put(skbn, len), skb->data, len);
  77                         skb_pull(skb, len);
  78 
  79                         /* Duplicate the Transport Header */
  80                         skb_push(skbn, NR_TRANSPORT_LEN);
  81                         memcpy(skbn->data, transport, NR_TRANSPORT_LEN);
  82 
  83                         if (skb->len > 0)
  84                                 skbn->data[4] |= NR_MORE_FLAG;
  85                 
  86                         skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */
  87                 }
  88                 
  89                 skb->free = 1;
  90                 kfree_skb(skb, FREE_WRITE);
  91         } else {
  92                 skb_queue_tail(&sk->write_queue, skb);          /* Throw it on the queue */
  93         }
  94 
  95         if (sk->nr->state == NR_STATE_3)
  96                 nr_kick(sk);
  97 }
  98 
  99 /* 
 100  *      This procedure is passed a buffer descriptor for an iframe. It builds
 101  *      the rest of the control part of the frame and then writes it out.
 102  */
 103 static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         if (skb == NULL)
 106                 return;
 107 
 108         skb->data[2] = sk->nr->vs;
 109         skb->data[3] = sk->nr->vr;
 110 
 111         if (sk->nr->condition & OWN_RX_BUSY_CONDITION)
 112                 skb->data[4] |= NR_CHOKE_FLAG;
 113 
 114         nr_transmit_buffer(sk, skb);    
 115 }
 116 
 117 void nr_send_nak_frame(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         struct sk_buff *skb, *skbn;
 120         
 121         if ((skb = skb_peek(&sk->nr->ack_queue)) == NULL)
 122                 return;
 123                 
 124         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)
 125                 return;
 126 
 127         nr_send_iframe(sk, skbn);
 128 
 129         sk->nr->condition &= ~ACK_PENDING_CONDITION;
 130         sk->nr->vl      = sk->nr->vr;
 131         sk->nr->t1timer = 0;
 132 }
 133 
 134 void nr_kick(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         struct sk_buff *skb, *skbn;
 137         int last = 1;
 138         unsigned short start, end, next;
 139 
 140         del_timer(&sk->timer);
 141 
 142         start = (skb_peek(&sk->nr->ack_queue) == NULL) ? sk->nr->va : sk->nr->vs;
 143         end   = (sk->nr->va + sk->window) % NR_MODULUS;
 144 
 145         if (!(sk->nr->condition & PEER_RX_BUSY_CONDITION) &&
 146             start != end                                   &&
 147             skb_peek(&sk->write_queue) != NULL) {
 148 
 149                 sk->nr->vs = start;
 150 
 151                 /*
 152                  * Transmit data until either we're out of data to send or
 153                  * the window is full.
 154                  */
 155                 do {
 156                         /*
 157                          * Dequeue the frame and copy it.
 158                          */
 159                         skb  = skb_dequeue(&sk->write_queue);
 160 
 161                         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 162                                 skb_queue_head(&sk->write_queue, skb);
 163                                 return;
 164                         }
 165 
 166                         next = (sk->nr->vs + 1) % NR_MODULUS;
 167                         last = (next == end);
 168 
 169                         /*
 170                          * Transmit the frame copy.
 171                          */
 172                         nr_send_iframe(sk, skbn);
 173 
 174                         sk->nr->vs = next;
 175 
 176                         /*
 177                          * Requeue the original data frame.
 178                          */
 179                         skb_queue_tail(&sk->nr->ack_queue, skb);
 180 
 181                 } while (!last && skb_peek(&sk->write_queue) != NULL);
 182 
 183                 sk->nr->vl = sk->nr->vr;
 184                 sk->nr->condition &= ~ACK_PENDING_CONDITION;
 185 
 186                 if (sk->nr->t1timer == 0) {
 187                         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 188                 }
 189         }
 190 
 191         nr_set_timer(sk);
 192 }
 193 
 194 void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         unsigned char *dptr;
 197 
 198         /*
 199          *      Add the protocol byte and network header.
 200          */
 201         dptr = skb_push(skb, NR_NETWORK_LEN);
 202 
 203         memcpy(dptr, &sk->nr->source_addr, sizeof(ax25_address));
 204         dptr[6] &= ~LAPB_C;
 205         dptr[6] &= ~LAPB_E;
 206         dptr[6] |= SSSID_SPARE;
 207         dptr += AX25_ADDR_LEN;
 208 
 209         memcpy(dptr, &sk->nr->dest_addr,   sizeof(ax25_address));
 210         dptr[6] &= ~LAPB_C;
 211         dptr[6] |= LAPB_E;
 212         dptr[6] |= SSSID_SPARE;
 213         dptr += AX25_ADDR_LEN;
 214 
 215         *dptr++ = nr_default.ttl;
 216 
 217         skb->arp = 1;
 218 
 219         if (!nr_route_frame(skb, NULL)) {
 220                 kfree_skb(skb, FREE_WRITE);
 221 
 222                 sk->state = TCP_CLOSE;
 223                 sk->err   = ENETUNREACH;
 224                 if (!sk->dead)
 225                         sk->state_change(sk);
 226                 sk->dead  = 1;
 227         }
 228 }
 229 
 230 /*
 231  * The following routines are taken from page 170 of the 7th ARRL Computer
 232  * Networking Conference paper, as is the whole state machine.
 233  */
 234 
 235 void nr_nr_error_recovery(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         nr_establish_data_link(sk);
 238 }
 239 
 240 void nr_establish_data_link(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         sk->nr->condition = 0x00;
 243         sk->nr->n2count   = 0;
 244 
 245         nr_write_internal(sk, NR_CONNREQ);
 246 
 247         sk->nr->t2timer = 0;
 248         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 249 }
 250 
 251 /*
 252  * Never send a NAK when we are CHOKEd.
 253  */
 254 void nr_enquiry_response(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         int frametype = NR_INFOACK;
 257         
 258         if (sk->nr->condition & OWN_RX_BUSY_CONDITION) {
 259                 frametype |= NR_CHOKE_FLAG;
 260         } else {
 261                 if (skb_peek(&sk->nr->reseq_queue) != NULL) {
 262                         frametype |= NR_NAK_FLAG;
 263                 }
 264         }
 265         
 266         nr_write_internal(sk, frametype);
 267 
 268         sk->nr->vl = sk->nr->vr;
 269         sk->nr->condition &= ~ACK_PENDING_CONDITION;
 270 }
 271 
 272 void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 273 {
 274         if (sk->nr->vs == nr) {
 275                 nr_frames_acked(sk, nr);
 276                 nr_requeue_frames(sk);
 277                 nr_calculate_rtt(sk);
 278                 sk->nr->t1timer = 0;
 279                 sk->nr->n2count = 0;
 280         } else {
 281                 if (sk->nr->va != nr) {
 282                         nr_frames_acked(sk, nr);
 283                         nr_requeue_frames(sk);
 284                         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 285                 }
 286         }
 287 }
 288 
 289 #endif

/* [previous][next][first][last][top][bottom][index][help] */