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

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