aoenet.c 3.1 KB

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