aoenet.c 3.3 KB

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