aoe  87
About: AoE (ATA over Ethernet) Protocol Driver (Linux kernel 4.8.x and greater are not supported).
  Fossies Dox: aoe-87.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

aoenet.c
Go to the documentation of this file.
1 /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */
2 /*
3  * aoenet.c
4  * Ethernet portion of AoE driver
5  */
6 
7 #include <linux/hdreg.h>
8 #include <linux/blkdev.h>
9 #include <linux/netdevice.h>
10 #include <linux/moduleparam.h>
11 #include <net/net_namespace.h>
12 #include <asm/unaligned.h>
13 #include "aoe.h"
14 
15 #define NECODES 5
16 
17 static char *aoe_errlist[] =
18 {
19  "no such error",
20  "unrecognized command code",
21  "bad argument parameter",
22  "device unavailable",
23  "config string present",
24  "unsupported version"
25 };
26 
27 enum {
28  IFLISTSZ = 1024,
29 };
30 
31 static char aoe_iflist[IFLISTSZ];
33 MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=dev1[,dev2...]\n");
34 
35 static wait_queue_head_t txwq;
36 static struct ktstate kts;
37 
38 #ifndef MODULE
39 static int __init aoe_iflist_setup(char *str)
40 {
41  strncpy(aoe_iflist, str, IFLISTSZ);
42  aoe_iflist[IFLISTSZ - 1] = '\0';
43  return 1;
44 }
45 
46 __setup("aoe_iflist=", aoe_iflist_setup);
47 #endif
48 
49 static spinlock_t txlock;
50 static struct sk_buff_head skbtxq;
51 
52 /* enters with txlock held */
53 static int
54 tx(int id)
55 {
56  struct sk_buff *skb;
57  struct aoe_hdr *h;
58  struct aoe_atahdr *ah;
59  struct net_device *ifp;
60  int changef;
61 
62  while ((skb = skb_dequeue(&skbtxq))) {
63  spin_unlock_irq(&txlock);
64  h = (struct aoe_hdr *) skb_mac_header(skb);
65  ah = (struct aoe_atahdr *) (h + 1);
66  if (current->flags & PF_MEMALLOC)
67  changef = 0;
68  else
69  changef = ah->aflags & AOEAFL_WRITE;
70  if (changef)
71  current->flags |= PF_MEMALLOC;
72  ifp = skb->dev;
73  if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit())
74  printk(KERN_WARNING
75  "aoe: packet could not be sent on %s. %s\n",
76  ifp ? ifp->name : "netif",
77  "consider increasing tx_queue_len");
78  if (changef)
79  current->flags &= ~PF_MEMALLOC;
80  spin_lock_irq(&txlock);
81  }
82  return 0;
83 }
84 
85 /* This function is copied here from linux-2.6.10-rc3-bk11/lib/string.c
86  * for compatibility with FC2, which issues a warning on MODPOST
87  * about strcspn being undefined.
88  */
89 static size_t
90 aoe_strcspn(const char *s, const char *reject)
91 {
92  const char *p;
93  const char *r;
94  size_t count = 0;
95 
96  for (p = s; *p != '\0'; ++p) {
97  for (r = reject; *r != '\0'; ++r) {
98  if (*p == *r)
99  return count;
100  }
101  ++count;
102  }
103 
104  return count;
105 }
106 
107 int
108 is_aoe_netif(struct net_device *ifp)
109 {
110  register char *p, *q;
111  register int len;
112 
113  if (aoe_iflist[0] == '\0')
114  return 1;
115 
116  p = aoe_iflist + strspn(aoe_iflist, WHITESPACE);
117  for (; *p; p = q + strspn(q, WHITESPACE)) {
118  q = p + aoe_strcspn(p, WHITESPACE);
119  if (q != p)
120  len = q - p;
121  else
122  len = strlen(p); /* last token in aoe_iflist */
123 
124  if (strlen(ifp->name) == len && !strncmp(ifp->name, p, len))
125  return 1;
126  if (q == p)
127  break;
128  }
129 
130  return 0;
131 }
132 
133 int
134 set_aoe_iflist(const char __user *user_str, size_t size)
135 {
136  if (size >= IFLISTSZ)
137  return -EINVAL;
138 
139  if (copy_from_user(aoe_iflist, user_str, size)) {
140  printk(KERN_INFO "aoe: copy from user failed\n");
141  return -EFAULT;
142  }
143  aoe_iflist[size] = 0x00;
144  return 0;
145 }
146 
147 unsigned long long
148 mac_addr(char addr[6])
149 {
150  u64 n = 0;
151  char *p = (char *) &n;
152 
153  memcpy(p + 2, addr, 6); /* (sizeof addr != 6) */
154 
155  return (unsigned long long) __be64_to_cpu(n);
156 }
157 
158 void
159 aoenet_xmit(struct sk_buff *sl)
160 {
161  struct sk_buff *skb;
162  ulong flags;
163 
164  while ((skb = sl)) {
165  sl = sl->next;
166  skb->next = skb->prev = NULL;
167  spin_lock_irqsave(&txlock, flags);
168  skb_queue_tail(&skbtxq, skb);
169  spin_unlock_irqrestore(&txlock, flags);
170  wake_up(&txwq);
171  }
172 }
173 
174 /*
175  * (1) len doesn't include the header by default. I want this.
176  */
177 static int
178 aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
179 {
180  struct aoe_hdr *h;
181  struct aoe_atahdr *ah;
182  u32 n;
183  int sn;
184 
185  if (dev_net(ifp) != &init_net)
186  goto exit;
187 
188  skb = skb_share_check(skb, GFP_ATOMIC);
189  if (skb == NULL)
190  return 0;
191  if (!is_aoe_netif(ifp))
192  goto exit;
193  skb_push(skb, ETH_HLEN); /* (1) */
194  sn = sizeof(*h) + sizeof(*ah);
195  if (skb->len >= sn) {
196  sn -= skb_headlen(skb);
197  if (sn > 0 && !__pskb_pull_tail(skb, sn))
198  goto exit;
199  }
200  h = (struct aoe_hdr *) skb->data;
201  n = be32_to_cpu(get_unaligned(&h->tag));
202  if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
203  goto exit;
204 
205  if (h->verfl & AOEFL_ERR) {
206  n = h->err;
207  if (n > NECODES)
208  n = 0;
209  if (net_ratelimit())
210  printk(KERN_ERR
211  "aoe: error packet from %d.%d@%s; ecode=%d '%s'\n",
212  be16_to_cpu(get_unaligned(&h->major)), h->minor,
213  skb->dev->name, h->err, aoe_errlist[n]);
214  goto exit;
215  }
216 
217  switch (h->cmd) {
218  case AOECMD_ATA:
219  /* ata_rsp may keep skb for later processing or give it back */
220  skb = aoecmd_ata_rsp(skb);
221  break;
222  case AOECMD_CFG:
223  aoecmd_cfg_rsp(skb);
224  break;
225  default:
226  if (h->cmd >= AOECMD_VEND_MIN)
227  break; /* don't complain about vendor commands */
228  printk(KERN_INFO
229  "aoe: warning: unknown aoe command type 0x%02x\n",
230  h->cmd);
231  break;
232  }
233  if (skb)
234 exit: dev_kfree_skb(skb);
235  return 0;
236 }
237 
238 static struct packet_type aoe_pt = {
239  .type = __constant_htons(ETH_P_AOE),
240  .func = aoenet_rcv,
241 };
242 
243 int __init
245 {
246  skb_queue_head_init(&skbtxq);
247  init_waitqueue_head(&txwq);
248  spin_lock_init(&txlock);
249  kts.lock = &txlock;
250  kts.fn = tx;
251  kts.waitq = &txwq;
252  kts.id = 0;
253  snprintf(kts.name, sizeof(kts.name), "aoe_tx%d", kts.id);
254  if (aoe_ktstart(&kts))
255  return -EAGAIN;
256  dev_add_pack(&aoe_pt);
257  return 0;
258 }
259 
260 void
262 {
263  aoe_ktstop(&kts);
264  skb_queue_purge(&skbtxq);
265  dev_remove_pack(&aoe_pt);
266 }
267 
ktstate::name
char name[12]
Definition: aoe.h:202
aoe_atahdr::aflags
unsigned char aflags
Definition: aoe.h:52
u32
uint32_t u32
Definition: dat.h:20
aoe_errlist
static char * aoe_errlist[]
Definition: aoenet.c:17
AOEFL_ERR
Definition: aoe.h:23
WHITESPACE
#define WHITESPACE
Definition: aoe.h:9
aoe_iflist
static char aoe_iflist[IFLISTSZ]
Definition: aoenet.c:31
tx
static int tx(int id)
Definition: aoenet.c:54
ktstate
Definition: aoe.h:197
AOECMD_VEND_MIN
Definition: aoe.h:20
aoecmd_ata_rsp
struct sk_buff * aoecmd_ata_rsp(struct sk_buff *)
Definition: aoecmd.c:1385
aoe.h
skbtxq
static struct sk_buff_head skbtxq
Definition: aoenet.c:50
ktstate::waitq
wait_queue_head_t * waitq
Definition: aoe.h:200
ktstate::id
int id
Definition: aoe.h:204
AOEFL_RSP
Definition: aoe.h:22
MODULE_PARM_DESC
MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=dev1[,dev2...]\n")
IFLISTSZ
Definition: aoenet.c:28
AOEAFL_WRITE
Definition: aoe.h:28
aoe_ktstop
void aoe_ktstop(struct ktstate *k)
Definition: aoecmd.c:1339
txlock
static spinlock_t txlock
Definition: aoenet.c:49
ulong
unsigned long ulong
Definition: aoe-sancheck.c:30
aoenet_xmit
void aoenet_xmit(struct sk_buff *sl)
Definition: aoenet.c:159
NECODES
#define NECODES
Definition: aoenet.c:15
AOECMD_ATA
Definition: aoe.h:18
aoe_hdr::err
unsigned char err
Definition: aoe.h:44
aoe_atahdr
Definition: aoe.h:51
is_aoe_netif
int is_aoe_netif(struct net_device *ifp)
Definition: aoenet.c:108
AOECMD_CFG
Definition: aoe.h:19
aoecmd_cfg_rsp
void aoecmd_cfg_rsp(struct sk_buff *)
Definition: aoecmd.c:1618
aoe_pt
static struct packet_type aoe_pt
Definition: aoenet.c:238
aoe_hdr::tag
u32 tag
Definition: aoe.h:48
ktstate::lock
spinlock_t * lock
Definition: aoe.h:203
aoe_strcspn
static size_t aoe_strcspn(const char *s, const char *reject)
Definition: aoenet.c:90
aoe_hdr::cmd
unsigned char cmd
Definition: aoe.h:47
txwq
static wait_queue_head_t txwq
Definition: aoenet.c:35
aoe_iflist_setup
static int __init aoe_iflist_setup(char *str)
Definition: aoenet.c:39
mac_addr
unsigned long long mac_addr(char addr[6])
Definition: aoenet.c:148
ktstate::fn
int(* fn)(int)
Definition: aoe.h:201
module_param_string
module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600)
aoenet_rcv
static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
Definition: aoenet.c:178
aoe_hdr::major
u16 major
Definition: aoe.h:45
aoenet_init
int __init aoenet_init(void)
Definition: aoenet.c:244
aoe_hdr
Definition: aoe.h:39
set_aoe_iflist
int set_aoe_iflist(const char __user *user_str, size_t size)
Definition: aoenet.c:134
aoe_hdr::verfl
unsigned char verfl
Definition: aoe.h:43
aoenet_exit
void aoenet_exit(void)
Definition: aoenet.c:261
__setup
__setup("aoe_iflist=", aoe_iflist_setup)
ETH_P_AOE
#define ETH_P_AOE
Definition: aoe.h:14
kts
static struct ktstate kts
Definition: aoenet.c:36
aoe_ktstart
int aoe_ktstart(struct ktstate *k)
Definition: aoecmd.c:1346
aoe_hdr::minor
unsigned char minor
Definition: aoe.h:46