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

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