--- aoe.c.orig Wed Oct 5 09:01:07 2005 +++ aoe.c Sat Oct 8 23:55:56 2005 @@ -46,8 +46,8 @@ aoead(int fd) // advertise the virtual p->vercmd = 0x10 | Qread; len = qcget(p->data, 1024); p->len = htons(len); - if (write(fd, buf, len) == -1) - perror("write aoe id"); + if (putpkt(fd, buf, len) == -1) + perror("putpkt aoe id"); } int @@ -162,7 +162,7 @@ doaoe(Aoehdr *p) p->maj = htons(shelf); p->min = slot; p->flags |= Resp; - if (write(sfd, p, len) == -1) { + if (putpkt(sfd, (uchar *) p, len) == -1) { perror("write to network"); exit(1); } @@ -178,7 +178,7 @@ aoe(void) aoead(sfd); for (;;) { - n = read(sfd, buf, sizeof buf); + n = getpkt(sfd, buf, sizeof buf); if (n < 0) { perror("read network"); exit(1); --- dat.h.orig Wed Oct 5 09:17:05 2005 +++ dat.h Sat Oct 8 23:57:02 2005 @@ -19,7 +19,7 @@ enum { typedef unsigned char uchar; //typedef unsigned short ushort; -//typedef unsigned long ulong; +typedef unsigned long ulong; typedef long long vlong; typedef struct Aoehdr Aoehdr; --- fns.h.orig Wed Oct 5 15:05:08 2005 +++ fns.h Sat Oct 8 23:54:34 2005 @@ -22,4 +22,6 @@ int dial(char *); int getea(int, char *, uchar *); int putsec(int, uchar *, vlong, int); int getsec(int, uchar *, vlong, int); +int putpkt(int, uchar *, int); +int getpkt(int, uchar *, int); vlong getsize(int); --- linux.c.orig Wed Oct 5 14:57:11 2005 +++ linux.c Sat Oct 8 23:53:48 2005 @@ -100,6 +100,18 @@ putsec(int fd, uchar *place, vlong lba, return write(fd, place, nsec * 512); } +int +getpkt(int fd, uchar *buf, int sz) +{ + return read(fd, buf, sz); +} + +int +putpkt(int fd, uchar *buf, int sz) +{ + return write(fd, buf, sz); +} + vlong getsize(int fd) { --- freebsd.c.orig Wed Oct 5 09:18:25 2005 +++ freebsd.c Sun Oct 9 16:06:32 2005 @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2005, Stacey Son + * All rights reserved. + */ + +// freebsd.c: low level access routines for FreeBSD +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dat.h" +#include "fns.h" + +#define BPF_DEV "/dev/bpf0" + +/* Packet buffer for getpkt() */ +static uchar *pktbuf = NULL; +static int pktbufsz = 0; + +int +dial(char *eth) +{ + char m; + int fd = -1; + struct bpf_version bv; + u_int v; + unsigned bufsize, linktype; + char device[sizeof BPF_DEV]; + struct ifreq ifr; + + /* packet filter for bpf */ + struct bpf_insn bpf_insns[] = { + /* Load the type into register */ + BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), + /* Does it match AoE Type (0x88a2)? No, goto INVALID */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x88a2, 0, 10), + /* Load the flags into register */ + BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 14), + /* Check to see if the Resp flag is set */ + BPF_STMT(BPF_ALU+BPF_AND+BPF_K, Resp), + /* Yes, goto INVALID */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 7), + /* Load the command into register */ + BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 19), + /* Is this a ATAcmd? No, goto VALID */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ATAcmd, 0, 4), + /* Load the shelf number into register */ + BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16), + /* Does it match shelf number? No, goto INVALID */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (u_int) shelf, 0, 3), + /* Load the slot number into register */ + BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18), + /* Does it match shelf number? No, goto INVALID */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (u_int) slot, 0, 1), + /* VALID: return -1 (allow the packet to be read) */ + BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + /* INVALID: return 0 (ignore the packet) */ + BPF_STMT(BPF_RET+BPF_K, 0), + }; + + struct bpf_program bpf_program = { + sizeof(bpf_insns)/sizeof(struct bpf_insn), + bpf_insns + }; + + + strncpy(device, BPF_DEV, sizeof BPF_DEV); + + /* find a bpf device we can use, check /dev/bpf[0-9] */ + for (m = '0'; m <= '9'; m++) { + device[sizeof(BPF_DEV)-2] = m; + + if ((fd = open(device, O_RDWR)) > 0) + break; + } + + if (fd < 0) { + perror("open"); + return -1; + } + + if (ioctl(fd, BIOCVERSION, &bv) < 0) { + perror("BIOCVERSION"); + goto bad; + } + + if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) { + fprintf(stderr, + "kernel bpf filter out of date\n"); + goto bad; + } + + /* + * Try finding a good size for the buffer; 65536 may be too + * big, so keep cutting it in half until we find a size + * that works, or run out of sizes to try. + * + */ + for (v = 65536; v != 0; v >>= 1) { + (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); + + (void)strncpy(ifr.ifr_name, eth, + sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) + break; /* that size worked; we're done */ + + if (errno != ENOBUFS) { + fprintf(stderr, "BIOCSETIF: %s: %s\n", + eth, strerror(errno)); + goto bad; + } + } + if (v == 0) { + fprintf(stderr, + "BIOCSBLEN: %s: No buffer size worked\n", eth); + goto bad; + } + + /* Allocate memory for the packet buffer */ + pktbufsz = v; + if ((pktbuf = malloc(pktbufsz)) == NULL) { + perror("malloc"); + goto bad; + } + + /* Don't wait for buffer to be full or timeout */ + v = 1; + if (ioctl(fd, BIOCIMMEDIATE, &v) < 0) { + perror("BIOCIMMEDIATE"); + goto bad; + } + + /* Only read incoming packets */ + v = 0; + if (ioctl(fd, BIOCSSEESENT, &v) < 0) { + perror("BIOCSSEESENT"); + goto bad; + } + + /* Don't complete ethernet hdr */ + v = 1; + if (ioctl(fd, BIOCSHDRCMPLT, &v) < 0) { + perror("BIOCSHDRCMPLT"); + goto bad; + } + + /* Get the data link layer type. */ + if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { + perror("BIOCGDLT"); + goto bad; + } + linktype = v; + + /* Get the filter buf size */ + if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { + perror("BIOCGBLEN"); + goto bad; + } + bufsize = v; + + if (ioctl(fd, BIOCSETF, (caddr_t)&bpf_program) < 0) { + perror("BIOSETF"); + goto bad; + } + + return(fd); + +bad: + close(fd); + return(-1); +} + +int +getea(int s, char *eth, uchar *ea) +{ + int mib[6]; + int len; + char *buf, *next, *end; + struct if_msghdr *ifm; + struct sockaddr_dl *sdl; + + + mib[0] = CTL_NET; mib[1] = AF_ROUTE; + mib[2] = 0; mib[3] = AF_LINK; + mib[4] = NET_RT_IFLIST; mib[5] = 0; + + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { + return (-1); + } + + if (!(buf = (char *) malloc(len))) { + return (-1); + } + + if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { + free(buf); + return (-1); + } + end = buf + len; + + for (next = buf; next < end; next += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type == RTM_IFINFO) { + sdl = (struct sockaddr_dl *)(ifm + 1); + if (strncmp(&sdl->sdl_data[0], eth, + sdl->sdl_nlen) == 0) { + memcpy(ea, LLADDR(sdl), ETHER_ADDR_LEN); + break; + } + + } + + } + + free(buf); + return(0); +} + + +int +getsec(int fd, uchar *place, vlong lba, int nsec) +{ + lseek(fd, lba * 512, 0); + return read(fd, place, nsec * 512); +} + +int +putsec(int fd, uchar *place, vlong lba, int nsec) +{ + lseek(fd, lba * 512, 0); + return write(fd, place, nsec * 512); +} + +static int pktn = 0; +static uchar *pktbp = NULL; + +int +getpkt(int fd, uchar *buf, int sz) +{ + register struct bpf_hdr *bh; + register int pktlen, retlen; + + if (pktn <= 0) { + if ((pktn = read(fd, pktbuf, pktbufsz)) < 0) { + perror("read"); + exit(1); + } + pktbp = pktbuf; + } + + bh = (struct bpf_hdr *) pktbp; + retlen = (int) bh->bh_caplen; + /* This memcpy() is currently needed */ + memcpy(buf, (void *)(pktbp + bh->bh_hdrlen), + retlen > sz ? sz : retlen); + pktlen = bh->bh_hdrlen + bh->bh_caplen; + + pktbp = pktbp + BPF_WORDALIGN(pktlen); + pktn -= (int) BPF_WORDALIGN(pktlen); + + return retlen; +} + +int +putpkt(int fd, uchar *buf, int sz) +{ + return write(fd, buf, sz); +} + +vlong +getsize(int fd) +{ + vlong size; + struct stat s; + int n; + struct disklabel lab; + + // Try getting disklabel from block dev + if ((n = ioctl(fd, DIOCGDINFO, lab)) != -1) { + size = lab.d_secsize * lab.d_secperunit; + } else { + // must not be a block special dev + if (fstat(fd, &s) == -1) { + perror("getsize"); + exit(1); + } + size = s.st_size; + } + printf("ioctl returned %d\n", n); + printf("%lld bytes\n", size); + return size; +} --- makefile.fbsd.orig Wed Oct 5 09:18:32 2005 +++ makefile.fbsd Sat Oct 8 23:57:31 2005 @@ -0,0 +1,12 @@ +# makefile for vblade + +O=aoe.o freebsd.o ata.o +CFLAGS += -Wall -g -O2 + +vblade: $O + cc -o vblade $O + +$O: dat.h fns.h + +clean : + rm -f $O vblade