root/net/ax25/ax25_out.c

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

DEFINITIONS

This source file includes following definitions.
  1. ax25_output
  2. ax25_send_iframe
  3. ax25_kick
  4. ax25_transmit_buffer
  5. ax25_nr_error_recovery
  6. ax25_establish_data_link
  7. ax25_transmit_enquiry
  8. ax25_enquiry_response
  9. ax25_timeout_response
  10. ax25_check_iframes_acked
  11. ax25_check_need_response
  12. dama_enquiry_response
  13. dama_check_need_response
  14. dama_establish_data_link

   1 /*
   2  *      AX.25 release 031
   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  *      Most of this code is based on the SDL diagrams published in the 7th
  16  *      ARRL Computer Networking Conference papers. The diagrams have mistakes
  17  *      in them, but are mostly correct. Before you modify the code could you
  18  *      read the SDL diagrams as the code is not obvious and probably very
  19  *      easy to break;
  20  *
  21  *      History
  22  *      AX.25 028a      Jonathan(G4KLX) New state machine based on SDL diagrams.
  23  *      AX.25 029       Alan(GW4PTS)    Switched to KA9Q constant names.
  24  *                      Jonathan(G4KLX) Only poll when window is full.
  25  *      AX.25 030       Jonathan(G4KLX) Added fragmentation to ax25_output.
  26  *                                      Added support for extended AX.25.
  27  *      AX.25 031       Joerg(DL1BKE)   Added DAMA support
  28  *
  29  *                      Joerg(DL1BKE)   Modified fragmenter to fragment vanilla 
  30  *                                      AX.25 I-Frames. Added PACLEN parameter.
  31  *                      Joerg(DL1BKE)   Fixed a problem with buffer allocation
  32  *                                      for fragments.
  33  */
  34 
  35 #include <linux/config.h>
  36 #ifdef CONFIG_AX25
  37 #include <linux/errno.h>
  38 #include <linux/types.h>
  39 #include <linux/socket.h>
  40 #include <linux/in.h>
  41 #include <linux/kernel.h>
  42 #include <linux/sched.h>
  43 #include <linux/timer.h>
  44 #include <linux/string.h>
  45 #include <linux/sockios.h>
  46 #include <linux/net.h>
  47 #include <net/ax25.h>
  48 #include <linux/inet.h>
  49 #include <linux/netdevice.h>
  50 #include <linux/skbuff.h>
  51 #include <net/sock.h>
  52 #include <asm/segment.h>
  53 #include <asm/system.h>
  54 #include <linux/fcntl.h>
  55 #include <linux/mm.h>
  56 #include <linux/interrupt.h>
  57 
  58 /*
  59  * All outgoing AX.25 I frames pass via this routine. Therefore this is
  60  * where the fragmentation of frames takes place.
  61  */
  62 void ax25_output(ax25_cb *ax25, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         struct sk_buff *skbn;
  65         unsigned char *p;
  66         int frontlen, mtu, len, fragno, ka9qfrag, first = 1;
  67         long flags;
  68         
  69         /*
  70          * dl1bke 960301: We use the new PACLEN parameter as MTU of the AX.25 layer.
  71          *                This will (hopefully) allow user programs to write() data
  72          *                w/o having to think of the maximal amount of data we can
  73          *                send with one call. It's called PACLEN to (1) avoid confusion
  74          *                with (IP) MTU and (2) TAPR calls this PACLEN, too ;-)
  75          */
  76 
  77         mtu = ax25->paclen;
  78         
  79         if ((skb->len - 1) > mtu) {
  80                 if (*skb->data == AX25_P_TEXT) {
  81                         skb_pull(skb, 1); /* skip PID */
  82                         ka9qfrag = 0;
  83                 } else {
  84                         mtu -= 2;       /* Allow for fragment control info */
  85                         ka9qfrag = 1;
  86                 }
  87                 
  88                 fragno = skb->len / mtu;
  89                 if (skb->len % mtu == 0) fragno--;
  90 
  91                 frontlen = skb_headroom(skb);   /* Address space + CTRL */
  92 
  93                 while (skb->len > 0) {
  94                         save_flags(flags); 
  95                         cli();
  96                         /* 
  97                          * do _not_ use sock_alloc_send_skb, our socket may have
  98                          * sk->shutdown set...
  99                          */
 100                         if ((skbn = alloc_skb(mtu + 2 + frontlen, GFP_ATOMIC)) == NULL) {
 101                                 restore_flags(flags);
 102                                 printk("ax25_output: alloc_skb returned NULL\n");
 103                                 if (skb_device_locked(skb))
 104                                         skb_device_unlock(skb);
 105                                 return;
 106                         }
 107 
 108                         skbn->sk   = skb->sk;
 109                         
 110                         if (skbn->sk)
 111                                 atomic_add(skbn->truesize, &skbn->sk->wmem_alloc);
 112                         
 113                         restore_flags(flags);
 114                         
 115                         skbn->free = 1;
 116                         skbn->arp  = 1;
 117 
 118                         len = (mtu > skb->len) ? skb->len : mtu;
 119                         
 120                         if (ka9qfrag == 1) {
 121                                 skb_reserve(skbn, frontlen + 2);
 122 
 123                                 memcpy(skb_put(skbn, len), skb->data, len);
 124                                 p = skb_push(skbn, 2);
 125 
 126                                 *p++ = AX25_P_SEGMENT;
 127 
 128                                 *p = fragno--;
 129                                 if (first) {
 130                                         *p |= SEG_FIRST;
 131                                         first = 0;
 132                                 }
 133                         } else {
 134                                 skb_reserve(skbn, frontlen + 1);
 135                                 memcpy(skb_put(skbn, len), skb->data, len);
 136                                 p = skb_push(skbn, 1);
 137                                 *p = AX25_P_TEXT;
 138                         }
 139 
 140                         skb_pull(skb, len);
 141                         skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */
 142                 }
 143                 
 144                 skb->free = 1;
 145                 kfree_skb(skb, FREE_WRITE);
 146         } else {
 147                 skb_queue_tail(&ax25->write_queue, skb);          /* Throw it on the queue */
 148         }
 149 
 150         if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
 151                 if (!ax25->dama_slave)          /* bke 960114: we aren't allowed to transmit */
 152                         ax25_kick(ax25);        /* in DAMA mode unless we received a Poll */
 153         }
 154 }
 155 
 156 /* 
 157  *  This procedure is passed a buffer descriptor for an iframe. It builds
 158  *  the rest of the control part of the frame and then writes it out.
 159  */
 160 static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         unsigned char *frame;
 163 
 164         if (skb == NULL)
 165                 return;
 166 
 167         if (ax25->modulus == MODULUS) {
 168                 frame = skb_push(skb, 1);
 169 
 170                 *frame = I;
 171                 *frame |= (poll_bit) ? PF : 0;
 172                 *frame |= (ax25->vr << 5);
 173                 *frame |= (ax25->vs << 1);
 174         } else {
 175                 frame = skb_push(skb, 2);
 176 
 177                 frame[0] = I;
 178                 frame[0] |= (ax25->vs << 1);
 179                 frame[1] = (poll_bit) ? EPF : 0;
 180                 frame[1] |= (ax25->vr << 1);
 181         }
 182 
 183         ax25_transmit_buffer(ax25, skb, C_COMMAND);     
 184 }
 185 
 186 void ax25_kick(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         struct sk_buff *skb, *skbn;
 189         int last = 1;
 190         unsigned short start, end, next;
 191 
 192         del_timer(&ax25->timer);
 193 
 194         start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
 195         end   = (ax25->va + ax25->window) % ax25->modulus;
 196 
 197         if (!(ax25->condition & PEER_RX_BUSY_CONDITION) &&
 198             start != end                                   &&
 199             skb_peek(&ax25->write_queue) != NULL) {
 200 
 201                 ax25->vs = start;
 202 
 203                 /*
 204                  * Transmit data until either we're out of data to send or
 205                  * the window is full. Send a poll on the final I frame if
 206                  * the window is filled.
 207                  */
 208 
 209                 /*
 210                  * Dequeue the frame and copy it.
 211                  */
 212                 skb  = skb_dequeue(&ax25->write_queue);
 213 
 214                 do {
 215                         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 216                                 skb_queue_head(&ax25->write_queue, skb);
 217                                 return;
 218                         }
 219 
 220                         next = (ax25->vs + 1) % ax25->modulus;
 221 #ifdef notdef
 222                         last = (next == end) || skb_peek(&ax25->write_queue) == NULL;
 223 #else
 224                         last = (next == end);
 225 #endif
 226                         /*
 227                          * Transmit the frame copy.
 228                          * bke 960114: do not set the Poll bit on the last frame
 229                          * in DAMA mode.
 230                          */
 231                         ax25_send_iframe(ax25, skbn, (last && !ax25->dama_slave) ? POLLON : POLLOFF);
 232 
 233                         ax25->vs = next;
 234 
 235                         /*
 236                          * Requeue the original data frame.
 237                          */
 238                         skb_queue_tail(&ax25->ack_queue, skb);
 239 #ifdef notdef
 240                 } while (!last);
 241 #else
 242                 } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
 243 #endif
 244                 ax25->condition &= ~ACK_PENDING_CONDITION;
 245 
 246                 if (ax25->t1timer == 0) {
 247                         ax25->t3timer = 0;
 248                         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 249                 }
 250         }
 251 
 252         ax25_set_timer(ax25);
 253 }
 254 
 255 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257         unsigned char *ptr;
 258 
 259         if (ax25->device == NULL) {
 260                 if (ax25->sk != NULL) {
 261                         ax25->sk->state = TCP_CLOSE;
 262                         ax25->sk->err   = ENETUNREACH;
 263                         if (!ax25->sk->dead)
 264                                 ax25->sk->state_change(ax25->sk);
 265                         ax25->sk->dead  = 1;
 266                 }
 267                 return;
 268         }
 269 
 270         if (skb_headroom(skb) < size_ax25_addr(ax25->digipeat)) {
 271                 printk("ax25_transmit_buffer: not enough room for digi-peaters\n");
 272                 skb->free = 1;
 273                 kfree_skb(skb, FREE_WRITE);
 274                 return;
 275         }
 276 
 277         ptr = skb_push(skb, size_ax25_addr(ax25->digipeat));
 278         build_ax25_addr(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
 279 
 280         skb->arp = 1;
 281 
 282         ax25_queue_xmit(skb, ax25->device, SOPRI_NORMAL);
 283 }
 284 
 285 /*
 286  * The following routines are taken from page 170 of the 7th ARRL Computer
 287  * Networking Conference paper, as is the whole state machine.
 288  */
 289 
 290 void ax25_nr_error_recovery(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {
 292         ax25_establish_data_link(ax25);
 293 }
 294 
 295 void ax25_establish_data_link(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         ax25->condition = 0x00;
 298         ax25->n2count   = 0;
 299 
 300         if (ax25->modulus == MODULUS) {
 301                 ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
 302         } else {
 303                 ax25_send_control(ax25, SABME, POLLON, C_COMMAND);
 304         }
 305         
 306         ax25->t3timer = 0;
 307         ax25->t2timer = 0;
 308         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 309 }
 310 
 311 void ax25_transmit_enquiry(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         if (ax25->condition & OWN_RX_BUSY_CONDITION)
 314                 ax25_send_control(ax25, RNR, POLLON, C_COMMAND);
 315         else
 316                 ax25_send_control(ax25, RR, POLLON, C_COMMAND);
 317 
 318         ax25->condition &= ~ACK_PENDING_CONDITION;
 319 
 320         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 321 }
 322         
 323 void ax25_enquiry_response(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 324 {
 325         if (ax25->condition & OWN_RX_BUSY_CONDITION)
 326                 ax25_send_control(ax25, RNR, POLLON, C_RESPONSE);
 327         else
 328                 ax25_send_control(ax25, RR, POLLON, C_RESPONSE);
 329 
 330         ax25->condition &= ~ACK_PENDING_CONDITION;
 331 }
 332 
 333 void ax25_timeout_response(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 334 {
 335         if (ax25->condition & OWN_RX_BUSY_CONDITION)
 336                 ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE);
 337         else
 338                 ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
 339 
 340         ax25->condition &= ~ACK_PENDING_CONDITION;
 341 }
 342 
 343 void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 344 {
 345         if (ax25->vs == nr) {
 346                 ax25_frames_acked(ax25, nr);
 347                 ax25_calculate_rtt(ax25);
 348                 ax25->t1timer = 0;
 349                 ax25->t3timer = ax25->t3;
 350         } else {
 351                 if (ax25->va != nr) {
 352                         ax25_frames_acked(ax25, nr);
 353                         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 354                 }
 355         }
 356 }
 357 
 358 /*
 359  *      dl1bke 960114: shouldn't ax25/dama_check_need_response reside as
 360  *                static inline void ...() in ax25.h, should it? ;-)
 361  */
 362 void ax25_check_need_response(ax25_cb *ax25, int type, int pf)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364         if (!ax25->dama_slave && type == C_COMMAND && pf)
 365                 ax25_enquiry_response(ax25);
 366 }
 367 
 368 /*
 369  *      dl1bke 960114: transmit I frames on DAMA poll
 370  */
 371 void dama_enquiry_response(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 372 {
 373         ax25_cb *ax25o;
 374         
 375         if (!(ax25->condition & PEER_RX_BUSY_CONDITION)) {
 376                 ax25_requeue_frames(ax25);
 377                 ax25_kick(ax25);
 378         }
 379 
 380         if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 ||
 381             skb_peek(&ax25->ack_queue) != NULL) {
 382                 ax25_t1_timeout(ax25);
 383         } else {
 384                 ax25->n2count = 0;
 385         }
 386         
 387         ax25->t3timer = ax25->t3;
 388         
 389 
 390         /* The FLEXNET DAMA master implementation refuses to send us ANY */
 391         /* I frame for this connection if we send a REJ here, probably   */
 392         /* due to it's frame collector scheme? A simple RR or  RNR will  */
 393         /* invoke the retransmission, and in fact REJs are superfluous   */
 394         /* in DAMA mode anyway...                                        */
 395         
 396 #if 0
 397         if (ax25->condition & REJECT_CONDITION)
 398                 ax25_send_control(ax25, REJ, POLLOFF, C_RESPONSE);
 399         else
 400 #endif  
 401                 ax25_enquiry_response(ax25);
 402                 
 403         /* Note that above response to the poll could be sent behind the  */
 404         /* transmissions of the other channels as well... This version    */    
 405         /* gives better performance on FLEXNET nodes. (Why, Gunter?)      */
 406 
 407         for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
 408                 if (ax25o->device != ax25->device)
 409                         continue;
 410 
 411                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2) {
 412                         ax25_t1_timeout(ax25o);
 413                         continue;
 414                 }
 415 
 416                 if (!ax25o->dama_slave)
 417                         continue;
 418                         
 419                 if ( !(ax25o->condition & PEER_RX_BUSY_CONDITION) && 
 420                      (ax25o->state == AX25_STATE_3 || 
 421                      (ax25o->state == AX25_STATE_4 && ax25o->t1timer == 0))) {
 422                         ax25_requeue_frames(ax25o);
 423                         ax25_kick(ax25o);
 424                 }
 425                 
 426                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 ||
 427                     skb_peek(&ax25o->ack_queue) != NULL) {
 428                         ax25_t1_timeout(ax25o);
 429                 }
 430 
 431                 ax25o->t3timer = ax25o->t3;
 432         }
 433 }
 434 
 435 void dama_check_need_response(ax25_cb *ax25, int type, int pf)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437         if (ax25->dama_slave && type == C_COMMAND && pf)
 438                 dama_enquiry_response(ax25);
 439 }
 440 
 441 void dama_establish_data_link(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 442 {
 443         ax25->condition = 0x00;
 444         ax25->n2count   = 0;
 445 
 446         ax25->t3timer = ax25->t3;
 447         ax25->t2timer = 0;
 448         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 449 }
 450 
 451 #endif

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