llc_utility.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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