/* enters with txlock held */ staticint
tx(int id) __must_hold(&txlock)
{ struct sk_buff *skb; struct net_device *ifp;
while ((skb = skb_dequeue(&skbtxq))) {
spin_unlock_irq(&txlock);
ifp = skb->dev; if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit())
pr_warn("aoe: packet could not be sent on %s. %s\n",
ifp ? ifp->name : "netif", "consider increasing tx_queue_len");
dev_put(ifp);
spin_lock_irq(&txlock);
} return 0;
}
int
is_aoe_netif(struct net_device *ifp)
{ registerchar *p, *q; registerint len;
if (aoe_iflist[0] == '\0') return 1;
p = aoe_iflist + strspn(aoe_iflist, WHITESPACE); for (; *p; p = q + strspn(q, WHITESPACE)) {
q = p + strcspn(p, WHITESPACE); if (q != p)
len = q - p; else
len = strlen(p); /* last token in aoe_iflist */
if (strlen(ifp->name) == len && !strncmp(ifp->name, p, len)) return 1; if (q == p) break;
}
return 0;
}
int
set_aoe_iflist(constchar __user *user_str, size_t size)
{ if (size >= IFLISTSZ) return -EINVAL;
if (copy_from_user(aoe_iflist, user_str, size)) {
printk(KERN_INFO "aoe: copy from user failed\n"); return -EFAULT;
}
aoe_iflist[size] = 0x00; return 0;
}
/* * (1) len doesn't include the header by default. I want this.
*/ staticint
aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
{ struct aoe_hdr *h; struct aoe_atahdr *ah;
u32 n; int sn;
if (dev_net(ifp) != &init_net) gotoexit;
skb = skb_share_check(skb, GFP_ATOMIC); if (skb == NULL) return 0; if (!is_aoe_netif(ifp)) gotoexit;
skb_push(skb, ETH_HLEN); /* (1) */
sn = sizeof(*h) + sizeof(*ah); if (skb->len >= sn) {
sn -= skb_headlen(skb); if (sn > 0 && !__pskb_pull_tail(skb, sn)) gotoexit;
}
h = (struct aoe_hdr *) skb->data;
n = get_unaligned_be32(&h->tag); if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) gotoexit;
if (h->verfl & AOEFL_ERR) {
n = h->err; if (n > NECODES)
n = 0; if (net_ratelimit())
printk(KERN_ERR "%s%d.%d@%s; ecode=%d '%s'\n", "aoe: error packet from ",
get_unaligned_be16(&h->major),
h->minor, skb->dev->name,
h->err, aoe_errlist[n]); gotoexit;
}
switch (h->cmd) { case AOECMD_ATA: /* ata_rsp may keep skb for later processing or give it back */
skb = aoecmd_ata_rsp(skb); break; case AOECMD_CFG:
aoecmd_cfg_rsp(skb); break; default: if (h->cmd >= AOECMD_VEND_MIN) break; /* don't complain about vendor commands */
pr_info("aoe: unknown AoE command type 0x%02x\n", h->cmd); break;
}
if (!skb) return 0; exit:
dev_kfree_skb(skb); return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.