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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* net/atm/signaling.c - ATM signaling */
  2. /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  3. #include <linux/errno.h> /* error codes */
  4. #include <linux/kernel.h> /* printk */
  5. #include <linux/skbuff.h>
  6. #include <linux/wait.h>
  7. #include <linux/sched.h> /* jiffies and HZ */
  8. #include <linux/atm.h> /* ATM stuff */
  9. #include <linux/atmsap.h>
  10. #include <linux/atmsvc.h>
  11. #include <linux/atmdev.h>
  12. #include <linux/bitops.h>
  13. #include "resources.h"
  14. #include "signaling.h"
  15. #undef WAIT_FOR_DEMON /* #define this if system calls on SVC sockets
  16.    should block until the demon runs.
  17.    Danger: may cause nasty hangs if the demon
  18.    crashes. */
  19. #if 0
  20. #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
  21. #else
  22. #define DPRINTK(format,args...)
  23. #endif
  24. struct atm_vcc *sigd = NULL;
  25. static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
  26. extern spinlock_t atm_dev_lock;
  27. static void sigd_put_skb(struct sk_buff *skb)
  28. {
  29. #ifdef WAIT_FOR_DEMON
  30. static unsigned long silence = 0;
  31. DECLARE_WAITQUEUE(wait,current);
  32. add_wait_queue(&sigd_sleep,&wait);
  33. while (!sigd) {
  34. set_current_state(TASK_UNINTERRUPTIBLE);
  35. if (time_after(jiffies, silence) || silence == 0) {
  36. printk(KERN_INFO "atmsvc: waiting for signaling demon "
  37.     "...n");
  38. silence = (jiffies+30*HZ)|1;
  39. }
  40. schedule();
  41. }
  42. current->state = TASK_RUNNING;
  43. remove_wait_queue(&sigd_sleep,&wait);
  44. #else
  45. if (!sigd) {
  46. printk(KERN_WARNING "atmsvc: no signaling demonn");
  47. kfree_skb(skb);
  48. return;
  49. }
  50. #endif
  51. atm_force_charge(sigd,skb->truesize);
  52. skb_queue_tail(&sigd->recvq,skb);
  53. wake_up(&sigd->sleep);
  54. }
  55. static void modify_qos(struct atm_vcc *vcc,struct atmsvc_msg *msg)
  56. {
  57. struct sk_buff *skb;
  58. if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
  59.     !test_bit(ATM_VF_READY,&vcc->flags))
  60. return;
  61. msg->type = as_error;
  62. if (!vcc->dev->ops->change_qos) msg->reply = -EOPNOTSUPP;
  63. else {
  64. /* should lock VCC */
  65. msg->reply = vcc->dev->ops->change_qos(vcc,&msg->qos,
  66.     msg->reply);
  67. if (!msg->reply) msg->type = as_okay;
  68. }
  69. /*
  70.  * Should probably just turn around the old skb. But the, the buffer
  71.  * space accounting needs to follow the change too. Maybe later.
  72.  */
  73. while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
  74. schedule();
  75. *(struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)) = *msg;
  76. sigd_put_skb(skb);
  77. }
  78. static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
  79. {
  80. struct atmsvc_msg *msg;
  81. struct atm_vcc *session_vcc;
  82. msg = (struct atmsvc_msg *) skb->data;
  83. atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
  84. DPRINTK("sigd_send %d (0x%lx)n",(int) msg->type,
  85.   (unsigned long) msg->vcc);
  86. vcc = *(struct atm_vcc **) &msg->vcc;
  87. switch (msg->type) {
  88. case as_okay:
  89. vcc->reply = msg->reply;
  90. if (!*vcc->local.sas_addr.prv &&
  91.     !*vcc->local.sas_addr.pub) {
  92. vcc->local.sas_family = AF_ATMSVC;
  93. memcpy(vcc->local.sas_addr.prv,
  94.     msg->local.sas_addr.prv,ATM_ESA_LEN);
  95. memcpy(vcc->local.sas_addr.pub,
  96.     msg->local.sas_addr.pub,ATM_E164_LEN+1);
  97. }
  98. session_vcc = vcc->session ? vcc->session : vcc;
  99. if (session_vcc->vpi || session_vcc->vci) break;
  100. session_vcc->itf = msg->pvc.sap_addr.itf;
  101. session_vcc->vpi = msg->pvc.sap_addr.vpi;
  102. session_vcc->vci = msg->pvc.sap_addr.vci;
  103. if (session_vcc->vpi || session_vcc->vci)
  104. session_vcc->qos = msg->qos;
  105. break;
  106. case as_error:
  107. clear_bit(ATM_VF_REGIS,&vcc->flags);
  108. clear_bit(ATM_VF_READY,&vcc->flags);
  109. vcc->reply = msg->reply;
  110. break;
  111. case as_indicate:
  112. vcc = *(struct atm_vcc **) &msg->listen_vcc;
  113. DPRINTK("as_indicate!!!n");
  114. if (!vcc->backlog_quota) {
  115. sigd_enq(0,as_reject,vcc,NULL,NULL);
  116. return 0;
  117. }
  118. vcc->backlog_quota--;
  119. skb_queue_tail(&vcc->listenq,skb);
  120. if (vcc->callback) {
  121. DPRINTK("waking vcc->sleep 0x%pn",
  122.     &vcc->sleep);
  123. vcc->callback(vcc);
  124. }
  125. return 0;
  126. case as_close:
  127. set_bit(ATM_VF_RELEASED,&vcc->flags);
  128. clear_bit(ATM_VF_READY,&vcc->flags);
  129. vcc->reply = msg->reply;
  130. break;
  131. case as_modify:
  132. modify_qos(vcc,msg);
  133. break;
  134. default:
  135. printk(KERN_ALERT "sigd_send: bad message type %dn",
  136.     (int) msg->type);
  137. return -EINVAL;
  138. }
  139. if (vcc->callback) vcc->callback(vcc);
  140. dev_kfree_skb(skb);
  141. return 0;
  142. }
  143. void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
  144.     struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
  145.     const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply)
  146. {
  147. struct sk_buff *skb;
  148. struct atmsvc_msg *msg;
  149. DPRINTK("sigd_enq %d (0x%p)n",(int) type,vcc);
  150. while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
  151. schedule();
  152. msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg));
  153. memset(msg,0,sizeof(*msg));
  154. msg->type = type;
  155. *(struct atm_vcc **) &msg->vcc = vcc;
  156. *(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
  157. msg->reply = reply;
  158. if (qos) msg->qos = *qos;
  159. if (vcc) msg->sap = vcc->sap;
  160. if (svc) msg->svc = *svc;
  161. if (vcc) msg->local = vcc->local;
  162. if (pvc) msg->pvc = *pvc;
  163. sigd_put_skb(skb);
  164. if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags);
  165. }
  166. void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
  167.     struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
  168.     const struct sockaddr_atmsvc *svc)
  169. {
  170. sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0);
  171. /* other ISP applications may use "reply" */
  172. }
  173. static void purge_vccs(struct atm_vcc *vcc)
  174. {
  175. while (vcc) {
  176. if (vcc->family == PF_ATMSVC &&
  177.     !test_bit(ATM_VF_META,&vcc->flags)) {
  178. set_bit(ATM_VF_RELEASED,&vcc->flags);
  179. vcc->reply = -EUNATCH;
  180. wake_up(&vcc->sleep);
  181. }
  182. vcc = vcc->next;
  183. }
  184. }
  185. static void sigd_close(struct atm_vcc *vcc)
  186. {
  187. struct atm_dev *dev;
  188. DPRINTK("sigd_closen");
  189. sigd = NULL;
  190. if (skb_peek(&vcc->recvq))
  191. printk(KERN_ERR "sigd_close: closing with requests pendingn");
  192. skb_queue_purge(&vcc->recvq);
  193. purge_vccs(nodev_vccs);
  194. spin_lock (&atm_dev_lock);
  195. for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
  196. spin_unlock (&atm_dev_lock);
  197. }
  198. static struct atmdev_ops sigd_dev_ops = {
  199. close: sigd_close,
  200. send: sigd_send
  201. };
  202. static struct atm_dev sigd_dev = {
  203. &sigd_dev_ops,
  204. NULL, /* no PHY */
  205.      "sig", /* type */
  206. 999, /* dummy device number */
  207. NULL,NULL, /* pretend not to have any VCCs */
  208. NULL,NULL, /* no data */
  209. { 0 }, /* no flags */
  210. NULL, /* no local address */
  211. { 0 } /* no ESI, no statistics */
  212. };
  213. int sigd_attach(struct atm_vcc *vcc)
  214. {
  215. if (sigd) return -EADDRINUSE;
  216. DPRINTK("sigd_attachn");
  217. sigd = vcc;
  218. bind_vcc(vcc,&sigd_dev);
  219. set_bit(ATM_VF_META,&vcc->flags);
  220. set_bit(ATM_VF_READY,&vcc->flags);
  221. wake_up(&sigd_sleep);
  222. return 0;
  223. }