aoenet.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 ...]\"");
  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. void
  72. aoenet_xmit(struct sk_buff_head *queue)
  73. {
  74. struct sk_buff *skb, *tmp;
  75. skb_queue_walk_safe(queue, skb, tmp) {
  76. __skb_unlink(skb, queue);
  77. dev_queue_xmit(skb);
  78. }
  79. }
  80. /*
  81. * (1) len doesn't include the header by default. I want this.
  82. */
  83. static int
  84. aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
  85. {
  86. struct aoe_hdr *h;
  87. u32 n;
  88. if (dev_net(ifp) != &init_net)
  89. goto exit;
  90. skb = skb_share_check(skb, GFP_ATOMIC);
  91. if (skb == NULL)
  92. return 0;
  93. if (skb_linearize(skb))
  94. goto exit;
  95. if (!is_aoe_netif(ifp))
  96. goto exit;
  97. skb_push(skb, ETH_HLEN); /* (1) */
  98. h = (struct aoe_hdr *) skb_mac_header(skb);
  99. n = get_unaligned_be32(&h->tag);
  100. if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
  101. goto exit;
  102. if (h->verfl & AOEFL_ERR) {
  103. n = h->err;
  104. if (n > NECODES)
  105. n = 0;
  106. if (net_ratelimit())
  107. printk(KERN_ERR
  108. "%s%d.%d@%s; ecode=%d '%s'\n",
  109. "aoe: error packet from ",
  110. get_unaligned_be16(&h->major),
  111. h->minor, skb->dev->name,
  112. h->err, aoe_errlist[n]);
  113. goto exit;
  114. }
  115. switch (h->cmd) {
  116. case AOECMD_ATA:
  117. aoecmd_ata_rsp(skb);
  118. break;
  119. case AOECMD_CFG:
  120. aoecmd_cfg_rsp(skb);
  121. break;
  122. default:
  123. if (h->cmd >= AOECMD_VEND_MIN)
  124. break; /* don't complain about vendor commands */
  125. printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
  126. }
  127. exit:
  128. dev_kfree_skb(skb);
  129. return 0;
  130. }
  131. static struct packet_type aoe_pt = {
  132. .type = __constant_htons(ETH_P_AOE),
  133. .func = aoenet_rcv,
  134. };
  135. int __init
  136. aoenet_init(void)
  137. {
  138. dev_add_pack(&aoe_pt);
  139. return 0;
  140. }
  141. void
  142. aoenet_exit(void)
  143. {
  144. dev_remove_pack(&aoe_pt);
  145. }