root/net/netrom/nr_subr.c

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

DEFINITIONS

This source file includes following definitions.
  1. nr_clear_tx_queue
  2. nr_frames_acked
  3. nr_requeue_frames
  4. nr_validate_nr
  5. nr_in_rx_window
  6. nr_write_internal
  7. nr_transmit_dm
  8. nr_calculate_t1
  9. nr_calculate_rtt

   1 /*
   2  *      NET/ROM release 002
   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_subr.c
  17  */
  18  
  19 #include <linux/config.h>
  20 #ifdef CONFIG_NETROM
  21 #include <linux/errno.h>
  22 #include <linux/types.h>
  23 #include <linux/socket.h>
  24 #include <linux/in.h>
  25 #include <linux/kernel.h>
  26 #include <linux/sched.h>
  27 #include <linux/timer.h>
  28 #include <linux/string.h>
  29 #include <linux/sockios.h>
  30 #include <linux/net.h>
  31 #include <net/ax25.h>
  32 #include <linux/inet.h>
  33 #include <linux/netdevice.h>
  34 #include <linux/skbuff.h>
  35 #include <net/sock.h>
  36 #include <asm/segment.h>
  37 #include <asm/system.h>
  38 #include <linux/fcntl.h>
  39 #include <linux/mm.h>
  40 #include <linux/interrupt.h>
  41 #include <net/netrom.h>
  42 
  43 /*
  44  * This routine purges the input queue of frames.
  45  */
  46 void nr_clear_tx_queue(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         struct sk_buff *skb;
  49 
  50         while ((skb = skb_dequeue(&sk->write_queue)) != NULL) {
  51                 skb->sk   = sk;
  52                 skb->free = 1;
  53                 kfree_skb(skb, FREE_WRITE);
  54         }
  55 
  56         while ((skb = skb_dequeue(&sk->nr->ack_queue)) != NULL) {
  57                 skb->sk   = sk;
  58                 skb->free = 1;
  59                 kfree_skb(skb, FREE_WRITE);
  60         }
  61 
  62         while ((skb = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
  63                 skb->free = 1;
  64                 kfree_skb(skb, FREE_READ);
  65         }
  66 }
  67 
  68 /*
  69  * This routine purges the input queue of those frames that have been
  70  * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
  71  * SDL diagram.
  72  */
  73 void nr_frames_acked(struct sock *sk, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75         struct sk_buff *skb;
  76 
  77         /*
  78          * Remove all the ack-ed frames from the ack queue.
  79          */
  80         if (sk->nr->va != nr) {
  81                 while (skb_peek(&sk->nr->ack_queue) != NULL && sk->nr->va != nr) {
  82                         skb = skb_dequeue(&sk->nr->ack_queue);
  83                         skb->sk   = sk;
  84                         skb->free = 1;
  85                         kfree_skb(skb, FREE_WRITE);
  86                         sk->nr->va = (sk->nr->va + 1) % NR_MODULUS;
  87                 }
  88         }
  89 }
  90 
  91 /*
  92  * Requeue all the un-ack-ed frames on the output queue to be picked
  93  * up by nr_kick called from the timer. This arrangement handles the
  94  * possibility of an empty output queue.
  95  */
  96 void nr_requeue_frames(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         struct sk_buff *skb, *skb_prev = NULL;
  99 
 100         while ((skb = skb_dequeue(&sk->nr->ack_queue)) != NULL) {
 101                 if (skb_prev == NULL)
 102                         skb_queue_head(&sk->write_queue, skb);
 103                 else
 104                         skb_append(skb_prev, skb);
 105                 skb_prev = skb;
 106         }
 107 }
 108 
 109 /*
 110  *      Validate that the value of nr is between va and vs. Return true or
 111  *      false for testing.
 112  */
 113 int nr_validate_nr(struct sock *sk, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         unsigned short vc = sk->nr->va;
 116 
 117         while (vc != sk->nr->vs) {
 118                 if (nr == vc) return 1;
 119                 vc = (vc + 1) % NR_MODULUS;
 120         }
 121         
 122         if (nr == sk->nr->vs) return 1;
 123 
 124         return 0;
 125 }
 126 
 127 /*
 128  *      Check that ns is within the receive window.
 129  */
 130 int nr_in_rx_window(struct sock *sk, unsigned short ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         unsigned short vc = sk->nr->vl;
 133         unsigned short vt = (sk->nr->vl + sk->window) % NR_MODULUS;
 134 
 135         while (vc != vt) {
 136                 if (ns == vc) return 1;
 137                 vc = (vc + 1) % NR_MODULUS;
 138         }
 139         
 140         if (ns == vt) return 1;
 141 
 142         return 0;
 143 }
 144 
 145 /* 
 146  *  This routine is called when the HDLC layer internally generates a
 147  *  control frame.
 148  */
 149 void nr_write_internal(struct sock *sk, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         struct sk_buff *skb;
 152         unsigned char  *dptr;
 153         int len;
 154         
 155         switch (frametype & 0x0F) {
 156                 case NR_CONNREQ: len = 52; break;
 157                 case NR_CONNACK: len = 38; break;
 158                 case NR_DISCREQ: len = 37; break;
 159                 case NR_DISCACK: len = 37; break;
 160                 case NR_INFOACK: len = 37; break;
 161                 default:
 162                         printk("nr_write_internal: invalid frame type %d\n", frametype);
 163                         return;
 164         }
 165         
 166         if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
 167                 return;
 168 
 169         dptr = skb->data + 32;
 170 
 171         switch (frametype & 0x0F) {
 172 
 173                 case NR_CONNREQ:
 174                         *dptr++ = sk->nr->my_index;
 175                         *dptr++ = sk->nr->my_id;
 176                         *dptr++ = 0;
 177                         *dptr++ = 0;
 178                         *dptr++ = frametype;
 179                         *dptr++ = sk->window;
 180                         memcpy(dptr, &sk->nr->user_addr, sizeof(ax25_address));
 181                         dptr[6] &= ~LAPB_C;
 182                         dptr[6] &= ~LAPB_E;
 183                         dptr[6] |= SSID_SPARE;
 184                         dptr += 7;
 185                         memcpy(dptr, &sk->nr->source_addr, sizeof(ax25_address));
 186                         dptr[6] &= ~LAPB_C;
 187                         dptr[6] &= ~LAPB_E;
 188                         dptr[6] |= SSID_SPARE;
 189                         break;
 190 
 191                 case NR_CONNACK:
 192                         *dptr++ = sk->nr->your_index;
 193                         *dptr++ = sk->nr->your_id;
 194                         *dptr++ = sk->nr->my_index;
 195                         *dptr++ = sk->nr->my_id;
 196                         *dptr++ = frametype;
 197                         *dptr++ = sk->window;
 198                         break;
 199 
 200                 case NR_DISCREQ:
 201                 case NR_DISCACK:
 202                         *dptr++ = sk->nr->your_index;
 203                         *dptr++ = sk->nr->your_id;
 204                         *dptr++ = 0;
 205                         *dptr++ = 0;
 206                         *dptr++ = frametype;
 207                         break;
 208 
 209                 case NR_INFOACK:
 210                         *dptr++ = sk->nr->your_index;
 211                         *dptr++ = sk->nr->your_id;
 212                         *dptr++ = 0;
 213                         *dptr++ = sk->nr->vr;
 214                         *dptr++ = frametype;
 215                         break;
 216         }
 217 
 218         skb->free = 1;
 219         skb->len  = len;
 220 
 221         nr_transmit_buffer(sk, skb);
 222 }
 223 
 224 /*
 225  * This routine is called when a Connect Acknowledge with the Choke Flag
 226  * set is needed to refuse a connection.
 227  */
 228 void nr_transmit_dm(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230         struct sk_buff *skbn;
 231         unsigned char *dptr;
 232 
 233         if ((skbn = alloc_skb(38, GFP_ATOMIC)) == NULL)
 234                 return;
 235 
 236         dptr = skbn->data + 16;
 237 
 238         *dptr++ = AX25_P_NETROM;
 239         
 240         memcpy(dptr, skb->data + 24, 7);
 241         dptr[6] &= ~LAPB_C;
 242         dptr[6] &= ~LAPB_E;
 243         dptr[6] |= SSID_SPARE;
 244         dptr += 7;
 245         
 246         memcpy(dptr, skb->data + 17, 7);
 247         dptr[6] &= ~LAPB_C;
 248         dptr[6] |= LAPB_E;
 249         dptr[6] |= SSID_SPARE;
 250         dptr += 7;
 251 
 252         *dptr++ = nr_default.ttl;
 253 
 254         *dptr++ = skb->data[32];
 255         *dptr++ = skb->data[33];
 256         *dptr++ = 0;
 257         *dptr++ = 0;
 258         *dptr++ = NR_CONNACK + NR_CHOKE_FLAG;
 259         *dptr++ = 0;
 260 
 261         skbn->free = 1;
 262         skbn->len  = 38;
 263         skbn->sk   = NULL;
 264 
 265         if (!nr_route_frame(skbn, NULL))
 266                 kfree_skb(skbn, FREE_WRITE);
 267 }
 268 
 269 /*
 270  *      Exponential backoff for NET/ROM
 271  */
 272 unsigned short nr_calculate_t1(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 273 {
 274         int n, t;
 275         
 276         for (t = 2, n = 0; n < sk->nr->n2count; n++)
 277                 t *= 2;
 278 
 279         return t * sk->nr->rtt;
 280 }
 281 
 282 /*
 283  *      Calculate the Round Trip Time
 284  */
 285 void nr_calculate_rtt(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         if (sk->nr->n2count == 0)
 288                 sk->nr->rtt = (9 * sk->nr->rtt + sk->nr->t1 - sk->nr->t1timer) / 10;
 289 
 290         /* Don't go below one second */
 291         if (sk->nr->rtt < 1 * PR_SLOWHZ)
 292                 sk->nr->rtt = 1 * PR_SLOWHZ;
 293 }
 294 
 295 #endif

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