aoenet.c
上传用户:ajay2009
上传日期:2009-05-22
资源大小:495k
文件大小:3k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
  2. /*
  3.  * aoenet.c
  4.  * Ethernet portion of AoE driver
  5.  */
  6. #include <linux/hdreg.h>
  7. #include <linux/blkdev.h>
  8. #include <linux/netdevice.h>
  9. #include <linux/moduleparam.h>
  10. #include "aoe.h"
  11. #define NECODES 5
  12. static char *aoe_errlist[] =
  13. {
  14. "no such error",
  15. "unrecognized command code",
  16. "bad argument parameter",
  17. "device unavailable",
  18. "config string present",
  19. "unsupported version"
  20. };
  21. enum {
  22. IFLISTSZ = 1024,
  23. };
  24. static char aoe_iflist[IFLISTSZ];
  25. module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600);
  26. MODULE_PARM_DESC(aoe_iflist, "aoe_iflist="dev1 [dev2 ...]"n");
  27. #ifndef MODULE
  28. static int __init aoe_iflist_setup(char *str)
  29. {
  30. strncpy(aoe_iflist, str, IFLISTSZ);
  31. aoe_iflist[IFLISTSZ - 1] = '';
  32. return 1;
  33. }
  34. __setup("aoe_iflist=", aoe_iflist_setup);
  35. #endif
  36. int
  37. is_aoe_netif(struct net_device *ifp)
  38. {
  39. register char *p, *q;
  40. register int len;
  41. if (aoe_iflist[0] == '')
  42. return 1;
  43. p = aoe_iflist + strspn(aoe_iflist, WHITESPACE);
  44. for (; *p; p = q + strspn(q, WHITESPACE)) {
  45. q = p + strcspn(p, WHITESPACE);
  46. if (q != p)
  47. len = q - p;
  48. else
  49. len = strlen(p); /* last token in aoe_iflist */
  50. if (strlen(ifp->name) == len && !strncmp(ifp->name, p, len))
  51. return 1;
  52. if (q == p)
  53. break;
  54. }
  55. return 0;
  56. }
  57. int
  58. set_aoe_iflist(const char __user *user_str, size_t size)
  59. {
  60. if (size >= IFLISTSZ)
  61. return -EINVAL;
  62. if (copy_from_user(aoe_iflist, user_str, size)) {
  63. printk(KERN_INFO "aoe: %s: copy from user failedn", __FUNCTION__);
  64. return -EFAULT;
  65. }
  66. aoe_iflist[size] = 0x00;
  67. return 0;
  68. }
  69. u64
  70. mac_addr(char addr[6])
  71. {
  72. __be64 n = 0;
  73. char *p = (char *) &n;
  74. memcpy(p + 2, addr, 6); /* (sizeof addr != 6) */
  75. return __be64_to_cpu(n);
  76. }
  77. static struct sk_buff *
  78. skb_check(struct sk_buff *skb)
  79. {
  80. if (skb_is_nonlinear(skb))
  81. if ((skb = skb_share_check(skb, GFP_ATOMIC)))
  82. if (skb_linearize(skb, GFP_ATOMIC) < 0) {
  83. dev_kfree_skb(skb);
  84. return NULL;
  85. }
  86. return skb;
  87. }
  88. void
  89. aoenet_xmit(struct sk_buff *sl)
  90. {
  91. struct sk_buff *skb;
  92. while ((skb = sl)) {
  93. sl = sl->next;
  94. skb->next = skb->prev = NULL;
  95. dev_queue_xmit(skb);
  96. }
  97. }
  98. /* 
  99.  * (1) len doesn't include the header by default.  I want this. 
  100.  */
  101. static int
  102. aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
  103. {
  104. struct aoe_hdr *h;
  105. u32 n;
  106. skb = skb_check(skb);
  107. if (!skb)
  108. return 0;
  109. if (!is_aoe_netif(ifp))
  110. goto exit;
  111. //skb->len += ETH_HLEN; /* (1) */
  112. skb_push(skb, ETH_HLEN); /* (1) */
  113. h = (struct aoe_hdr *) skb->mac.raw;
  114. n = be32_to_cpu(h->tag);
  115. if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
  116. goto exit;
  117. if (h->verfl & AOEFL_ERR) {
  118. n = h->err;
  119. if (n > NECODES)
  120. n = 0;
  121. if (net_ratelimit())
  122. printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; "
  123.        "ecode=%d '%s'n",
  124.        be16_to_cpu(h->major), h->minor, 
  125.        h->err, aoe_errlist[n]);
  126. goto exit;
  127. }
  128. switch (h->cmd) {
  129. case AOECMD_ATA:
  130. aoecmd_ata_rsp(skb);
  131. break;
  132. case AOECMD_CFG:
  133. aoecmd_cfg_rsp(skb);
  134. break;
  135. default:
  136. printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %dn", h->cmd);
  137. }
  138. exit:
  139. dev_kfree_skb(skb);
  140. return 0;
  141. }
  142. static struct packet_type aoe_pt = {
  143. .type = __constant_htons(ETH_P_AOE),
  144. .func = aoenet_rcv,
  145. };
  146. int __init
  147. aoenet_init(void)
  148. {
  149. dev_add_pack(&aoe_pt);
  150. return 0;
  151. }
  152. void
  153. aoenet_exit(void)
  154. {
  155. dev_remove_pack(&aoe_pt);
  156. }