Browse Source

Import upstream version 6

Ed L. Cashin 18 years ago
commit
0359ef052e
15 changed files with 1193 additions and 0 deletions
  1. 340 0
      COPYING
  2. 12 0
      HACKING
  3. 33 0
      NEWS
  4. 76 0
      README
  5. 232 0
      aoe.c
  6. 159 0
      ata.c
  7. 1 0
      config.h
  8. 115 0
      dat.h
  9. 25 0
      fns.h
  10. 122 0
      linux.c
  11. 11 0
      linux.h
  12. 12 0
      makefile
  13. BIN
      vblade
  14. 49 0
      vblade.8
  15. 6 0
      vbladed

+ 340 - 0
COPYING

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 12 - 0
HACKING

@@ -0,0 +1,12 @@
+Contributions to the vblade are welcome.  
+
+In contributing, though, please stay true to the original simplicity
+of the software.  Many open source projects suffer from the "creeping
+feature demon" phenomenon.  If you think the vblade needs a great new
+feature, first seriously try to think of a way to accomplish your goal
+without adding to the vblade itself.
+
+Patches should be clean (to the point and easy to read) and should do
+one thing.  Send multiple patches if necessary.  Patches should be
+generated with "diff -uprN" if possible, and should be designed to be
+applied with "patch -p1".

+ 33 - 0
NEWS

@@ -0,0 +1,33 @@
+-*- change-log -*-
+	
+2005-08-31 20:14:12 GMT Ed L. Cashin <ecashin@coraid.com>
+	ATA identify: don't juggle bytes in shorts on big endian arch
+	add manpage for vblade, vbladed
+	release vblade-6
+	
+2005-03-17 15:24:30 GMT	Ed L. Cashin <ecashin@coraid.com>
+	follow up on vblade-2's off-by-one patch, making end of device usable
+	release vblade-5
+	
+2005-03-15 22:03:17 GMT	Ed L. Cashin <ecashin@coraid.com>
+	don't rely on kernel headers for defining the aoe type 0x88a2
+	release vblade-4
+	
+2005-03-15 17:27:01 GMT	Ed L. Cashin <ecashin@coraid.com>
+	docs: aoe-2.6-7 is the first driver to support multiple blades per mac
+	release vblade-3
+	
+2005-03-11 18:30:26 GMT	Ed L. Cashin <ecashin@coraid.com>
+	put 64-bit configuration into config.h file
+	don't use uninitialized variables
+	broadcast config query on startup
+	clarify desired patch format in HACKING
+	add sah@coraid.com's vblade-1.ata.c.patch: fix off-by-one and ext LBA
+	add docs, remove daemonizing code from vblade
+	release vblade-2
+	
+2005-02-08 20:21:52 GMT	Ed L. Cashin <ecashin@coraid.com>
+	starting documentation
+	add script that daemonizes vblade process, logging output
+	make vblade sources -Wall clean, use daemon(3)
+	release vblade-1

+ 76 - 0
README

@@ -0,0 +1,76 @@
+This is a beta release of vblade, the virtual EtherDrive (R) blade.
+The vblade is a program that makes a seekable file available over an
+ethernet local area network (LAN) via the ATA over Ethernet (AoE)
+protocol.
+
+The seekable file is typically a block device like /dev/md0 but even
+regular files will work.  When vblade exports the block storage over
+AoE it becomes a storage target.  Another host on the same LAN can
+access the storage if it has a compatible aoe kernel driver.
+
+The Linux aoe driver for the 2.6 kernel is compatible if you use
+aoe-2.6-7 or newer.  You can use older aoe drivers but you will only
+be able to see one vblade per MAC address.
+
+The following command should build the vblade program:
+
+  make
+
+There is a "vbladed" script that daemonizes the program and sends its
+output to the logger program.  Make sure you have logger installed if
+you would like to run vblade as a daemon with the vbladed script.
+
+  ecashin@kokone vblade$ echo 'I have logger' | logger
+  ecashin@kokone vblade$ tail -3 /var/log/messages
+  Feb  8 14:52:49 kokone -- MARK --
+  Feb  8 15:12:49 kokone -- MARK --
+  Feb  8 15:19:56 kokone logger: I have logger
+
+Here is a short example showing how to export a block device with a
+vblade.  (This is a loop device backed by a sparse file, but you could
+use any seekable file instead of /dev/loop7.)
+
+  ecashin@kokone vblade$ make
+  cc -Wall   -c -o aoe.o aoe.c
+  cc -Wall   -c -o linux.o linux.c
+  cc -Wall   -c -o ata.o ata.c
+  cc -o vblade aoe.o linux.o ata.o
+  ecashin@kokone vblade$ su
+  Password: 
+  root@kokone vblade# modprobe loop
+  root@kokone vblade# dd if=/dev/zero bs=1k count=1 seek=`expr 1024 \* 4096` of=bd
+  -file
+  1+0 records in
+  1+0 records out
+  1024 bytes transferred in 0.009901 seconds (103423 bytes/sec)
+  root@kokone vblade# losetup /dev/loop7 bd-file  
+  root@kokone vblade# ./vblade 9 0 eth0 /dev/loop7 
+  ioctl returned 0
+  4294968320 bytes
+  pid 16967: e9.0, 8388610 sectors
+
+Here's how you can use the Linux aoe driver to access the storage from
+another host on the LAN.
+
+  ecashin@kokone ecashin$ ssh makki
+  Last login: Mon Feb  7 10:25:04 2005
+  ecashin@makki ~$ su
+  Password: 
+  root@makki ecashin# modprobe aoe
+  root@makki ecashin# aoe-stat
+      e9.0            eth1              up
+  root@makki ecashin# mkfs -t ext3 /dev/etherd/e9.0
+  mke2fs 1.35 (28-Feb-2004)
+...
+  Creating journal (8192 blocks): done
+  Writing superblocks and filesystem accounting information: done
+  
+  This filesystem will be automatically checked every 24 mounts or
+  180 days, whichever comes first.  Use tune2fs -c or -i to override.
+  root@makki ecashin# mkdir /mnt/e9.0
+  root@makki ecashin# mount /dev/etherd/e9.0 /mnt/e9.0
+  root@makki ecashin# echo hooray > /mnt/e9.0/test.txt
+  root@makki ecashin# cat /mnt/e9.0/test.txt
+  hooray
+
+Remember: be as careful with these devices as you would with /dev/hda!

+ 232 - 0
aoe.c

@@ -0,0 +1,232 @@
+// aoe.c: the ATA over Ethernet virtual EtherDrive (R) blade
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include "dat.h"
+#include "fns.h"
+
+// dummy for testing
+int
+qcget(uchar *p, int len)
+{
+	memset(p, 0xff, len);
+	return len;
+}
+
+int
+qcset(uchar *p, int len)
+{
+	return len;
+}
+
+void
+aoead(int fd)			// advertise the virtual blade
+{
+	int len;
+	uchar buf[2000];
+	Conf *p;
+
+	p = (Conf *)buf;
+	memset(p, 0, sizeof *p);
+	memset(p->h.dst, 0xff, 6);
+	memmove(p->h.src, mac, 6);
+	p->h.type = htons(0x88a2);
+	p->h.flags = Resp;
+	p->h.maj = htons(shelf);
+	p->h.min = slot;
+	p->h.cmd = Config;
+	p->bufcnt = htons(Bufcount);
+	p->firmware = htons(FWV);
+	p->vercmd = 0x10 | Qread;
+	len = qcget(p->data, 1024);
+	p->len = htons(len);
+	if (write(fd, buf, len) == -1)
+		perror("write aoe id");
+}
+
+int
+isbcast(uchar *ea)		// replace with assembler routine
+{
+	uchar *b = (uchar *)"\377\377\377\377\377\377";
+
+	return memcmp(ea, b, 6) == 0;
+}
+
+long long
+getlba(uchar *p)
+{
+	vlong v;
+	int i;
+
+	v = 0;
+	for (i = 0; i < 6; i++)
+		v |= (vlong)(*p++) << i * 8;
+	return v;
+}
+
+int
+aoeata(Ata *p)	// do ATA reqeust
+{
+	Ataregs r;
+	int len = 60;
+
+	if (p->sectors && (p->aflag & Write) == 0)
+		len = sizeof (Ata);
+	r.lba = getlba(p->lba);
+	r.sectors = p->sectors;
+	r.feature = p->err;
+	r.cmd = p->cmd;
+	atacmd(&r, p->data);
+	p->sectors = r.sectors;
+	p->err = r.err;
+	p->cmd = r.status;
+	return len;
+}
+
+int
+confcmd(Conf *p)	// process conf request
+{
+	uchar buf[1024];
+	int len = 0, len2;
+
+	switch (p->vercmd & 0xf) {
+	case Qread:
+		len = qcget(p->data, 1024);
+		p->len = htons(len);
+		break;
+	case Qtest:
+		len = qcget(buf, 1024);
+		if (len != ntohs(p->len))
+			return 0;
+		if (memcmp(buf, p->data, len) != 0)
+			return 0;
+		memmove(p->data, buf, len);
+		break;
+	case Qprefix:
+		len = qcget(buf, 1024);
+		len2 = ntohs(p->len);
+		if (len2 > len)
+			return 0;
+		if (memcmp(buf, p->data, len2) != 0)
+			return 0;
+		memmove(p->data, buf, len);
+		p->len = htons(len);
+		break;
+	case Qset:
+		if (qcget(buf, 1024) > 0) {
+			p->h.flags |= Error;
+			p->h.error = ConfigErr;
+			break;
+		}
+		len = 1024;
+		// fall thru
+	case Qfset:
+		len = ntohs(p->len);
+		qcset(p->data, len);
+		break;
+	default:
+		p->h.flags |= BadArg;
+	}
+	p->bufcnt = htons(Bufcount);
+	p->firmware = htons(FWV);
+	p->vercmd |= 0x10;
+	return len;
+}
+
+void
+doaoe(Aoehdr *p)
+{
+	int len;
+
+	switch (p->cmd) {
+	case ATAcmd:
+		len = aoeata((Ata*)p);
+		break;
+	case Config:
+		if ((len = confcmd((Conf *)p)) == 0)
+			return;
+		break;
+	default:
+		p->error = BadCmd;
+		len = 1024;
+		break;
+	}
+	memmove(p->dst, p->src, 6);
+	memmove(p->src, mac, 6);
+	p->maj = htons(shelf);
+	p->min = slot;
+	p->flags |= Resp;
+	if (write(sfd, p, len) == -1) {
+		perror("write to network");
+		exit(1);
+	}
+}
+
+void
+aoe(void)
+{
+	Aoehdr *p;
+	uchar buf[1400];
+	int n, sh;
+
+	aoead(sfd);
+
+	for (;;) {
+		n = read(sfd, buf, sizeof buf);
+		if (n < 0) {
+			perror("read network");
+			exit(1);
+		}
+		if (n < 60)
+			continue;
+		p = (Aoehdr *)buf;
+		if (ntohs(p->type) != 0x88a2)
+			continue;
+		if (p->flags & Resp)
+			continue;
+		sh = ntohs(p->maj);
+		if (sh != shelf && sh != (ushort)~0)
+			continue;
+		if (p->min != slot && p->min != (uchar)~0)
+			continue;
+		doaoe(p);
+	}
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "usage: %s <shelf> <slot> <ethn> <device>\n", 
+		progname);
+	exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+	setbuf(stdin, NULL);
+	progname = *argv;
+	if (argc != 5)
+		usage();
+	bfd = open(argv[4], O_RDWR);
+	if (bfd == -1) {
+		perror("open");
+		exit(1);
+	}
+	shelf = atoi(argv[1]);
+	slot = atoi(argv[2]);
+	size = getsize(bfd);
+	size /= 512;
+	sfd = dial(argv[3]);
+	getea(sfd, argv[3], mac);
+	printf("pid %ld: e%d.%d, %lld sectors\n",
+		(long) getpid(), shelf, slot, size);
+	fflush(stdout);
+	aoe();
+	return 0;
+}

+ 159 - 0
ata.c

@@ -0,0 +1,159 @@
+// ata.c:  ATA simulator for vblade
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include "dat.h"
+#include "fns.h"
+
+enum {
+	// err bits
+	UNC =	1<<6,
+	MC =	1<<5,
+	IDNF =	1<<4,
+	MCR =	1<<3,
+	ABRT = 	1<<2,
+	NM =	1<<1,
+
+	// status bits
+	BSY =	1<<7,
+	DRDY =	1<<6,
+	DF =		1<<5,
+	DRQ =	1<<3,
+	ERR =	1<<0,
+};
+
+static ushort ident[256] = {
+	[47] 0x8000,
+	[49] 0x0200,
+	[50] 0x4000,
+	[83] 0x5400,
+	[84] 0x4000,
+	[86] 0x1400,
+	[87] 0x4000,
+	[93] 0x400b,
+};
+
+static void
+setfld(ushort *a, int idx, int len, char *str)	// set field in ident
+{
+	uchar *p;
+
+	p = (uchar *)(a+idx);
+	while (len > 0) {
+		if (*str == 0)
+			p[1] = ' ';
+		else
+			p[1] = *str++;
+		if (*str == 0)
+			p[0] = ' ';
+		else
+			p[0] = *str++;
+		p += 2;
+		len -= 2;
+	}
+}
+
+static void
+setlba28(ushort *ident, vlong lba)
+{
+	uchar *cp;
+
+	cp = (uchar *) &ident[60];
+	*cp++ = lba;
+	*cp++ = lba >>= 8;
+	*cp++ = lba >>= 8;
+	*cp++ = (lba >>= 8) & 0xf;
+}
+
+static void
+setlba48(ushort *ident, vlong lba)
+{
+	uchar *cp;
+
+	cp = (uchar *) &ident[100];
+	*cp++ = lba;
+	*cp++ = lba >>= 8;
+	*cp++ = lba >>= 8;
+	*cp++ = lba >>= 8;
+	*cp++ = lba >>= 8;
+	*cp++ = lba >>= 8;
+}
+		
+void
+atainit(void)
+{
+	char buf[64];
+
+	setfld(ident, 27, 40, "Coraid EtherDrive vblade");
+	sprintf(buf, "V%d.%d\n", 4, 0);
+	setfld(ident, 23, 8, buf);
+	setfld(ident, 10, 20, "SSN HERE");
+}
+
+
+/* The ATA spec is weird in that you specify the device size as number
+ * of sectors and then address the sectors with an offset.  That means
+ * with LBA 28 you shouldn't see an LBA of all ones.  Still, we don't
+ * check for that.
+ */
+void
+atacmd(Ataregs *p, uchar *dp)		// do the ata cmd
+{
+	vlong lba;
+	ushort *ip;
+	int n;
+	enum { MAXLBA28SIZE = 0x0fffffff };
+
+	switch (p->cmd) {
+	case 0x20:		// read sectors
+	case 0x30:		// write sectors
+		lba = p->lba & MAXLBA28SIZE;
+		break;
+	case 0x24:		// read sectors ext
+	case 0x34:		// write sectors ext
+		lba = p->lba & 0x0000ffffffffffffLL;	// full 48
+		break;
+	case 0xe7:		// flush cache
+		return;
+	case 0xec:		// identify device
+		memmove(dp, ident, 512);
+		ip = (ushort *)dp;
+		if (size & ~MAXLBA28SIZE)
+			setlba28(ip, MAXLBA28SIZE);
+		else
+			setlba28(ip, size);
+		setlba48(ip, size);
+		p->err = 0;
+		p->status = DRDY;
+		return;
+	default:
+		p->status = DRDY | ERR;
+		p->err = ABRT;
+		return;
+	}
+
+	if (lba + p->sectors > size) {
+		p->err = IDNF;
+		p->status = DRDY | ERR;
+		p->lba = lba;
+		return;
+	}
+	if (p->cmd == 0x20 || p->cmd == 0x24) {
+		n = getsec(bfd, dp, lba, p->sectors);
+		if (n == -1) {
+			perror("read block device");
+			p->status |= ERR;
+		}
+	} else {
+		n = putsec(bfd, dp, lba, p->sectors);
+		if (n == -1) {
+			perror("write block device");
+			p->status |= ERR;
+		}
+	}
+	p->lba += p->sectors;
+	p->sectors = 0;
+	p->status = DRDY;
+	p->err = 0;
+}

+ 1 - 0
config.h

@@ -0,0 +1 @@
+#define _FILE_OFFSET_BITS 64 

+ 115 - 0
dat.h

@@ -0,0 +1,115 @@
+/* dat.h: include file for vblade AoE target */
+
+#define	nil	((void *)0)
+/*
+ *	tunable variables
+ */
+
+enum {
+	FWV			= 0x4000,		// Firmware version
+};
+
+#undef major
+#undef minor
+#undef makedev
+
+#define	major(x)		((x) >> 24 & 0xFF)
+#define	minor(x)		((x) & 0xffffff)
+#define	makedev(x, y)	((x) << 24 | (y))
+
+typedef unsigned char uchar;
+//typedef unsigned short ushort;
+//typedef unsigned long ulong;
+typedef long long vlong;
+
+typedef struct Aoehdr Aoehdr;
+typedef struct Ata Ata;
+typedef struct Conf Conf;
+typedef struct Ataregs Ataregs;
+
+
+struct Ataregs
+{
+	vlong	lba;
+	uchar	cmd;
+	uchar	status;
+	uchar	err;
+	uchar	feature;
+	uchar	sectors;
+};
+
+struct Aoehdr
+{
+	uchar	dst[6];
+	uchar	src[6];
+	ushort	type;
+	uchar	flags;
+	uchar	error;
+	ushort	maj;
+	uchar	min;
+	uchar	cmd;
+	uchar	tag[4];
+};
+
+struct Ata
+{
+	Aoehdr	h;
+	uchar	aflag;
+	uchar	err;
+	uchar	sectors;
+	uchar	cmd;
+	uchar	lba[6];
+	uchar	resvd[2];
+	uchar	data[1024];
+};
+
+struct Conf
+{
+	Aoehdr	h;
+	ushort	bufcnt;
+	ushort	firmware;
+	uchar	filler;
+	uchar	vercmd;
+	ushort	len;
+	uchar	data[1024];
+};
+
+
+enum {
+	AoEver = 1,
+
+	ATAcmd = 0,		// command codes
+	Config,
+
+	Resp = (1<<3),		// flags
+	Error = (1<<2),
+
+	BadCmd = 1,
+	BadArg,
+	DevUnavailable,
+	ConfigErr,
+	BadVersion,
+
+	Write = (1<<0),
+	Async = (1<<1),
+	Device = (1<<4),
+	Extend = (1<<6),
+
+	Qread = 0,
+	Qtest,
+	Qprefix,
+	Qset,
+	Qfset,
+
+	Nretries = 3,
+
+	Bufcount = 32,
+};
+
+int	shelf, slot;
+ulong	aoetag;
+uchar	mac[6];
+int	bfd;		// block file descriptor
+int	sfd;		// socket file descriptor
+vlong	size;		// size of vblade
+char	*progname;

+ 25 - 0
fns.h

@@ -0,0 +1,25 @@
+// fns.h: function prototypes
+
+// aoe.c
+
+void	aoe(void);
+void	aoeinit(void);
+void	aoequery(void);
+void	aoeconfig(void);
+void	aoead(int);
+void	aoeflush(int, int);
+void	aoetick(void);
+void	aoerequest(int, int, vlong, int, uchar *, int);
+
+// ata.c
+
+void	atainit(void);
+void	atacmd(Ataregs *, uchar *);
+
+// os specific
+
+int	dial(char *);
+int	getea(int, char *, uchar *);
+int	putsec(int, uchar *, vlong, int);
+int	getsec(int, uchar *, vlong, int);
+vlong	getsize(int);

+ 122 - 0
linux.c

@@ -0,0 +1,122 @@
+// linux.c: low level access routines for Linux
+#include "config.h"
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <features.h>    /* for the glibc version number */
+#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
+#include <netpacket/packet.h>
+#include <net/ethernet.h>     /* the L2 protocols */
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>   /* The L2 protocols */
+#endif
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <linux/fs.h>
+#include <sys/stat.h>
+
+#include "dat.h"
+#include "fns.h"
+
+int	getindx(int, char *);
+int	getea(int, char *, uchar *);
+
+
+
+int
+dial(char *eth)		// get us a raw connection to an interface
+{
+	int i;
+	int n, s;
+	struct sockaddr_ll sa;
+	enum { aoe_type = 0x88a2 };
+
+	memset(&sa, 0, sizeof sa);
+	s = socket(PF_PACKET, SOCK_RAW, htons(aoe_type));
+	if (s == -1) {
+		perror("got bad socket");
+		return -1;
+	}
+	i = getindx(s, eth);
+	sa.sll_family = AF_PACKET;
+	sa.sll_protocol = htons(0x88a2);
+	sa.sll_ifindex = i;
+	n = bind(s, (struct sockaddr *)&sa, sizeof sa);
+	if (n == -1) {
+		perror("bind funky");
+		return -1;
+	}
+	return s;
+}
+
+int
+getindx(int s, char *name)	// return the index of device 'name'
+{
+	struct ifreq xx;
+	int n;
+
+	strcpy(xx.ifr_name, name);
+	n = ioctl(s, SIOCGIFINDEX, &xx);
+	if (n == -1)
+		return -1;
+	return xx.ifr_ifindex;
+}
+
+int
+getea(int s, char *name, uchar *ea)
+{
+	struct ifreq xx;
+	int n;
+
+        strcpy(xx.ifr_name, name);
+	n = ioctl(s, SIOCGIFHWADDR, &xx);
+	if (n == -1) {
+		perror("Can't get hw addr");
+		return 0;
+	}
+	memmove(ea, xx.ifr_hwaddr.sa_data, 6);
+	return 1;
+}
+
+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);
+}
+
+vlong
+getsize(int fd)
+{
+	vlong size;
+	struct stat s;
+	int n;
+
+	n = ioctl(fd, BLKGETSIZE64, &size);
+	if (n == -1) {	// must not be a block special
+		n = fstat(fd, &s);
+		if (n == -1) {
+			perror("getsize");
+			exit(1);
+		}
+		size = s.st_size;
+	}
+	printf("ioctl returned %d\n", n);
+	printf("%lld bytes\n", size);
+	return size;
+}

+ 11 - 0
linux.h

@@ -0,0 +1,11 @@
+// linux.h: header for linux.c
+
+typedef unsigned char uchar;
+typedef long long vlong;
+
+int	dial(char *);
+int	getindx(int, char *);
+int	getea(int, char *, uchar *);
+int	getsec(int, uchar *, vlong, int);
+int	putsec(int, uchar *, vlong, int);
+vlong	getsize(int);

+ 12 - 0
makefile

@@ -0,0 +1,12 @@
+# makefile for vblade
+
+O=aoe.o linux.o ata.o
+CFLAGS += -Wall -g -O2
+
+vblade: $O
+	cc -o vblade $O
+
+$O: dat.h fns.h
+
+clean :
+	rm -f $O vblade

BIN
vblade


+ 49 - 0
vblade.8

@@ -0,0 +1,49 @@
+.TH vblade 8
+.SH NAME
+vblade, vbladed \- export data via ATA over Ethernet
+.SH SYNOPSIS
+.nf
+.B vblade {shelf} {slot} {netif} {filename}
+.fi
+.SH DESCRIPTION
+The
+.I vblade
+command starts a process that uses raw sockets to perform ATA over
+Ethernet, acting like a virtual EtherDrive (R) blade.
+.PP
+The 
+.I vbladed
+script can be used to daemonize the vblade process,
+detaching it from your terminal and sending its output to the system
+logs.
+.SS Arguments
+.TP
+\fBshelf\fP
+This should be the shelf address (major AoE address) of the AoE device
+to create.
+.TP
+\fBslot\fP
+This should be the slot address (minor AoE address) of the AoE device
+to create.
+.TP
+\fBnetif\fP
+The name of the ethernet network interface to use for AoE
+communications.
+.TP
+\fBfilename\fP
+The name of the regular file or block device to export.
+.SH EXAMPLE
+In this example, the root user on a host named
+.I nai
+exports a file named "3TB" to the LAN on eth0 using AoE shelf address 11
+and slot address 1.  The process runs in the foreground.  Using 
+.I vbladed
+would have resulted in the process running as a daemon in the
+background.
+.IP
+.EX
+ nai:~# vblade 11 1 eth0 /data/3TB
+.EE
+.LP
+.SH AUTHOR
+Brantley Coile (brantley@coraid.com)

+ 6 - 0
vbladed

@@ -0,0 +1,6 @@
+#! /bin/sh
+# run a vblade daemon using a logger process
+# output is directed to syslogd
+#
+
+sh -c "`dirname $0`/vblade - $* < /dev/null 2>&1 | logger -t vbladed" &