Wednesday, January 17, 2007

Using the NetBSD iScsi Target code on Solaris

The NetBSD iScsi target will, quite happily, compile and run on Solaris. The code was developed by Alistair Crooks, and is based on code released by Intel, under the BSD licence.

To try it out, I used the Belenix LiveCD distribution of OpenSolaris.
(root)# uname -a
SunOS belenix 5.11 BeleniX0.4.3 i86pc i386 i86pc
(root)# gcc -v
Reading specs from /usr/foss/lib/gcc/i386-pc-solaris2.10/3.4.3/specs
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
(root)# cd tmp
(root)# curl -O
(root)# ls -l netbsd-iscsi-20060526.tar.gz
-rw------- 1 root root 239964 May 27 22:21 netbsd-iscsi-20060526.tar.gz
(root)# gunzip < netbsd-iscsi-20060526.tar.gz | tar xvf -
(root)# cd iscsi
(root)# cd src
(root)# ./configure
(root)# make
(root)# cd ../bin
(root)# ls -l
-rwx------ 1 root root 226580 May 27 22:24 iscsi-harness
-rwx------ 1 root root 219028 May 27 22:24 iscsi-target

I just wanted to use the iScsi target to confirm if the Microsoft iScsi initiator would work ok with it, and take some Ethereal traces of the initial login sequence. So I just used the following simple configuration file, which exports out a 100 mega byte file.
(root)# cat /etc/iscsi/targets
extent0 /tmp/iscsi-target0 0 100MB

target0 rw extent0
(root)# ./iscsi-target &
(root)# ls -l /tmp/iscsi-target0
-rw------- 1 root root 104857601 May 27 23:17 /tmp/iscsi-target0

I tried the target with v2.03 of the Microdoft iScsi initiator, and and I can report that every thing I tried worked ok.

You can browse the source code of the iScsi target at the NetBSD CVS server. To get the latest version of the code, it may be best to get it from the CVS server.

I've just noted that Alistair make some further changes to the code at the start of 2007, which are noted at this digest.

Sunday, January 14, 2007

Linux iScsi Target and the Inquiry LUN Response

Ok, last time we completed compiling and installing the Linux iScsi target. Now we need to configure it and start it. All I wanted to do, at this stage, was a simple test. So I just did the minimal amount of configuration. I was going to be running the target on Centos-4, running under VmWare, so it was easy to add a second virtual hard drive to the environment, in this case '/dev/sdb', to export out from the target.
# cat /etc/ietd.conf
#IncomingUser nwsmith secretsecret
Lun 0 /dev/sdb fileio
Alias iscsitest01

# service iscsi-target start
Starting iSCSI target service: [ OK ]

# netstat -ntlp | grep 3260
tcp 0 0* LISTEN 3160/ietd

# tail /var/log/messages
Jan 14 15:59:02 localhost kernel: iSCSI Enterprise Target Software - version 0.4.5
Jan 14 15:59:02 localhost kernel: iotype_init(91) register fileio
Jan 14 15:59:03 localhost kernel: target_param(109) d 1 8192 262144 65536 2 20 8 0
Jan 14 15:59:03 localhost iscsi-target: ietd startup succeeded

The Linux iScsi target seems to work fine with the Microsoft iScsi initiator (v2.03).

Ok, now we have the target running, one of the thing I wanted to look at was how the Linux iScsi target handled the initial login and connection from the Microsoft initiator. I was looking for how it handles the "Inquiry LUN" packet. I used Ethereal to capture and analyse the packets - filter on port 3260.

I had a look at the source code, and found what I was looking for in file "target_disk.c" and in function:
static int build_inquiry_response(struct iscsi_cmnd *cmnd)

By editing the values in this function, you can adjust the following fields in the response packet:

Version, Flags, Vendor Id:, Product Id:, Product Revision Level:

I tried changing some of these fields in the code, recompiling, restarting the target, and then used Ethereal to check that the response (from the target) to the (initiators) 'Inquiry' LUN packet changed as expected. And it did what I expected. (To change the Version returned, edit the line "data[2] = 3;").

The Version field indicates which version of SCSI is supported by the target. You can check which values are valid by reading the specification. The specification is called "SCSI Primary Commands - 3" or SPC-3 and you can download it from

In the case of the version field, the valid values are shown in table 84:
0x00 - The device does not claim conformance to any standard.
0x02 - Obsolete.
0x03 - The device complies to ANSI INCITS 301-1997 (SPC).
0x04 - The device complies to ANSI INCITS 351-2001 (SPC-2).
0x05 - The device complies to T10/1416-D (SPC-3).

Ok, I think that's enough detail for this post.

Saturday, January 13, 2007

Centos 4 and the Linux iScsi Target

I wanted to do some tests with the Microsoft iScsi initiator and the Linux iScsi target, but first I had to install and configure the target. I had Centos 4.4 (a RHEL4 Linux clone) setup in VmWare, so i thought that using that would be the easy way to do the test.

I had read in PcPro magazine, last year, issue 137 (March 2006) page 197, that the Linux iScsi target would compile & install on Centos-4, but they did not say exactly which version they used.

Ok, so I download the latest version "iscsitarget-0.4.14.tar.gz".

I knew there was a potential problem, as the README file said it needed kernel version of 2.6.14 or newer, and the CONFIG_CRYPTO_CRC32C option had to be enabled. Centos 4.4 uses kernel 2.6.9, but with many additional patches from latter kernels, and the PCpro people said it would be ok.

Ok, so lets try it:

# cat /etc/redhat-release
CentOS release 4.4 (Final)
# uname -a
Linux localhost.localdomain 2.6.9-42.0.3.EL #1 Fri Oct 6 05:59:54 CDT 2006 i686 i686 i386 GNU/Linux
# cat /usr/src/kernels/2.6.9-42.0.3.EL-i686/crypto/Kconfig | grep -A 6 CRC
config CRYPTO_CRC32C
tristate "CRC32c CRC algorithm"
depends on CRYPTO
select LIBCRC32C
Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
by iSCSI for header and data digests and by others.
See Castagnoli93. This implementation uses lib/libcrc32c.
Module will be crc32c.

# cd /home
# tar xfz iscsitarget-0.4.14.tar.gz
# chown -R root:root iscsitarget-0.4.14
# ll
drwxr-xr-x 7 root root 4096 Oct 19 10:48 iscsitarget-0.4.14
-rw-r--r-- 1 root root 92608 Mar 14 2006 iscsitarget-0.4.14.tar.gz
# cd iscsitarget-0.4.14
# export KERNELSRC=/usr/src/kernels/2.6.9-42.0.3.EL-i686/
# make
make -C usr
make[1]: Entering directory `/home/iscsitarget-0.4.14/usr'
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ietd.o ietd.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o iscsid.o iscsid.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o conn.o conn.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o session.o session.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o target.o target.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o message.o message.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ctldev.o ctldev.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o log.o log.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o chap.o chap.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o event.o event.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o param.o param.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o plain.o plain.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o isns.o isns.c
cc ietd.o iscsid.o conn.o session.o target.o message.o ctldev.o log.o chap.o event.o param.o plain.o isns.o -o ietd -lcrypto
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ietadm.o ietadm.c
cc ietadm.o param.o -o ietadm
make[1]: Leaving directory `/home/iscsitarget-0.4.14/usr'
make -C /lib/modules/2.6.9-42.0.3.EL/build SUBDIRS=/home/iscsitarget-0.4.14/kernel modules
make[1]: Entering directory `/usr/src/kernels/2.6.9-42.0.3.EL-i686'
CC [M] /home/iscsitarget-0.4.14/kernel/tio.o
CC [M] /home/iscsitarget-0.4.14/kernel/iscsi.o
CC [M] /home/iscsitarget-0.4.14/kernel/nthread.o
CC [M] /home/iscsitarget-0.4.14/kernel/wthread.o
CC [M] /home/iscsitarget-0.4.14/kernel/config.o
/home/iscsitarget-0.4.14/kernel/config.c:312: error: unknown field `unlocked_ioctl' specified in initializer
/home/iscsitarget-0.4.14/kernel/config.c:312: warning: initialization from incompatible pointer type
/home/iscsitarget-0.4.14/kernel/config.c:313: error: unknown field `compat_ioctl' specified in initializer
/home/iscsitarget-0.4.14/kernel/config.c:313: warning: initialization from incompatible pointer type
make[2]: *** [/home/iscsitarget-0.4.14/kernel/config.o] Error 1
make[1]: *** [_module_/home/iscsitarget-0.4.14/kernel] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.9-42.0.3.EL-i686'
make: *** [mods] Error 2

# cat /home/iscsitarget-0.4.14/kernel/config.c | grep -n ioctl
219:static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
312: .unlocked_ioctl = ioctl,
313: .compat_ioctl = ioctl,

Oops! It failed to compile.
Ok, let's google around and see who else has this problem...

It seems other people are getting the same sort of problem with the target versions 4.13 and 4.12 and the older Centos kernel 2.6.9-22.EL

I found this link, where you can download a patch for the target version 0.4.12, which should allow it to compile on kernel 2.6.9, but I did not try it, as it's a "quick hack - Use at your own risk". Maybe someone else can try this patch and give a report.

Ok, so should I dump Centos-4 for now and install Fedora 6, which has an up-to-date kernel. Or should I try and work out which version of the target it was that the Pcpro guy's were using? Ok, I choose the latter.

I went back and downloaded the older versions of the target. And to cut a long story short, I discovered that this version "iscsitarget-0.4.5.tar.gz" will compile on Centos-4. (If you look at the README for that version of the target, it says it is happy with kernel 2.6.10)
Here is the proof that it compiles:

# tar xfz iscsitarget-0.4.5.tar.gz
# chown -R root:root iscsitarget-0.4.5
# cd iscsitarget-0.4.5
# make
make -C usr
make[1]: Entering directory `/home/iscsitarget-0.4.5/usr'
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ietd.o ietd.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o iscsid.o iscsid.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o conn.o conn.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o session.o session.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o target.o target.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o message.o message.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ctldev.o ctldev.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o log.o log.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o md5.o md5.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o isns.o isns.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o sha1.o sha1.c
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o chap.o chap.c
cc ietd.o iscsid.o conn.o session.o target.o message.o ctldev.o log.o md5.o isns.o sha1.o chap.o -o ietd
cc -O2 -fno-inline -Wall -Wstrict-prototypes -g -I../include -c -o ietadm.o ietadm.c
cc ietadm.o ctldev.o -o ietadm
make[1]: Leaving directory `/home/iscsitarget-0.4.5/usr'
make -C /usr/src/kernels/2.6.9-42.0.3.EL-i686/ SUBDIRS=/home/iscsitarget-0.4.5/kernel modules
make[1]: Entering directory `/usr/src/kernels/2.6.9-42.0.3.EL-i686'
CC [M] /home/iscsitarget-0.4.5/kernel/tio.o
CC [M] /home/iscsitarget-0.4.5/kernel/iscsi.o
CC [M] /home/iscsitarget-0.4.5/kernel/nthread.o
CC [M] /home/iscsitarget-0.4.5/kernel/wthread.o
CC [M] /home/iscsitarget-0.4.5/kernel/config.o
CC [M] /home/iscsitarget-0.4.5/kernel/digest.o
CC [M] /home/iscsitarget-0.4.5/kernel/conn.o
CC [M] /home/iscsitarget-0.4.5/kernel/session.o
CC [M] /home/iscsitarget-0.4.5/kernel/target.o
CC [M] /home/iscsitarget-0.4.5/kernel/volume.o
CC [M] /home/iscsitarget-0.4.5/kernel/iotype.o
CC [M] /home/iscsitarget-0.4.5/kernel/file-io.o
CC [M] /home/iscsitarget-0.4.5/kernel/target_disk.o
LD [M] /home/iscsitarget-0.4.5/kernel/iscsi_trgt.o
Building modules, stage 2.
CC /home/iscsitarget-0.4.5/kernel/iscsi_trgt.mod.o
LD [M] /home/iscsitarget-0.4.5/kernel/iscsi_trgt.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.9-42.0.3.EL-i686'

# make install
`usr/ietd' -> `/usr/sbin/ietd'
`usr/ietadm' -> `/usr/sbin/ietadm'
if [ -f /etc/debian_version ]; then \
install -v -m 755 etc/initd/initd.debian /etc/init.d/iscsi-target; \
elif [ -f /etc/redhat-release ]; then \
install -v -m 755 etc/initd/initd.redhat /etc/init.d/iscsi-target; \
elif [ -f /etc/slackware-version ]; then \
install -v -m 755 etc/initd/initd /etc/rc.d/iscsi-target; \
else \
install -v -m 755 etc/initd/initd /etc/init.d/iscsi-target; \
`etc/initd/initd.redhat' -> `/etc/init.d/iscsi-target'
install: creating directory `/lib/modules/2.6.9-42.0.3.EL/kernel/iscsi'
`kernel/iscsi_trgt.ko' -> `/lib/modules/2.6.9-42.0.3.EL/kernel/iscsi/iscsi_trgt.ko'
depmod -aq

Version 0.4.5 was released on 2005-02-21, so that PcPro article must have been on the editors desk for a year!

Ok, I still need to see if it will work, but that something for another post!