root/net/netrom/nr_out.c

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

DEFINITIONS

This source file includes following definitions.
  1. nr_output
  2. nr_send_iframe
  3. nr_send_nak_frame
  4. nr_kick
  5. nr_transmit_buffer
  6. nr_nr_error_recovery
  7. nr_establish_data_link
  8. nr_enquiry_response
  9. nr_check_iframes_acked

   1 /*
   2  *      NET/ROM release 003
   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_out.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 int nr_output(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         skb_queue_tail(&sk->write_queue, skb);  /* Throw it on the queue */
  46 
  47         if (sk->nr->state == NR_STATE_3)
  48                 nr_kick(sk);
  49 
  50         return 0;
  51 }
  52 
  53 /* 
  54  *  This procedure is passed a buffer descriptor for an iframe. It builds
  55  *  the rest of the control part of the frame and then writes it out.
  56  */
  57 static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         if (skb == NULL)
  60                 return;
  61 
  62         skb->data[2] = sk->nr->vs;
  63         skb->data[3] = sk->nr->vr;
  64 
  65         nr_transmit_buffer(sk, skb);    
  66 }
  67 
  68 void nr_send_nak_frame(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         struct sk_buff *skb, *skbn;
  71         
  72         if ((skb = skb_peek(&sk->nr->ack_queue)) == NULL)
  73                 return;
  74                 
  75         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)
  76                 return;
  77 
  78         nr_send_iframe(sk, skbn);
  79 
  80         sk->nr->condition &= ~ACK_PENDING_CONDITION;
  81         sk->nr->vl      = sk->nr->vr;
  82         sk->nr->t1timer = 0;
  83 }
  84 
  85 void nr_kick(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87         struct sk_buff *skb, *skbn;
  88         int last = 1;
  89         unsigned short start, end, next;
  90 
  91         del_timer(&sk->timer);
  92 
  93         start = (skb_peek(&sk->nr->ack_queue) == NULL) ? sk->nr->va : sk->nr->vs;
  94         end   = (sk->nr->va + sk->window) % NR_MODULUS;
  95 
  96         if (!(sk->nr->condition & PEER_RX_BUSY_CONDITION) &&
  97             start != end                                   &&
  98             skb_peek(&sk->write_queue) != NULL) {
  99 
 100                 sk->nr->vs = start;
 101 
 102                 /*
 103                  * Transmit data until either we're out of data to send or
 104                  * the window is full.
 105                  */
 106                 do {
 107                         /*
 108                          * Dequeue the frame and copy it.
 109                          */
 110                         skb  = skb_dequeue(&sk->write_queue);
 111 
 112                         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 113                                 skb_queue_head(&sk->write_queue, skb);
 114                                 return;
 115                         }
 116 
 117                         next = (sk->nr->vs + 1) % NR_MODULUS;
 118                         last = (next == end);
 119 
 120                         /*
 121                          * Transmit the frame copy.
 122                          */
 123                         nr_send_iframe(sk, skbn);
 124 
 125                         sk->nr->vs = next;
 126 
 127                         /*
 128                          * Requeue the original data frame.
 129                          */
 130                         skb_queue_tail(&sk->nr->ack_queue, skb);
 131 
 132                 } while (!last && skb_peek(&sk->write_queue) != NULL);
 133 
 134                 sk->nr->vl = sk->nr->vr;
 135                 sk->nr->condition &= ~ACK_PENDING_CONDITION;
 136 
 137                 if (sk->nr->t1timer == 0) {
 138                         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 139                 }
 140         }
 141 
 142         nr_set_timer(sk);
 143 }
 144 
 145 void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         unsigned char *dptr;
 148 
 149         /*
 150          *      Add the protocol byte and network header.
 151          */
 152         dptr = skb_push(skb, NR_NETWORK_LEN);
 153 
 154         memcpy(dptr, &sk->nr->source_addr, sizeof(ax25_address));
 155         dptr[6] &= ~LAPB_C;
 156         dptr[6] &= ~LAPB_E;
 157         dptr[6] |= SSID_SPARE;
 158         dptr += AX25_ADDR_LEN;
 159 
 160         memcpy(dptr, &sk->nr->dest_addr,   sizeof(ax25_address));
 161         dptr[6] &= ~LAPB_C;
 162         dptr[6] |= LAPB_E;
 163         dptr[6] |= SSID_SPARE;
 164         dptr += AX25_ADDR_LEN;
 165 
 166         *dptr++ = nr_default.ttl;
 167 
 168         skb->arp = 1;
 169 
 170         if (!nr_route_frame(skb, NULL)) {
 171                 kfree_skb(skb, FREE_WRITE);
 172 
 173                 sk->state = TCP_CLOSE;
 174                 sk->err   = ENETUNREACH;
 175                 if (!sk->dead)
 176                         sk->state_change(sk);
 177                 sk->dead  = 1;
 178         }
 179 }
 180 
 181 /*
 182  * The following routines are taken from page 170 of the 7th ARRL Computer
 183  * Networking Conference paper, as is the whole state machine.
 184  */
 185 
 186 void nr_nr_error_recovery(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         nr_establish_data_link(sk);
 189 }
 190 
 191 void nr_establish_data_link(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193         sk->nr->condition = 0x00;
 194         sk->nr->n2count   = 0;
 195 
 196         nr_write_internal(sk, NR_CONNREQ);
 197 
 198         sk->nr->t2timer = 0;
 199         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 200 }
 201 
 202 /*
 203  * Never send a NAK when we are CHOKEd.
 204  */
 205 void nr_enquiry_response(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207         int frametype = NR_INFOACK;
 208         
 209         if (sk->nr->condition & OWN_RX_BUSY_CONDITION) {
 210                 frametype += NR_CHOKE_FLAG;
 211         } else {
 212                 if (skb_peek(&sk->nr->reseq_queue) != NULL) {
 213                         frametype += NR_NAK_FLAG;
 214                 }
 215         }
 216         
 217         nr_write_internal(sk, frametype);
 218 
 219         sk->nr->vl = sk->nr->vr;
 220         sk->nr->condition &= ~ACK_PENDING_CONDITION;
 221 }
 222 
 223 void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         if (sk->nr->vs == nr) {
 226                 nr_frames_acked(sk, nr);
 227                 nr_requeue_frames(sk);
 228                 nr_calculate_rtt(sk);
 229                 sk->nr->t1timer = 0;
 230                 sk->nr->n2count = 0;
 231         } else {
 232                 if (sk->nr->va != nr) {
 233                         nr_frames_acked(sk, nr);
 234                         nr_requeue_frames(sk);
 235                         sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
 236                 }
 237         }
 238 }
 239 
 240 #endif

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