atmtcp.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
  2. /* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
  3. #include <linux/module.h>
  4. #include <linux/wait.h>
  5. #include <linux/atmdev.h>
  6. #include <linux/atm_tcp.h>
  7. #include <linux/bitops.h>
  8. #include <asm/uaccess.h>
  9. #include <asm/atomic.h>
  10. extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
  11. #define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data))
  12. struct atmtcp_dev_data {
  13. struct atm_vcc *vcc; /* control VCC; NULL if detached */
  14. int persist; /* non-zero if persistent */
  15. };
  16. #define DEV_LABEL    "atmtcp"
  17. #define MAX_VPI_BITS  8 /* simplifies life */
  18. #define MAX_VCI_BITS 16
  19. /*
  20.  * Hairy code ahead: the control VCC may be closed while we're still
  21.  * waiting for an answer, so we need to re-validate out_vcc every once
  22.  * in a while.
  23.  */
  24. static int atmtcp_send_control(struct atm_vcc *vcc,int type,
  25.     const struct atmtcp_control *msg,int flag)
  26. {
  27. DECLARE_WAITQUEUE(wait,current);
  28. struct atm_vcc *out_vcc;
  29. struct sk_buff *skb;
  30. struct atmtcp_control *new_msg;
  31. int old_test;
  32. int error = 0;
  33. out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
  34. if (!out_vcc) return -EUNATCH;
  35. skb = alloc_skb(sizeof(*msg),GFP_KERNEL);
  36. if (!skb) return -ENOMEM;
  37. mb();
  38. out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
  39. if (!out_vcc) {
  40. dev_kfree_skb(skb);
  41. return -EUNATCH;
  42. }
  43. atm_force_charge(out_vcc,skb->truesize);
  44. new_msg = (struct atmtcp_control *) skb_put(skb,sizeof(*new_msg));
  45. *new_msg = *msg;
  46. new_msg->hdr.length = ATMTCP_HDR_MAGIC;
  47. new_msg->type = type;
  48. memset(&new_msg->vcc,0,sizeof(atm_kptr_t));
  49. *(struct atm_vcc **) &new_msg->vcc = vcc;
  50. old_test = test_bit(flag,&vcc->flags);
  51. out_vcc->push(out_vcc,skb);
  52. add_wait_queue(&vcc->sleep,&wait);
  53. while (test_bit(flag,&vcc->flags) == old_test) {
  54. mb();
  55. out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
  56. if (!out_vcc) {
  57. error = -EUNATCH;
  58. break;
  59. }
  60. set_current_state(TASK_UNINTERRUPTIBLE);
  61. schedule();
  62. }
  63. current->state = TASK_RUNNING;
  64. remove_wait_queue(&vcc->sleep,&wait);
  65. return error;
  66. }
  67. static int atmtcp_recv_control(const struct atmtcp_control *msg)
  68. {
  69. struct atm_vcc *vcc = *(struct atm_vcc **) &msg->vcc;
  70. vcc->vpi = msg->addr.sap_addr.vpi;
  71. vcc->vci = msg->addr.sap_addr.vci;
  72. vcc->qos = msg->qos;
  73. vcc->reply = msg->result;
  74. switch (msg->type) {
  75.     case ATMTCP_CTRL_OPEN:
  76. change_bit(ATM_VF_READY,&vcc->flags);
  77. break;
  78.     case ATMTCP_CTRL_CLOSE:
  79. change_bit(ATM_VF_ADDR,&vcc->flags);
  80. break;
  81.     default:
  82. printk(KERN_ERR "atmtcp_recv_control: unknown type %dn",
  83.     msg->type);
  84. return -EINVAL;
  85. }
  86. wake_up(&vcc->sleep);
  87. return 0;
  88. }
  89. static void atmtcp_v_dev_close(struct atm_dev *dev)
  90. {
  91. /* Nothing.... Isn't this simple :-)  -- REW */
  92. }
  93. static int atmtcp_v_open(struct atm_vcc *vcc,short vpi,int vci)
  94. {
  95. struct atmtcp_control msg;
  96. int error;
  97. memset(&msg,0,sizeof(msg));
  98. msg.addr.sap_family = AF_ATMPVC;
  99. msg.hdr.vpi = htons(vpi);
  100. msg.addr.sap_addr.vpi = vpi;
  101. msg.hdr.vci = htons(vci);
  102. msg.addr.sap_addr.vci = vci;
  103. error = atm_find_ci(vcc,&msg.addr.sap_addr.vpi,&msg.addr.sap_addr.vci);
  104. if (error) return error;
  105. if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
  106. msg.type = ATMTCP_CTRL_OPEN;
  107. msg.qos = vcc->qos;
  108. set_bit(ATM_VF_ADDR,&vcc->flags);
  109. clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
  110. error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
  111. if (error) return error;
  112. return vcc->reply;
  113. }
  114. static void atmtcp_v_close(struct atm_vcc *vcc)
  115. {
  116. struct atmtcp_control msg;
  117. memset(&msg,0,sizeof(msg));
  118. msg.addr.sap_family = AF_ATMPVC;
  119. msg.addr.sap_addr.vpi = vcc->vpi;
  120. msg.addr.sap_addr.vci = vcc->vci;
  121. clear_bit(ATM_VF_READY,&vcc->flags);
  122. (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR);
  123. }
  124. static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
  125. {
  126. struct atm_cirange ci;
  127. struct atm_vcc *vcc;
  128. if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
  129. if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
  130. if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS;
  131. if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
  132. if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
  133.     ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
  134. for (vcc = dev->vccs; vcc; vcc = vcc->next)
  135. if ((vcc->vpi >> ci.vpi_bits) ||
  136.     (vcc->vci >> ci.vci_bits)) return -EBUSY;
  137. dev->ci_range = ci;
  138. return 0;
  139. }
  140. static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb)
  141. {
  142. struct atmtcp_dev_data *dev_data;
  143. struct atm_vcc *out_vcc;
  144. struct sk_buff *new_skb;
  145. struct atmtcp_hdr *hdr;
  146. int size;
  147. if (vcc->qos.txtp.traffic_class == ATM_NONE) {
  148. if (vcc->pop) vcc->pop(vcc,skb);
  149. else dev_kfree_skb(skb);
  150. return -EINVAL;
  151. }
  152. dev_data = PRIV(vcc->dev);
  153. if (dev_data) out_vcc = dev_data->vcc;
  154. if (!dev_data || !out_vcc) {
  155. if (vcc->pop) vcc->pop(vcc,skb);
  156. else dev_kfree_skb(skb);
  157. if (dev_data) return 0;
  158. atomic_inc(&vcc->stats->tx_err);
  159. return -ENOLINK;
  160. }
  161. size = skb->len+sizeof(struct atmtcp_hdr);
  162. new_skb = atm_alloc_charge(out_vcc,size,GFP_ATOMIC);
  163. if (!new_skb) {
  164. if (vcc->pop) vcc->pop(vcc,skb);
  165. else dev_kfree_skb(skb);
  166. atomic_inc(&vcc->stats->tx_err);
  167. return -ENOBUFS;
  168. }
  169. hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
  170. hdr->vpi = htons(vcc->vpi);
  171. hdr->vci = htons(vcc->vci);
  172. hdr->length = htonl(skb->len);
  173. memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
  174. if (vcc->pop) vcc->pop(vcc,skb);
  175. else dev_kfree_skb(skb);
  176. out_vcc->push(out_vcc,new_skb);
  177. atomic_inc(&vcc->stats->tx);
  178. atomic_inc(&out_vcc->stats->rx);
  179. return 0;
  180. }
  181. static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page)
  182. {
  183. struct atmtcp_dev_data *dev_data = PRIV(dev);
  184. if (*pos) return 0;
  185. if (!dev_data->persist) return sprintf(page,"ephemeraln");
  186. return sprintf(page,"persistent, %sconnectedn",
  187.     dev_data->vcc ? "" : "dis");
  188. }
  189. static void atmtcp_c_close(struct atm_vcc *vcc)
  190. {
  191. struct atm_dev *atmtcp_dev;
  192. struct atmtcp_dev_data *dev_data;
  193. struct atm_vcc *walk;
  194. atmtcp_dev = (struct atm_dev *) vcc->dev_data;
  195. dev_data = PRIV(atmtcp_dev);
  196. dev_data->vcc = NULL;
  197. if (dev_data->persist) return;
  198. PRIV(atmtcp_dev) = NULL;
  199. kfree(dev_data);
  200. shutdown_atm_dev(atmtcp_dev);
  201. vcc->dev_data = NULL;
  202. for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
  203. wake_up(&walk->sleep);
  204. }
  205. static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
  206. {
  207. struct atm_dev *dev;
  208. struct atmtcp_hdr *hdr;
  209. struct atm_vcc *out_vcc;
  210. struct sk_buff *new_skb;
  211. int result = 0;
  212. if (!skb->len) return 0;
  213. dev = vcc->dev_data;
  214. hdr = (struct atmtcp_hdr *) skb->data;
  215. if (hdr->length == ATMTCP_HDR_MAGIC) {
  216. result = atmtcp_recv_control(
  217.     (struct atmtcp_control *) skb->data);
  218. goto done;
  219. }
  220. for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
  221. if (out_vcc->vpi == ntohs(hdr->vpi) &&
  222.     out_vcc->vci == ntohs(hdr->vci) &&
  223.     out_vcc->qos.rxtp.traffic_class != ATM_NONE)
  224. break;
  225. if (!out_vcc) {
  226. atomic_inc(&vcc->stats->tx_err);
  227. goto done;
  228. }
  229. skb_pull(skb,sizeof(struct atmtcp_hdr));
  230. new_skb = atm_alloc_charge(out_vcc,skb->len,GFP_KERNEL);
  231. if (!new_skb) {
  232. result = -ENOBUFS;
  233. goto done;
  234. }
  235. new_skb->stamp = xtime;
  236. memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
  237. out_vcc->push(out_vcc,new_skb);
  238. atomic_inc(&vcc->stats->tx);
  239. atomic_inc(&out_vcc->stats->rx);
  240. done:
  241. if (vcc->pop) vcc->pop(vcc,skb);
  242. else dev_kfree_skb(skb);
  243. return result;
  244. }
  245. /*
  246.  * Device operations for the virtual ATM devices created by ATMTCP.
  247.  */
  248. static struct atmdev_ops atmtcp_v_dev_ops = {
  249. dev_close: atmtcp_v_dev_close,
  250. open: atmtcp_v_open,
  251. close: atmtcp_v_close,
  252. ioctl: atmtcp_v_ioctl,
  253. send: atmtcp_v_send,
  254. proc_read: atmtcp_v_proc,
  255. owner: THIS_MODULE
  256. };
  257. /*
  258.  * Device operations for the ATMTCP control device.
  259.  */
  260. static struct atmdev_ops atmtcp_c_dev_ops = {
  261. close: atmtcp_c_close,
  262. send: atmtcp_c_send
  263. };
  264. static struct atm_dev atmtcp_control_dev = {
  265. &atmtcp_c_dev_ops,
  266. NULL, /* no PHY */
  267. "atmtcp", /* type */
  268. 999, /* dummy device number */
  269. NULL,NULL, /* pretend not to have any VCCs */
  270. NULL,NULL, /* no data */
  271. { 0 }, /* no flags */
  272. NULL, /* no local address */
  273. { 0 } /* no ESI, no statistics */
  274. };
  275. static int atmtcp_create(int itf,int persist,struct atm_dev **result)
  276. {
  277. struct atmtcp_dev_data *dev_data;
  278. struct atm_dev *dev;
  279. dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
  280. if (!dev_data)
  281. return -ENOMEM;
  282. dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
  283. if (!dev) {
  284. kfree(dev_data);
  285. return itf == -1 ? -ENOMEM : -EBUSY;
  286. }
  287. dev->ci_range.vpi_bits = MAX_VPI_BITS;
  288. dev->ci_range.vci_bits = MAX_VCI_BITS;
  289. PRIV(dev) = dev_data;
  290. PRIV(dev)->vcc = NULL;
  291. PRIV(dev)->persist = persist;
  292. if (result) *result = dev;
  293. return 0;
  294. }
  295. int atmtcp_attach(struct atm_vcc *vcc,int itf)
  296. {
  297. struct atm_dev *dev;
  298. dev = NULL;
  299. if (itf != -1) dev = atm_find_dev(itf);
  300. if (dev) {
  301. if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
  302. if (PRIV(dev)->vcc) return -EBUSY;
  303. }
  304. else {
  305. int error;
  306. error = atmtcp_create(itf,0,&dev);
  307. if (error) return error;
  308. }
  309. PRIV(dev)->vcc = vcc;
  310. bind_vcc(vcc,&atmtcp_control_dev);
  311. set_bit(ATM_VF_META,&vcc->flags);
  312. set_bit(ATM_VF_READY,&vcc->flags);
  313. vcc->dev_data = dev;
  314. (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */
  315. vcc->stats = &atmtcp_control_dev.stats.aal5;
  316. return dev->number;
  317. }
  318. int atmtcp_create_persistent(int itf)
  319. {
  320. return atmtcp_create(itf,1,NULL);
  321. }
  322. int atmtcp_remove_persistent(int itf)
  323. {
  324. struct atm_dev *dev;
  325. struct atmtcp_dev_data *dev_data;
  326. dev = atm_find_dev(itf);
  327. if (!dev) return -ENODEV;
  328. if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
  329. dev_data = PRIV(dev);
  330. if (!dev_data->persist) return 0;
  331. dev_data->persist = 0;
  332. if (PRIV(dev)->vcc) return 0;
  333. kfree(dev_data);
  334. shutdown_atm_dev(dev);
  335. return 0;
  336. }
  337. #ifdef MODULE
  338. int init_module(void)
  339. {
  340. atm_tcp_ops.attach = atmtcp_attach;
  341. atm_tcp_ops.create_persistent = atmtcp_create_persistent;
  342. atm_tcp_ops.remove_persistent = atmtcp_remove_persistent;
  343. return 0;
  344. }
  345. void cleanup_module(void)
  346. {
  347. atm_tcp_ops.attach = NULL;
  348. atm_tcp_ops.create_persistent = NULL;
  349. atm_tcp_ops.remove_persistent = NULL;
  350. }
  351. MODULE_LICENSE("GPL");
  352. #else
  353. struct atm_tcp_ops atm_tcp_ops = {
  354. atmtcp_attach, /* attach */
  355. atmtcp_create_persistent, /* create_persistent */
  356. atmtcp_remove_persistent /* remove_persistent */
  357. };
  358. #endif