aoenet.c 2.9 KB

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