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