~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/802/llc_utility.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * NET          An implementation of the IEEE 802.2 LLC protocol for the
  3  *              LINUX operating system.  LLC is implemented as a set of 
  4  *              state machines and callbacks for higher networking layers.
  5  *
  6  *              Small utilities, Linux timer handling.
  7  *
  8  *              Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
  9  *
 10  *              This program 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  *      Changes
 16  *              Alan Cox        :       Chainsawed into Linux form.
 17  *                                      Added llc_ function name prefixes.
 18  *                                      Fixed bug in stop/start timer.
 19  *                                      Added llc_cancel_timers for closing
 20  *                                              down an llc
 21  */
 22 
 23 #include <linux/types.h>
 24 #include <linux/kernel.h>
 25 #include <linux/netdevice.h>
 26 #include <linux/skbuff.h>
 27 #include <linux/proc_fs.h>
 28 #include <linux/stat.h>
 29 #include <net/llc_frame.h>
 30 #include <net/llc.h>
 31 
 32 int llc_decode_frametype(frameptr fr)
 33 {
 34         if (IS_UFRAME(fr)) 
 35         {      /* unnumbered cmd/rsp */
 36                 switch(fr->u_mm.mm & 0x3B)
 37                 {
 38                         case 0x1B:
 39                             return(SABME_CMD);
 40                             break;
 41                         case 0x10:
 42                             return(DISC_CMD);
 43                             break;
 44                         case 0x18:
 45                             return(UA_RSP);
 46                             break;
 47                         case 0x03:
 48                             return(DM_RSP);
 49                             break;
 50                         case 0x21:
 51                             return(FRMR_RSP);
 52                             break;
 53                         case 0x00:
 54                             return(UI_CMD);
 55                             break;
 56                         case 0x2B:
 57                             if (IS_RSP(fr)) 
 58                                 return(XID_RSP);
 59                             else
 60                                 return(XID_CMD);
 61                             break;
 62                         case 0x38:
 63                             if (IS_RSP(fr))
 64                                 return(TEST_RSP);
 65                             else
 66                                 return(TEST_CMD);
 67                             break;
 68                         default:
 69                             return(BAD_FRAME);
 70                 }
 71         }
 72         else if (IS_SFRAME(fr))
 73         {  /* supervisory cmd/rsp */
 74                 switch(fr->s_hdr.ss)
 75                 {
 76                         case 0x00:
 77                             if (IS_RSP(fr)) 
 78                                 return(RR_RSP);
 79                             else
 80                                 return(RR_CMD);
 81                             break;
 82                         case 0x02:
 83                             if (IS_RSP(fr))
 84                                 return(REJ_RSP);
 85                             else
 86                                 return(REJ_CMD);
 87                             break;
 88                         case 0x01:
 89                             if (IS_RSP(fr))
 90                                 return(RNR_RSP);
 91                             else
 92                                 return(RNR_CMD);
 93                             break;
 94                         default:
 95                             return(BAD_FRAME);
 96                 }
 97         }
 98         else
 99         {                         /* information xfer */
100                 if (IS_RSP(fr)) 
101                         return(I_RSP);
102                 else    
103                         return(I_CMD);
104         }
105 }
106 
107 
108 /*
109  *      Validate_seq_nos will check N(S) and N(R) to see if they are
110  *      invalid or unexpected.
111  *      "unexpected" is explained on p44 Send State Variable.
112  *      The return value is:
113  *              4 * invalid N(R) +
114  *              2 * invalid N(S) +
115  *              1 * unexpected N(S)
116  */
117 
118 int llc_validate_seq_nos(llcptr lp, frameptr fr)
119 {
120         int res;
121      
122         /*
123          *      A U-frame is always good 
124          */
125 
126         if (IS_UFRAME(fr)) 
127                 return(0);      
128 
129         /*
130          *      For S- and I-frames check N(R): 
131          */
132 
133         if (fr->i_hdr.nr == lp->vs) 
134         {       /* if N(R) = V(S)  */
135                 res = 0;                        /* N(R) is good */
136         }
137         else
138         {                               /* lp->k = transmit window size */
139                 if (lp->vs >= lp->k) 
140                 {       /* if window not wrapped around 127 */
141                         if ((fr->i_hdr.nr < lp->vs) &&
142                                 (fr->i_hdr.nr > (lp->vs - lp->k)))
143                                 res = 0;
144                         else 
145                                 res = 4;                /* N(R) invalid */
146                 }
147                 else
148                 {       /* window wraps around 127 */
149                         if ((fr->i_hdr.nr < lp->vs) ||
150                                 (fr->i_hdr.nr > (128 + lp->vs - lp->k))) 
151                                 res = 0;
152                         else
153                                 res = 4;                /* N(R) invalid */
154                 }
155         }
156 
157         /*
158          *      For an I-frame, must check N(S) also:  
159          */
160 
161         if (IS_IFRAME(fr)) 
162         {
163                 if (fr->i_hdr.ns == lp->vr) 
164                         return res;   /* N(S) good */
165                 if (lp->vr >= lp->rw) 
166                 {
167                         /* if receive window not wrapped */
168 
169                         if ((fr->i_hdr.ns < lp->vr) &&
170                                 (fr->i_hdr.ns > (lp->vr - lp->k)))
171                                 res = res +1;           /* N(S) unexpected */
172                         else  
173                                 res = res +2;         /* N(S) invalid */            
174                 }
175                 else
176                 {
177                         /* Window wraps around 127 */
178 
179                         if ((fr->i_hdr.ns < lp->vr) ||
180                                 (fr->i_hdr.ns > (128 + lp->vr - lp->k)))
181                                 res = res +1;           /* N(S) unexpected */
182                         else
183                                 res = res +2;         /* N(S) invalid */            
184                 }
185         }                                       
186         return(res);
187 }
188 
189 /* **************** timer management routines ********************* */
190 
191 static void llc_p_timer_expired(unsigned long ulp)
192 {
193         llc_timer_expired((llcptr) ulp, P_TIMER);
194 }
195 
196 static void llc_rej_timer_expired(unsigned long ulp)
197 {
198         llc_timer_expired((llcptr) ulp, REJ_TIMER);
199 }
200 
201 static void llc_ack_timer_expired(unsigned long ulp)
202 {
203         llc_timer_expired((llcptr) ulp, ACK_TIMER);
204 } 
205 
206 static void llc_busy_timer_expired(unsigned long ulp)
207 {
208         llc_timer_expired((llcptr) ulp, BUSY_TIMER);
209 }
210 
211 /* exp_fcn is an array holding the 4 entry points of the
212    timer expiry routines above.
213    It is required to keep start_timer() generic.
214    Thank you cdecl.
215  */
216 
217 static void (* exp_fcn[])(unsigned long) = 
218 {
219         llc_p_timer_expired,
220         llc_rej_timer_expired,
221         llc_ack_timer_expired,
222         llc_busy_timer_expired
223 };   
224 
225 void llc_start_timer(llcptr lp, int t)
226 {
227         if (lp->timer_state[t] == TIMER_IDLE)
228         {
229                 lp->tl[t].expires = jiffies + lp->timer_interval[t];
230                 lp->tl[t].data = (unsigned long) lp;
231                 lp->tl[t].function = exp_fcn[t];
232                 add_timer(&lp->tl[t]);
233                 lp->timer_state[t] = TIMER_RUNNING;
234         }
235 }
236 
237 void llc_stop_timer(llcptr lp, int t)
238 {
239         if (lp->timer_state[t] == TIMER_RUNNING)
240         {
241                 del_timer(&lp->tl[t]);
242                 lp->timer_state[t] = TIMER_IDLE;
243         }
244 }
245 
246 void llc_cancel_timers(llcptr lp)
247 {
248         llc_stop_timer(lp, P_TIMER);
249         llc_stop_timer(lp, REJ_TIMER);
250         llc_stop_timer(lp, ACK_TIMER);
251         llc_stop_timer(lp, BUSY_TIMER);
252 }
253 
254 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.