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                 switch (*skb->data) {
  81                         case AX25_P_SEGMENT:
  82                                 /* this is an error, but... */
  83                                 printk("ax25_output(): woops, fragmentation of fragment?!\n");
  84                                 /* okay, let's fragment it further (tss, tss...) */
  85                         case AX25_P_NETROM:     /* err, is this a good idea? */
  86                         case AX25_P_IP:
  87                                 mtu -= 2;       /* Allow for fragment control info */
  88                                 ka9qfrag = 1;
  89                                 break;
  90                         default:
  91                                 ka9qfrag = 0;
  92                                 skb_pull(skb, 1); /* skip PID */
  93                                 break;
  94 
  95                 }
  96                 
  97                 fragno = skb->len / mtu;
  98                 if (skb->len % mtu == 0) fragno--;
  99 
 100                 frontlen = skb_headroom(skb);   /* Address space + CTRL */
 101 
 102                 while (skb->len > 0) {
 103                         save_flags(flags); 
 104                         cli();
 105                         /* 
 106                          * do _not_ use sock_alloc_send_skb, our socket may have
 107                          * sk->shutdown set...
 108                          *
 109                          */
 110                         if ((skbn = alloc_skb(mtu + 2 + frontlen, GFP_ATOMIC)) == NULL) {
 111                                 restore_flags(flags);
 112                                 printk("ax25_output(): alloc_skb returned NULL\n");
 113                                 if (skb_device_locked(skb))
 114                                         skb_device_unlock(skb);
 115                                 return;
 116                         }
 117 
 118                         skbn->sk   = skb->sk;
 119                         
 120                         if (skbn->sk)
 121                                 atomic_add(skbn->truesize, &skbn->sk->wmem_alloc);
 122                         
 123                         restore_flags(flags);
 124                         
 125                         skbn->free = 1;
 126                         skbn->arp  = 1;
 127 
 128                         len = (mtu > skb->len) ? skb->len : mtu;
 129                         
 130                         if (ka9qfrag == 1) {
 131                                 skb_reserve(skbn, frontlen + 2);
 132 
 133                                 memcpy(skb_put(skbn, len), skb->data, len);
 134                                 p = skb_push(skbn, 2);
 135 
 136                                 *p++ = AX25_P_SEGMENT;
 137 
 138                                 *p = fragno--;
 139                                 if (first) {
 140                                         *p |= SEG_FIRST;
 141                                         first = 0;
 142                                 }
 143                         } else {
 144                                 skb_reserve(skbn, frontlen + 1);
 145                                 memcpy(skb_put(skbn, len), skb->data, len);
 146                                 p = skb_push(skbn, 1);
 147                                 *p = AX25_P_TEXT;
 148                         }
 149 
 150                         skb_pull(skb, len);
 151                         skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */
 152                 }
 153                 
 154                 skb->free = 1;
 155                 kfree_skb(skb, FREE_WRITE);
 156         } else {
 157                 skb_queue_tail(&ax25->write_queue, skb);          /* Throw it on the queue */
 158         }
 159 
 160         if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
 161                 if (!ax25->dama_slave)          /* bke 960114: we aren't allowed to transmit */
 162                         ax25_kick(ax25);        /* in DAMA mode unless we received a Poll */
 163         }
 164 }
 165 
 166 /* 
 167  *  This procedure is passed a buffer descriptor for an iframe. It builds
 168  *  the rest of the control part of the frame and then writes it out.
 169  */
 170 static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         unsigned char *frame;
 173 
 174         if (skb == NULL)
 175                 return;
 176 
 177         if (ax25->modulus == MODULUS) {
 178                 frame = skb_push(skb, 1);
 179 
 180                 *frame = I;
 181                 *frame |= (poll_bit) ? PF : 0;
 182                 *frame |= (ax25->vr << 5);
 183                 *frame |= (ax25->vs << 1);
 184         } else {
 185                 frame = skb_push(skb, 2);
 186 
 187                 frame[0] = I;
 188                 frame[0] |= (ax25->vs << 1);
 189                 frame[1] = (poll_bit) ? EPF : 0;
 190                 frame[1] |= (ax25->vr << 1);
 191         }
 192 
 193         ax25_transmit_buffer(ax25, skb, C_COMMAND);     
 194 }
 195 
 196 void ax25_kick(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 197 {
 198         struct sk_buff *skb, *skbn;
 199         int last = 1;
 200         unsigned short start, end, next;
 201 
 202         del_timer(&ax25->timer);
 203 
 204         start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
 205         end   = (ax25->va + ax25->window) % ax25->modulus;
 206 
 207         if (!(ax25->condition & PEER_RX_BUSY_CONDITION) &&
 208             start != end                                   &&
 209             skb_peek(&ax25->write_queue) != NULL) {
 210 
 211                 ax25->vs = start;
 212 
 213                 /*
 214                  * Transmit data until either we're out of data to send or
 215                  * the window is full. Send a poll on the final I frame if
 216                  * the window is filled.
 217                  */
 218 
 219                 /*
 220                  * Dequeue the frame and copy it.
 221                  */
 222                 skb  = skb_dequeue(&ax25->write_queue);
 223 
 224                 do {
 225                         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 226                                 skb_queue_head(&ax25->write_queue, skb);
 227                                 return;
 228                         }
 229 
 230                         next = (ax25->vs + 1) % ax25->modulus;
 231 #ifdef notdef
 232                         last = (next == end) || skb_peek(&ax25->write_queue) == NULL;
 233 #else
 234                         last = (next == end);
 235 #endif
 236                         /*
 237                          * Transmit the frame copy.
 238                          * bke 960114: do not set the Poll bit on the last frame
 239                          * in DAMA mode.
 240                          */
 241                         ax25_send_iframe(ax25, skbn, (last && !ax25->dama_slave) ? POLLON : POLLOFF);
 242 
 243                         ax25->vs = next;
 244 
 245                         /*
 246                          * Requeue the original data frame.
 247                          */
 248                         skb_queue_tail(&ax25->ack_queue, skb);
 249 #ifdef notdef
 250                 } while (!last);
 251 #else
 252                 } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
 253 #endif
 254                 ax25->condition &= ~ACK_PENDING_CONDITION;
 255 
 256                 if (ax25->t1timer == 0) {
 257                         ax25->t3timer = 0;
 258                         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 259                 }
 260         }
 261 
 262         ax25_set_timer(ax25);
 263 }
 264 
 265 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
     /* [previous][next][first][last][top][bottom][index][help] */
 266 {
 267         unsigned char *ptr;
 268 
 269         if (ax25->device == NULL) {
 270                 if (ax25->sk != NULL) {
 271                         ax25->sk->state = TCP_CLOSE;
 272                         ax25->sk->err   = ENETUNREACH;
 273                         if (!ax25->sk->dead)
 274                                 ax25->sk->state_change(ax25->sk);
 275                         ax25->sk->dead  = 1;
 276                 }
 277                 return;
 278         }
 279 
 280         if (skb_headroom(skb) < size_ax25_addr(ax25->digipeat)) {
 281                 printk("ax25_transmit_buffer: not enough room for digi-peaters\n");
 282                 skb->free = 1;
 283                 kfree_skb(skb, FREE_WRITE);
 284                 return;
 285         }
 286 
 287         ptr = skb_push(skb, size_ax25_addr(ax25->digipeat));
 288         build_ax25_addr(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
 289 
 290         skb->arp = 1;
 291 
 292         ax25_queue_xmit(skb, ax25->device, SOPRI_NORMAL);
 293 }
 294 
 295 /*
 296  * The following routines are taken from page 170 of the 7th ARRL Computer
 297  * Networking Conference paper, as is the whole state machine.
 298  */
 299 
 300 void ax25_nr_error_recovery(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 301 {
 302         ax25_establish_data_link(ax25);
 303 }
 304 
 305 void ax25_establish_data_link(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307         ax25->condition = 0x00;
 308         ax25->n2count   = 0;
 309 
 310         if (ax25->modulus == MODULUS) {
 311                 ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
 312         } else {
 313                 ax25_send_control(ax25, SABME, POLLON, C_COMMAND);
 314         }
 315         
 316         ax25->t3timer = 0;
 317         ax25->t2timer = 0;
 318         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 319 }
 320 
 321 void ax25_transmit_enquiry(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323         if (ax25->condition & OWN_RX_BUSY_CONDITION)
 324                 ax25_send_control(ax25, RNR, POLLON, C_COMMAND);
 325         else
 326                 ax25_send_control(ax25, RR, POLLON, C_COMMAND);
 327 
 328         ax25->condition &= ~ACK_PENDING_CONDITION;
 329 
 330         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 331 }
 332         
 333 void ax25_enquiry_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, POLLON, C_RESPONSE);
 337         else
 338                 ax25_send_control(ax25, RR, POLLON, C_RESPONSE);
 339 
 340         ax25->condition &= ~ACK_PENDING_CONDITION;
 341 }
 342 
 343 void ax25_timeout_response(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 344 {
 345         if (ax25->condition & OWN_RX_BUSY_CONDITION)
 346                 ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE);
 347         else
 348                 ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
 349 
 350         ax25->condition &= ~ACK_PENDING_CONDITION;
 351 }
 352 
 353 void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 354 {
 355         if (ax25->vs == nr) {
 356                 ax25_frames_acked(ax25, nr);
 357                 ax25_calculate_rtt(ax25);
 358                 ax25->t1timer = 0;
 359                 ax25->t3timer = ax25->t3;
 360         } else {
 361                 if (ax25->va != nr) {
 362                         ax25_frames_acked(ax25, nr);
 363                         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 364                 }
 365         }
 366 }
 367 
 368 /*
 369  *      dl1bke 960114: shouldn't ax25/dama_check_need_response reside as
 370  *                static inline void ...() in ax25.h, should it? ;-)
 371  */
 372 void ax25_check_need_response(ax25_cb *ax25, int type, int pf)
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374         if (!ax25->dama_slave && type == C_COMMAND && pf)
 375                 ax25_enquiry_response(ax25);
 376 }
 377 
 378 /*
 379  *      dl1bke 960114: transmit I frames on DAMA poll
 380  */
 381 void dama_enquiry_response(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 382 {
 383         ax25_cb *ax25o;
 384         
 385         if (!(ax25->condition & PEER_RX_BUSY_CONDITION)) {
 386                 ax25_requeue_frames(ax25);
 387                 ax25_kick(ax25);
 388         }
 389 
 390         if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 ||
 391             skb_peek(&ax25->ack_queue) != NULL) {
 392                 ax25_t1_timeout(ax25);
 393         } else {
 394                 ax25->n2count = 0;
 395         }
 396         
 397         ax25->t3timer = ax25->t3;
 398         
 399 
 400         /* The FLEXNET DAMA master implementation refuses to send us ANY */
 401         /* I frame for this connection if we send a REJ here, probably   */
 402         /* due to it's frame collector scheme? A simple RR or  RNR will  */
 403         /* invoke the retransmission, and in fact REJs are superfluous   */
 404         /* in DAMA mode anyway...                                        */
 405         
 406 #if 0
 407         if (ax25->condition & REJECT_CONDITION)
 408                 ax25_send_control(ax25, REJ, POLLOFF, C_RESPONSE);
 409         else
 410 #endif  
 411                 ax25_enquiry_response(ax25);
 412                 
 413         /* Note that above response to the poll could be sent behind the  */
 414         /* transmissions of the other channels as well... This version    */    
 415         /* gives better performance on FLEXNET nodes. (Why, Gunter?)      */
 416 
 417         for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
 418                 if (ax25o->device != ax25->device)
 419                         continue;
 420 
 421                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2) {
 422                         ax25_t1_timeout(ax25o);
 423                         continue;
 424                 }
 425 
 426                 if (!ax25o->dama_slave)
 427                         continue;
 428                         
 429                 if ( !(ax25o->condition & PEER_RX_BUSY_CONDITION) && 
 430                      (ax25o->state == AX25_STATE_3 || 
 431                      (ax25o->state == AX25_STATE_4 && ax25o->t1timer == 0))) {
 432                         ax25_requeue_frames(ax25o);
 433                         ax25_kick(ax25o);
 434                 }
 435                 
 436                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 ||
 437                     skb_peek(&ax25o->ack_queue) != NULL) {
 438                         ax25_t1_timeout(ax25o);
 439                 }
 440 
 441                 ax25o->t3timer = ax25o->t3;
 442         }
 443 }
 444 
 445 void dama_check_need_response(ax25_cb *ax25, int type, int pf)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447         if (ax25->dama_slave && type == C_COMMAND && pf)
 448                 dama_enquiry_response(ax25);
 449 }
 450 
 451 void dama_establish_data_link(ax25_cb *ax25)
     /* [previous][next][first][last][top][bottom][index][help] */
 452 {
 453         ax25->condition = 0x00;
 454         ax25->n2count   = 0;
 455 
 456         ax25->t3timer = ax25->t3;
 457         ax25->t2timer = 0;
 458         ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
 459 }
 460 
 461 #endif

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