iscsiuio is used in conjunction with specific linux driver to improve performance, such as QLogic NetXtreme II or QLogic CNIC driver. It is not a necessary tool of open-iscsi. What's more, iscsiuio used a package uio which is out of maintain now, which would introduce CVEs unhandled. So I want to remove this tool from open-iscsi. Signed-off-by: Wenchao Hao <haowenchao@huawei.com>
29937 lines
899 KiB
Diff
29937 lines
899 KiB
Diff
From 2e9fb234583610262e37d0718b2dcade61cfa17e Mon Sep 17 00:00:00 2001
|
|
From: Wenchao Hao <haowenchao@huawei.com>
|
|
Date: Thu, 27 Jan 2022 09:52:18 +0800
|
|
Subject: [PATCH 2/3] Remove iscsiuio source code
|
|
|
|
iscsiuio is to be used in conjunction with specific linux driver to
|
|
improve performance, such as QLogic NetXtreme II or QLogic CNIC driver.
|
|
It is not a necessary tool of open-iscsi.
|
|
|
|
What's more, iscsiuio used a package uio which is out of maintain now,
|
|
which would introduce CVEs unhandled. So I want to remove this tool
|
|
from open-iscsi.
|
|
|
|
This patch removes iscsiuio source code
|
|
|
|
Signed-off-by: Wenchao Hao <haowenchao@huawei.com>
|
|
---
|
|
etc/systemd/iscsiuio.service | 20 -
|
|
etc/systemd/iscsiuio.socket | 9 -
|
|
iscsiuio/.gitignore | 25 -
|
|
iscsiuio/AUTHORS | 0
|
|
iscsiuio/ChangeLog | 7 -
|
|
iscsiuio/INSTALL | 290 --
|
|
iscsiuio/Makefile.am | 33 -
|
|
iscsiuio/NEWS | 0
|
|
iscsiuio/README | 224 --
|
|
iscsiuio/RELEASE.TXT | 2100 --------------
|
|
iscsiuio/configure.ac | 104 -
|
|
iscsiuio/docs/iscsiuio.8 | 89 -
|
|
iscsiuio/iscsiuiolog | 10 -
|
|
iscsiuio/src/.gitignore | 1 -
|
|
iscsiuio/src/Makefile.am | 1 -
|
|
iscsiuio/src/README | 13 -
|
|
iscsiuio/src/apps/Makefile.am | 1 -
|
|
iscsiuio/src/apps/README | 2 -
|
|
iscsiuio/src/apps/brcm-iscsi/Makefile.am | 13 -
|
|
.../src/apps/brcm-iscsi/Makefile.brcm-iscsi | 1 -
|
|
iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.c | 89 -
|
|
iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.h | 91 -
|
|
iscsiuio/src/apps/dhcpc/Makefile.am | 13 -
|
|
iscsiuio/src/apps/dhcpc/Makefile.dhcpc | 1 -
|
|
iscsiuio/src/apps/dhcpc/dhcpc.c | 417 ---
|
|
iscsiuio/src/apps/dhcpc/dhcpc.h | 86 -
|
|
iscsiuio/src/apps/dhcpc/dhcpv6.c | 517 ----
|
|
iscsiuio/src/apps/dhcpc/dhcpv6.h | 253 --
|
|
iscsiuio/src/uip-1.0-changelog.txt | 98 -
|
|
iscsiuio/src/uip/Makefile.am | 18 -
|
|
iscsiuio/src/uip/Makefile.include | 47 -
|
|
iscsiuio/src/uip/clock.h | 87 -
|
|
iscsiuio/src/uip/debug.h | 13 -
|
|
iscsiuio/src/uip/icmpv6.h | 302 --
|
|
iscsiuio/src/uip/ipv6.c | 1306 ---------
|
|
iscsiuio/src/uip/ipv6.h | 332 ---
|
|
iscsiuio/src/uip/ipv6_ndpc.c | 432 ---
|
|
iscsiuio/src/uip/ipv6_ndpc.h | 98 -
|
|
iscsiuio/src/uip/ipv6_pkt.h | 50 -
|
|
iscsiuio/src/uip/lc-addrlabels.h | 80 -
|
|
iscsiuio/src/uip/lc-switch.h | 73 -
|
|
iscsiuio/src/uip/lc.h | 130 -
|
|
iscsiuio/src/uip/psock.c | 339 ---
|
|
iscsiuio/src/uip/psock.h | 383 ---
|
|
iscsiuio/src/uip/pt.h | 322 ---
|
|
iscsiuio/src/uip/timer.c | 127 -
|
|
iscsiuio/src/uip/timer.h | 84 -
|
|
iscsiuio/src/uip/uip-neighbor.c | 219 --
|
|
iscsiuio/src/uip/uip-neighbor.h | 105 -
|
|
iscsiuio/src/uip/uip.c | 2434 -----------------
|
|
iscsiuio/src/uip/uip.h | 1574 -----------
|
|
iscsiuio/src/uip/uip_arch.h | 137 -
|
|
iscsiuio/src/uip/uip_arp.c | 479 ----
|
|
iscsiuio/src/uip/uip_arp.h | 197 --
|
|
iscsiuio/src/uip/uip_eth.c | 50 -
|
|
iscsiuio/src/uip/uip_eth.h | 43 -
|
|
iscsiuio/src/uip/uipopt.h | 536 ----
|
|
iscsiuio/src/unix/.gitignore | 3 -
|
|
iscsiuio/src/unix/Makefile.am | 41 -
|
|
iscsiuio/src/unix/clock-arch.c | 54 -
|
|
iscsiuio/src/unix/clock-arch.h | 39 -
|
|
iscsiuio/src/unix/iscsid_ipc.c | 1255 ---------
|
|
iscsiuio/src/unix/iscsid_ipc.h | 52 -
|
|
iscsiuio/src/unix/libs/Makefile.am | 14 -
|
|
iscsiuio/src/unix/libs/bnx2.c | 1165 --------
|
|
iscsiuio/src/unix/libs/bnx2.h | 304 --
|
|
iscsiuio/src/unix/libs/bnx2x.c | 1676 ------------
|
|
iscsiuio/src/unix/libs/bnx2x.h | 715 -----
|
|
iscsiuio/src/unix/libs/cnic.c | 671 -----
|
|
iscsiuio/src/unix/libs/cnic.h | 57 -
|
|
iscsiuio/src/unix/libs/qedi.c | 1195 --------
|
|
iscsiuio/src/unix/libs/qedi.h | 159 --
|
|
iscsiuio/src/unix/logger.c | 181 --
|
|
iscsiuio/src/unix/logger.h | 129 -
|
|
iscsiuio/src/unix/main.c | 442 ---
|
|
iscsiuio/src/unix/nic.c | 1548 -----------
|
|
iscsiuio/src/unix/nic.h | 407 ---
|
|
iscsiuio/src/unix/nic_id.c | 364 ---
|
|
iscsiuio/src/unix/nic_id.h | 47 -
|
|
iscsiuio/src/unix/nic_nl.c | 680 -----
|
|
iscsiuio/src/unix/nic_nl.h | 54 -
|
|
iscsiuio/src/unix/nic_utils.c | 1813 ------------
|
|
iscsiuio/src/unix/nic_utils.h | 104 -
|
|
iscsiuio/src/unix/nic_vlan.c | 337 ---
|
|
iscsiuio/src/unix/nic_vlan.h | 89 -
|
|
iscsiuio/src/unix/options.h | 118 -
|
|
iscsiuio/src/unix/packet.c | 145 -
|
|
iscsiuio/src/unix/packet.h | 78 -
|
|
iscsiuio/src/unix/ping.c | 518 ----
|
|
iscsiuio/src/unix/ping.h | 73 -
|
|
iscsiuio/src/unix/uip-conf.h | 160 --
|
|
91 files changed, 29192 deletions(-)
|
|
delete mode 100644 etc/systemd/iscsiuio.service
|
|
delete mode 100644 etc/systemd/iscsiuio.socket
|
|
delete mode 100644 iscsiuio/.gitignore
|
|
delete mode 100644 iscsiuio/AUTHORS
|
|
delete mode 100644 iscsiuio/ChangeLog
|
|
delete mode 100644 iscsiuio/INSTALL
|
|
delete mode 100644 iscsiuio/Makefile.am
|
|
delete mode 100644 iscsiuio/NEWS
|
|
delete mode 100644 iscsiuio/README
|
|
delete mode 100644 iscsiuio/RELEASE.TXT
|
|
delete mode 100644 iscsiuio/configure.ac
|
|
delete mode 100644 iscsiuio/docs/iscsiuio.8
|
|
delete mode 100644 iscsiuio/iscsiuiolog
|
|
delete mode 100644 iscsiuio/src/.gitignore
|
|
delete mode 100644 iscsiuio/src/Makefile.am
|
|
delete mode 100644 iscsiuio/src/README
|
|
delete mode 100644 iscsiuio/src/apps/Makefile.am
|
|
delete mode 100644 iscsiuio/src/apps/README
|
|
delete mode 100644 iscsiuio/src/apps/brcm-iscsi/Makefile.am
|
|
delete mode 100644 iscsiuio/src/apps/brcm-iscsi/Makefile.brcm-iscsi
|
|
delete mode 100644 iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.c
|
|
delete mode 100644 iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.h
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/Makefile.am
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/Makefile.dhcpc
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/dhcpc.c
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/dhcpc.h
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/dhcpv6.c
|
|
delete mode 100644 iscsiuio/src/apps/dhcpc/dhcpv6.h
|
|
delete mode 100644 iscsiuio/src/uip-1.0-changelog.txt
|
|
delete mode 100644 iscsiuio/src/uip/Makefile.am
|
|
delete mode 100644 iscsiuio/src/uip/Makefile.include
|
|
delete mode 100644 iscsiuio/src/uip/clock.h
|
|
delete mode 100644 iscsiuio/src/uip/debug.h
|
|
delete mode 100644 iscsiuio/src/uip/icmpv6.h
|
|
delete mode 100644 iscsiuio/src/uip/ipv6.c
|
|
delete mode 100644 iscsiuio/src/uip/ipv6.h
|
|
delete mode 100644 iscsiuio/src/uip/ipv6_ndpc.c
|
|
delete mode 100644 iscsiuio/src/uip/ipv6_ndpc.h
|
|
delete mode 100644 iscsiuio/src/uip/ipv6_pkt.h
|
|
delete mode 100644 iscsiuio/src/uip/lc-addrlabels.h
|
|
delete mode 100644 iscsiuio/src/uip/lc-switch.h
|
|
delete mode 100644 iscsiuio/src/uip/lc.h
|
|
delete mode 100644 iscsiuio/src/uip/psock.c
|
|
delete mode 100644 iscsiuio/src/uip/psock.h
|
|
delete mode 100644 iscsiuio/src/uip/pt.h
|
|
delete mode 100644 iscsiuio/src/uip/timer.c
|
|
delete mode 100644 iscsiuio/src/uip/timer.h
|
|
delete mode 100644 iscsiuio/src/uip/uip-neighbor.c
|
|
delete mode 100644 iscsiuio/src/uip/uip-neighbor.h
|
|
delete mode 100644 iscsiuio/src/uip/uip.c
|
|
delete mode 100644 iscsiuio/src/uip/uip.h
|
|
delete mode 100644 iscsiuio/src/uip/uip_arch.h
|
|
delete mode 100644 iscsiuio/src/uip/uip_arp.c
|
|
delete mode 100644 iscsiuio/src/uip/uip_arp.h
|
|
delete mode 100644 iscsiuio/src/uip/uip_eth.c
|
|
delete mode 100644 iscsiuio/src/uip/uip_eth.h
|
|
delete mode 100644 iscsiuio/src/uip/uipopt.h
|
|
delete mode 100644 iscsiuio/src/unix/.gitignore
|
|
delete mode 100644 iscsiuio/src/unix/Makefile.am
|
|
delete mode 100644 iscsiuio/src/unix/clock-arch.c
|
|
delete mode 100644 iscsiuio/src/unix/clock-arch.h
|
|
delete mode 100644 iscsiuio/src/unix/iscsid_ipc.c
|
|
delete mode 100644 iscsiuio/src/unix/iscsid_ipc.h
|
|
delete mode 100644 iscsiuio/src/unix/libs/Makefile.am
|
|
delete mode 100644 iscsiuio/src/unix/libs/bnx2.c
|
|
delete mode 100644 iscsiuio/src/unix/libs/bnx2.h
|
|
delete mode 100644 iscsiuio/src/unix/libs/bnx2x.c
|
|
delete mode 100644 iscsiuio/src/unix/libs/bnx2x.h
|
|
delete mode 100644 iscsiuio/src/unix/libs/cnic.c
|
|
delete mode 100644 iscsiuio/src/unix/libs/cnic.h
|
|
delete mode 100644 iscsiuio/src/unix/libs/qedi.c
|
|
delete mode 100644 iscsiuio/src/unix/libs/qedi.h
|
|
delete mode 100644 iscsiuio/src/unix/logger.c
|
|
delete mode 100644 iscsiuio/src/unix/logger.h
|
|
delete mode 100644 iscsiuio/src/unix/main.c
|
|
delete mode 100644 iscsiuio/src/unix/nic.c
|
|
delete mode 100644 iscsiuio/src/unix/nic.h
|
|
delete mode 100644 iscsiuio/src/unix/nic_id.c
|
|
delete mode 100644 iscsiuio/src/unix/nic_id.h
|
|
delete mode 100644 iscsiuio/src/unix/nic_nl.c
|
|
delete mode 100644 iscsiuio/src/unix/nic_nl.h
|
|
delete mode 100644 iscsiuio/src/unix/nic_utils.c
|
|
delete mode 100644 iscsiuio/src/unix/nic_utils.h
|
|
delete mode 100644 iscsiuio/src/unix/nic_vlan.c
|
|
delete mode 100644 iscsiuio/src/unix/nic_vlan.h
|
|
delete mode 100644 iscsiuio/src/unix/options.h
|
|
delete mode 100644 iscsiuio/src/unix/packet.c
|
|
delete mode 100644 iscsiuio/src/unix/packet.h
|
|
delete mode 100644 iscsiuio/src/unix/ping.c
|
|
delete mode 100644 iscsiuio/src/unix/ping.h
|
|
delete mode 100644 iscsiuio/src/unix/uip-conf.h
|
|
|
|
diff --git a/etc/systemd/iscsiuio.service b/etc/systemd/iscsiuio.service
|
|
deleted file mode 100644
|
|
index 923e019..0000000
|
|
--- a/etc/systemd/iscsiuio.service
|
|
+++ /dev/null
|
|
@@ -1,20 +0,0 @@
|
|
-[Unit]
|
|
-Description=iSCSI UserSpace I/O driver
|
|
-Documentation=man:iscsiuio(8)
|
|
-DefaultDependencies=no
|
|
-Conflicts=shutdown.target
|
|
-Requires=iscsid.service
|
|
-BindTo=iscsid.service
|
|
-After=network.target
|
|
-Before=remote-fs-pre.target iscsid.service
|
|
-Wants=remote-fs-pre.target
|
|
-
|
|
-[Service]
|
|
-Type=notify
|
|
-NotifyAccess=main
|
|
-ExecStart=/sbin/iscsiuio -f
|
|
-KillMode=mixed
|
|
-Restart=on-failure
|
|
-
|
|
-[Install]
|
|
-WantedBy=multi-user.target
|
|
diff --git a/etc/systemd/iscsiuio.socket b/etc/systemd/iscsiuio.socket
|
|
deleted file mode 100644
|
|
index d42cedc..0000000
|
|
--- a/etc/systemd/iscsiuio.socket
|
|
+++ /dev/null
|
|
@@ -1,9 +0,0 @@
|
|
-[Unit]
|
|
-Description=Open-iSCSI iscsiuio Socket
|
|
-Documentation=man:iscsiuio(8)
|
|
-
|
|
-[Socket]
|
|
-ListenStream=@ISCSID_UIP_ABSTRACT_NAMESPACE
|
|
-
|
|
-[Install]
|
|
-WantedBy=sockets.target
|
|
diff --git a/iscsiuio/.gitignore b/iscsiuio/.gitignore
|
|
deleted file mode 100644
|
|
index a27452a..0000000
|
|
--- a/iscsiuio/.gitignore
|
|
+++ /dev/null
|
|
@@ -1,25 +0,0 @@
|
|
-# Autogenerated files
|
|
-stamp-h1
|
|
-Makefile.in
|
|
-Makefile
|
|
-configure
|
|
-config.h.in
|
|
-config.h
|
|
-config.guess
|
|
-config.log
|
|
-config.status
|
|
-config.sub
|
|
-COPYING
|
|
-
|
|
-.deps
|
|
-autom4te.cache
|
|
-
|
|
-# autotools
|
|
-aclocal.m4
|
|
-compile
|
|
-depcomp
|
|
-install-sh
|
|
-libtool
|
|
-ltmain.sh
|
|
-missing
|
|
-
|
|
diff --git a/iscsiuio/AUTHORS b/iscsiuio/AUTHORS
|
|
deleted file mode 100644
|
|
index e69de29..0000000
|
|
diff --git a/iscsiuio/ChangeLog b/iscsiuio/ChangeLog
|
|
deleted file mode 100644
|
|
index a91b4d5..0000000
|
|
--- a/iscsiuio/ChangeLog
|
|
+++ /dev/null
|
|
@@ -1,7 +0,0 @@
|
|
-Version 0.4.1 (July 20, 2009)
|
|
- * Fix from Mike Christie to determine page size from getpagesize()
|
|
- rather then the constant PAGE_SIZE. PAGE_SIZE is not defined om
|
|
- ia64 and ppc.
|
|
- * Update documentation to indicate IPv6 is not supported
|
|
- * Fix code to catch the message from the CNIC that the network
|
|
- interface is going down.
|
|
diff --git a/iscsiuio/INSTALL b/iscsiuio/INSTALL
|
|
deleted file mode 100644
|
|
index c9fd2c0..0000000
|
|
--- a/iscsiuio/INSTALL
|
|
+++ /dev/null
|
|
@@ -1,290 +0,0 @@
|
|
-Installation Instructions
|
|
-*************************
|
|
-
|
|
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
|
-2006, 2007, 2008 Free Software Foundation, Inc.
|
|
-
|
|
- This file is free documentation; the Free Software Foundation gives
|
|
-unlimited permission to copy, distribute and modify it.
|
|
-
|
|
-Basic Installation
|
|
-==================
|
|
-
|
|
- Briefly, the shell commands `./configure; make; make install' should
|
|
-configure, build, and install this package. The following
|
|
-more-detailed instructions are generic; see the `README' file for
|
|
-instructions specific to this package.
|
|
-
|
|
- The `configure' shell script attempts to guess correct values for
|
|
-various system-dependent variables used during compilation. It uses
|
|
-those values to create a `Makefile' in each directory of the package.
|
|
-It may also create one or more `.h' files containing system-dependent
|
|
-definitions. Finally, it creates a shell script `config.status' that
|
|
-you can run in the future to recreate the current configuration, and a
|
|
-file `config.log' containing compiler output (useful mainly for
|
|
-debugging `configure').
|
|
-
|
|
- It can also use an optional file (typically called `config.cache'
|
|
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
-the results of its tests to speed up reconfiguring. Caching is
|
|
-disabled by default to prevent problems with accidental use of stale
|
|
-cache files.
|
|
-
|
|
- If you need to do unusual things to compile the package, please try
|
|
-to figure out how `configure' could check whether to do them, and mail
|
|
-diffs or instructions to the address given in the `README' so they can
|
|
-be considered for the next release. If you are using the cache, and at
|
|
-some point `config.cache' contains results you don't want to keep, you
|
|
-may remove or edit it.
|
|
-
|
|
- The file `configure.ac' (or `configure.in') is used to create
|
|
-`configure' by a program called `autoconf'. You need `configure.ac' if
|
|
-you want to change it or regenerate `configure' using a newer version
|
|
-of `autoconf'.
|
|
-
|
|
-The simplest way to compile this package is:
|
|
-
|
|
- 1. `cd' to the directory containing the package's source code and type
|
|
- `./configure' to configure the package for your system.
|
|
-
|
|
- Running `configure' might take a while. While running, it prints
|
|
- some messages telling which features it is checking for.
|
|
-
|
|
- 2. Type `make' to compile the package.
|
|
-
|
|
- 3. Optionally, type `make check' to run any self-tests that come with
|
|
- the package.
|
|
-
|
|
- 4. Type `make install' to install the programs and any data files and
|
|
- documentation.
|
|
-
|
|
- 5. You can remove the program binaries and object files from the
|
|
- source code directory by typing `make clean'. To also remove the
|
|
- files that `configure' created (so you can compile the package for
|
|
- a different kind of computer), type `make distclean'. There is
|
|
- also a `make maintainer-clean' target, but that is intended mainly
|
|
- for the package's developers. If you use it, you may have to get
|
|
- all sorts of other programs in order to regenerate files that came
|
|
- with the distribution.
|
|
-
|
|
- 6. Often, you can also type `make uninstall' to remove the installed
|
|
- files again.
|
|
-
|
|
-Compilers and Options
|
|
-=====================
|
|
-
|
|
- Some systems require unusual options for compilation or linking that
|
|
-the `configure' script does not know about. Run `./configure --help'
|
|
-for details on some of the pertinent environment variables.
|
|
-
|
|
- You can give `configure' initial values for configuration parameters
|
|
-by setting variables in the command line or in the environment. Here
|
|
-is an example:
|
|
-
|
|
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
|
-
|
|
- *Note Defining Variables::, for more details.
|
|
-
|
|
-Compiling For Multiple Architectures
|
|
-====================================
|
|
-
|
|
- You can compile the package for more than one kind of computer at the
|
|
-same time, by placing the object files for each architecture in their
|
|
-own directory. To do this, you can use GNU `make'. `cd' to the
|
|
-directory where you want the object files and executables to go and run
|
|
-the `configure' script. `configure' automatically checks for the
|
|
-source code in the directory that `configure' is in and in `..'.
|
|
-
|
|
- With a non-GNU `make', it is safer to compile the package for one
|
|
-architecture at a time in the source code directory. After you have
|
|
-installed the package for one architecture, use `make distclean' before
|
|
-reconfiguring for another architecture.
|
|
-
|
|
- On MacOS X 10.5 and later systems, you can create libraries and
|
|
-executables that work on multiple system types--known as "fat" or
|
|
-"universal" binaries--by specifying multiple `-arch' options to the
|
|
-compiler but only a single `-arch' option to the preprocessor. Like
|
|
-this:
|
|
-
|
|
- ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
|
- CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
|
- CPP="gcc -E" CXXCPP="g++ -E"
|
|
-
|
|
- This is not guaranteed to produce working output in all cases, you
|
|
-may have to build one architecture at a time and combine the results
|
|
-using the `lipo' tool if you have problems.
|
|
-
|
|
-Installation Names
|
|
-==================
|
|
-
|
|
- By default, `make install' installs the package's commands under
|
|
-`/usr/local/bin', include files under `/usr/local/include', etc. You
|
|
-can specify an installation prefix other than `/usr/local' by giving
|
|
-`configure' the option `--prefix=PREFIX'.
|
|
-
|
|
- You can specify separate installation prefixes for
|
|
-architecture-specific files and architecture-independent files. If you
|
|
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
|
-PREFIX as the prefix for installing programs and libraries.
|
|
-Documentation and other data files still use the regular prefix.
|
|
-
|
|
- In addition, if you use an unusual directory layout you can give
|
|
-options like `--bindir=DIR' to specify different values for particular
|
|
-kinds of files. Run `configure --help' for a list of the directories
|
|
-you can set and what kinds of files go in them.
|
|
-
|
|
- If the package supports it, you can cause programs to be installed
|
|
-with an extra prefix or suffix on their names by giving `configure' the
|
|
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
-
|
|
-Optional Features
|
|
-=================
|
|
-
|
|
- Some packages pay attention to `--enable-FEATURE' options to
|
|
-`configure', where FEATURE indicates an optional part of the package.
|
|
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
-is something like `gnu-as' or `x' (for the X Window System). The
|
|
-`README' should mention any `--enable-' and `--with-' options that the
|
|
-package recognizes.
|
|
-
|
|
- For packages that use the X Window System, `configure' can usually
|
|
-find the X include and library files automatically, but if it doesn't,
|
|
-you can use the `configure' options `--x-includes=DIR' and
|
|
-`--x-libraries=DIR' to specify their locations.
|
|
-
|
|
-Particular systems
|
|
-==================
|
|
-
|
|
- On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
|
-CC is not installed, it is recommended to use the following options in
|
|
-order to use an ANSI C compiler:
|
|
-
|
|
- ./configure CC="cc -Ae"
|
|
-
|
|
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
|
-
|
|
- On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
|
-parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
|
-a workaround. If GNU CC is not installed, it is therefore recommended
|
|
-to try
|
|
-
|
|
- ./configure CC="cc"
|
|
-
|
|
-and if that doesn't work, try
|
|
-
|
|
- ./configure CC="cc -nodtk"
|
|
-
|
|
-Specifying the System Type
|
|
-==========================
|
|
-
|
|
- There may be some features `configure' cannot figure out
|
|
-automatically, but needs to determine by the type of machine the package
|
|
-will run on. Usually, assuming the package is built to be run on the
|
|
-_same_ architectures, `configure' can figure that out, but if it prints
|
|
-a message saying it cannot guess the machine type, give it the
|
|
-`--build=TYPE' option. TYPE can either be a short name for the system
|
|
-type, such as `sun4', or a canonical name which has the form:
|
|
-
|
|
- CPU-COMPANY-SYSTEM
|
|
-
|
|
-where SYSTEM can have one of these forms:
|
|
-
|
|
- OS KERNEL-OS
|
|
-
|
|
- See the file `config.sub' for the possible values of each field. If
|
|
-`config.sub' isn't included in this package, then this package doesn't
|
|
-need to know the machine type.
|
|
-
|
|
- If you are _building_ compiler tools for cross-compiling, you should
|
|
-use the option `--target=TYPE' to select the type of system they will
|
|
-produce code for.
|
|
-
|
|
- If you want to _use_ a cross compiler, that generates code for a
|
|
-platform different from the build platform, you should specify the
|
|
-"host" platform (i.e., that on which the generated programs will
|
|
-eventually be run) with `--host=TYPE'.
|
|
-
|
|
-Sharing Defaults
|
|
-================
|
|
-
|
|
- If you want to set default values for `configure' scripts to share,
|
|
-you can create a site shell script called `config.site' that gives
|
|
-default values for variables like `CC', `cache_file', and `prefix'.
|
|
-`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
-`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
-`CONFIG_SITE' environment variable to the location of the site script.
|
|
-A warning: not all `configure' scripts look for a site script.
|
|
-
|
|
-Defining Variables
|
|
-==================
|
|
-
|
|
- Variables not defined in a site shell script can be set in the
|
|
-environment passed to `configure'. However, some packages may run
|
|
-configure again during the build, and the customized values of these
|
|
-variables may be lost. In order to avoid this problem, you should set
|
|
-them in the `configure' command line, using `VAR=value'. For example:
|
|
-
|
|
- ./configure CC=/usr/local2/bin/gcc
|
|
-
|
|
-causes the specified `gcc' to be used as the C compiler (unless it is
|
|
-overridden in the site shell script).
|
|
-
|
|
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
|
-an Autoconf bug. Until the bug is fixed you can use this workaround:
|
|
-
|
|
- CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
|
-
|
|
-`configure' Invocation
|
|
-======================
|
|
-
|
|
- `configure' recognizes the following options to control how it
|
|
-operates.
|
|
-
|
|
-`--help'
|
|
-`-h'
|
|
- Print a summary of all of the options to `configure', and exit.
|
|
-
|
|
-`--help=short'
|
|
-`--help=recursive'
|
|
- Print a summary of the options unique to this package's
|
|
- `configure', and exit. The `short' variant lists options used
|
|
- only in the top level, while the `recursive' variant lists options
|
|
- also present in any nested packages.
|
|
-
|
|
-`--version'
|
|
-`-V'
|
|
- Print the version of Autoconf used to generate the `configure'
|
|
- script, and exit.
|
|
-
|
|
-`--cache-file=FILE'
|
|
- Enable the cache: use and save the results of the tests in FILE,
|
|
- traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
- disable caching.
|
|
-
|
|
-`--config-cache'
|
|
-`-C'
|
|
- Alias for `--cache-file=config.cache'.
|
|
-
|
|
-`--quiet'
|
|
-`--silent'
|
|
-`-q'
|
|
- Do not print messages saying which checks are being made. To
|
|
- suppress all normal output, redirect it to `/dev/null' (any error
|
|
- messages will still be shown).
|
|
-
|
|
-`--srcdir=DIR'
|
|
- Look for the package's source code in directory DIR. Usually
|
|
- `configure' can determine that directory automatically.
|
|
-
|
|
-`--prefix=DIR'
|
|
- Use DIR as the installation prefix. *Note Installation Names::
|
|
- for more details, including other options available for fine-tuning
|
|
- the installation locations.
|
|
-
|
|
-`--no-create'
|
|
-`-n'
|
|
- Run the configure checks, but stop before creating any output
|
|
- files.
|
|
-
|
|
-`configure' also accepts some other, not widely useful, options. Run
|
|
-`configure --help' for more details.
|
|
diff --git a/iscsiuio/Makefile.am b/iscsiuio/Makefile.am
|
|
deleted file mode 100644
|
|
index 97f478f..0000000
|
|
--- a/iscsiuio/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,33 +0,0 @@
|
|
-SUBDIRS= src
|
|
-
|
|
-EXTRA_DIST = build_date
|
|
-
|
|
-build_date:
|
|
- if [ -n "$$SOURCE_DATE_EPOCH" ] ; then \
|
|
- echo 'char *build_date = "'`LC_ALL=C.UTF-8 date --date=@$$SOURCE_DATE_EPOCH -u`'";' > build_date.c ; \
|
|
- else \
|
|
- echo 'char *build_date = "'`date`'";' > build_date.c ; \
|
|
- fi
|
|
- echo 'char *build_date;'> build_date.h
|
|
-
|
|
-manprefix = /usr/share
|
|
-mandir = ${manprefix}/man
|
|
-logdir = /etc/logrotate.d
|
|
-
|
|
-install-am: all-am
|
|
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install-man install-log install-brcm
|
|
-
|
|
-install-man:
|
|
- cat docs/iscsiuio.8 | GZIP=$(GZIP_ENV) gzip -c > iscsiuio.8.gz
|
|
- $(INSTALL) -d $(DESTDIR)$(mandir)/man8/
|
|
- $(INSTALL_DATA) iscsiuio.8.gz $(DESTDIR)$(mandir)/man8/
|
|
-
|
|
-install-log:
|
|
- $(INSTALL) -d $(DESTDIR)$(logdir)/
|
|
- $(INSTALL_DATA) iscsiuiolog $(DESTDIR)$(logdir)/
|
|
-
|
|
-install-brcm:
|
|
- $(RM) $(DESTDIR)$(sbindir)/brcm_iscsiuio
|
|
- (cd $(DESTDIR)/$(sbindir); \
|
|
- $(RM) brcm_iscsiuio; \
|
|
- $(LN_S) iscsiuio brcm_iscsiuio)
|
|
diff --git a/iscsiuio/NEWS b/iscsiuio/NEWS
|
|
deleted file mode 100644
|
|
index e69de29..0000000
|
|
diff --git a/iscsiuio/README b/iscsiuio/README
|
|
deleted file mode 100644
|
|
index 53b700c..0000000
|
|
--- a/iscsiuio/README
|
|
+++ /dev/null
|
|
@@ -1,224 +0,0 @@
|
|
-Iscsiuio Userspace Tool
|
|
-Version 0.7.8.6
|
|
-Jun 27, 2019
|
|
-------------------------------------------------------
|
|
-
|
|
-This tool is to be used in conjunction with the QLogic NetXtreme II Linux
|
|
-driver (Kernel module name: 'bnx2' and 'bnx2x'), QLogic CNIC driver,
|
|
-and the QLogic iSCSI driver (Kernel module name: 'bnx2i').
|
|
-This user space tool is used in conjunction with the following
|
|
-QLogic Network Controllers:
|
|
- bnx2: BCM5706, BCM5708, BCM5709 devices
|
|
- bnx2x: BCM57710, BCM57711, BCM57711E, BCM57712, BCM57712E,
|
|
- BCM57800, BCM57810, BCM57840 devices
|
|
-
|
|
-This utility will provide the ARP and DHCP functionality for the iSCSI offload.
|
|
-The communication to the driver is done via Userspace I/O (Kernel module name
|
|
-'uio').
|
|
-
|
|
-There is one component to this application:
|
|
-
|
|
-1. 'iscsiuio' - This is the daemon which aids in creating iSCSI offloaded
|
|
- connections.
|
|
-
|
|
-Dependencies:
|
|
-=======================================
|
|
-
|
|
-Linux Kernel Dependencies:
|
|
-1. QLogic CNIC driver (cnic)
|
|
-1. QLogic iSCSI offload driver (bnx2i)
|
|
-2. Userspace I/O driver (uio)
|
|
-
|
|
-Directory Structure of this Package:
|
|
-=======================================
|
|
-
|
|
-<root>
|
|
- |
|
|
- +-doc (documentation directory: man pages)
|
|
- |
|
|
- +-src
|
|
- |
|
|
- +- uip - the uIP stack
|
|
- |
|
|
- +- unix - iscsiuio source
|
|
-
|
|
-
|
|
-
|
|
-Compiling / Installing
|
|
-=======================================
|
|
-
|
|
-1. Please untar the tarball.
|
|
-2. Run the configure script. This will create the Makefiles and proper
|
|
- header files needed for the build.
|
|
-3. Run 'make'. This will create the binary, 'iscsiuio'
|
|
-4. Run 'make install' to place the binaries in their installed location.
|
|
- (The default location is '/sbin')
|
|
-
|
|
-iscsid IFACE Configuration File:
|
|
-=======================================
|
|
-The network interface configuration files are driven by the iscsid iface
|
|
-files. The configuration data is parsed by iscsid and passed to the uIP
|
|
-stack when the connection is established.
|
|
-
|
|
-One can use the following iscsiadm commands to create/set the configuration
|
|
-using the iface files:
|
|
-
|
|
-1. Create the iface file:
|
|
-
|
|
- iscsiadm -m iface -I <iface name> --op=new
|
|
-
|
|
-2. Discover the targets associated with the new iface
|
|
-
|
|
- iscsiadm -m discovery -t st -p <iSCSI target IP address> -I <iface name>
|
|
-
|
|
-3. Update the iface file:
|
|
-
|
|
- To use a static IPv4 address:
|
|
- iscsiadm -m iface -I <iface name> --op=update --name=iface.ipaddress --value=<static IPv4 address ie: 192.168.0.1>
|
|
-
|
|
- To use a DHCP address:
|
|
- iscsiadm -m iface -I <iface name> --op=update --name=iface.ipaddress --value=0.0.0.0
|
|
-
|
|
- The following values are required.
|
|
-
|
|
- To specify the bnx2i as the transport:
|
|
- iscsiadm -m iface -I <iface name> --op=update --name=iface.transport_name --value=bnx2i
|
|
-
|
|
- To specify the network interface to offload with:
|
|
-
|
|
- a. Specify the physical network interface name <ie. eth0, eth1, eth2 ...>
|
|
- iscsiadm -m iface -I <iface name> --op=update --name=iface.net_ifacename --value=<network interface name>
|
|
-
|
|
- b. Specify the iSCSI MAC address of the iSCSI HBA
|
|
- iscsiadm -m iface -I <iface name> --op=update --name=iface.hwaddress --value=<MAC address of the iSCSI HBA>
|
|
-
|
|
-4. Now all the settings should be set so that one could connect to their
|
|
- desired iSCSI target.
|
|
-
|
|
- iscsiadm -m node -p <iSCSI target IP address> -T <target name> -I <iface name> --login
|
|
-
|
|
-bnx2 Limitations:
|
|
-=======================================
|
|
-* RX iSCSI ring:
|
|
- * default ring size is 3 entries
|
|
- * default buffer size is 0x400 bytes
|
|
-* TX iSCSI ring:
|
|
- * default ring size of 1 entry
|
|
- * default buffer size is 0x400 bytes
|
|
-
|
|
-bnx2x Limitations:
|
|
-=======================================
|
|
-* RX iSCSI ring:
|
|
- * default ring size is 15 entries
|
|
- * default buffer size is 0x400 bytes
|
|
-* TX iSCSI ring:
|
|
- * default ring size of 1 entry
|
|
- * default buffer size is 0x400 bytes
|
|
-
|
|
-Other Limiations:
|
|
-
|
|
-Any packets larger then the buffer size will not be sent/received by the
|
|
-hardware and will be dropped.
|
|
-
|
|
-IPv6 support:
|
|
-
|
|
-IPv6 NDP (neighbor discovery protocol), DHCPv6 and Static IPv6 are now
|
|
-supported. The IPv6 address used for the connection will be matched against
|
|
-the DHCPv6/static IPv6 address, the RA (router advertise) address, and the
|
|
-assigned link local address.
|
|
-
|
|
-VLAN support:
|
|
-
|
|
-VLAN support is only supported when using static IP addresses.
|
|
-Also, currently only 1 VLAN is supported per physical network interface.
|
|
-Either non-VLAN offloaded traffic is allowed or VLAN offloaded traffic
|
|
-is allowed. The current implementation does not support both at the
|
|
-same time.
|
|
-
|
|
-Currently there is no explicit VLAN attributes in the iface file.
|
|
-To configure the VLAN offload, the iface.hwaddress attribute or
|
|
-physical net_ifacename (without the VLAN identifier) must be used
|
|
-to specify the HBA device. For the proper CNIC routing, the
|
|
-corresponding L2 interface which has the associated VLAN interface must
|
|
-have an IP address on the same subnet.
|
|
-
|
|
-The following attributes need to be filled when offloading via the
|
|
-VLAN interface:
|
|
-
|
|
- iface.iscsi_ifacename = <name of this iface file>
|
|
- iface.hwaddress = XX:XX:XX:XX:XX:XX
|
|
- iface.ipaddress = XX.XX.XX.XX
|
|
- iface.transport_name = bnx2i
|
|
-
|
|
-Setting IP address:
|
|
-
|
|
-On RHEL5.4, RHEL5.5+, RHEL6.0+, and SLES11SP1 distributions,
|
|
-discovery login is done over the Linux TCP/IP stack and L2 network
|
|
-interface. The ethx interface corresponding to the HBA must
|
|
-therefore be in the same IP subnet in order to reach the iSCSI
|
|
-target during discovery. However, the HBA's IP address should not
|
|
-be the same as the L2 ethx's IP address.
|
|
-
|
|
-Starting with RHEL6.1 and all other newer distributions, discovery
|
|
-using SendTargets is done over the HBA interface, so there is no
|
|
-need for the HBA and L2 network to be on the same subnet. However,
|
|
-if VLAN is used on the HBA, they still have to be on the same subnet
|
|
-as described above.
|
|
-
|
|
-
|
|
-Setting Netmask and Gateway addresses:
|
|
-
|
|
-With the current limitations of the iface file, there are no entries
|
|
-to allow the user to enter a netmask or gateway IP address.
|
|
-
|
|
-The only way to explicitly configure these options is to use DHCP
|
|
-addressing. Then the netmask/gateway are set on the DHCP server.
|
|
-These settings are then sent to uIP via the DHCPOFFERs.
|
|
-
|
|
-If the netmask is not defined then the netmask are automatically
|
|
-generated depending on the destination IP address.
|
|
-
|
|
-Debugging:
|
|
-=======================================
|
|
-
|
|
-By default, the iscsiuio daemon does not output any messages to the log file,
|
|
-'/var/log/iscsiuio.log'. Message logging is only enabled when the daemon is
|
|
-run under debug mode.
|
|
-
|
|
-To run the daemon in debug mode please pass the parameter '-d <debug level>'
|
|
-
|
|
-where the following debug levels are defined:
|
|
-
|
|
-DEBUG 4 - Print all messages
|
|
-INFO 3 - Print messages needed to follow the uIP code (default)
|
|
-WARN 2 - Print warning messages
|
|
-ERROR 1 - Only print critical errors
|
|
-
|
|
-A sample banner message:
|
|
-
|
|
-INFO [Mon Jun 20 11:23:14 2011]Started iSCSI uio stack: Ver 0.7.0.6
|
|
-INFO [Mon Jun 20 11:23:14 2011]Build date: Mon Jun 20 11:22:05 PDT 2011
|
|
-INFO [Mon Jun 20 11:23:14 2011]Debug mode enabled
|
|
-
|
|
-These messages can be used to help debug any issues.
|
|
-
|
|
-When debugging issues like the iscsid, the iscsiuio daemon can be run
|
|
-in the foreground and the maximum debugging level should be used.
|
|
-
|
|
-To place the daemon in foreground mode please pass the parameter '-f'
|
|
-
|
|
-Note: The messages to the log file are not flushed unless debugging is enabled.
|
|
-
|
|
-Note: If the daemon iscsiuio is running, one will not be able to
|
|
- trample over the existing binary. One might see the following message:
|
|
-
|
|
- 'cannot create regular file `/sbin/iscsiuio': Text file busy'
|
|
-
|
|
- The solve this, please stop the iscsid service and then install.
|
|
-
|
|
-Warning: If full debug is enabled, this may quickly fill the partition
|
|
-containing the iscsiuio logs. This is because full debugging will log
|
|
-packet activity which on a busy network will quickly fill the logs.
|
|
-
|
|
-Note: If the bnx2i and cnic drivers are unloaded, then iscsiuio will also
|
|
-need to be restarted so that it can determine the iscsid version.
|
|
diff --git a/iscsiuio/RELEASE.TXT b/iscsiuio/RELEASE.TXT
|
|
deleted file mode 100644
|
|
index 28e681b..0000000
|
|
--- a/iscsiuio/RELEASE.TXT
|
|
+++ /dev/null
|
|
@@ -1,2100 +0,0 @@
|
|
- Release Notes
|
|
- QLogic uIP Linux Driver
|
|
- Version 0.7.8.6
|
|
- 06/27/2019
|
|
-
|
|
- QLogic Corporation
|
|
- 26650 Aliso Viejo Pkwy,
|
|
- Aliso Viejo, CA 92656
|
|
-
|
|
- Copyright (c) 2004 - 2013 Broadcom Corporation
|
|
- Copyright (c) 2014, QLogic Corporation
|
|
- All rights reserved
|
|
-
|
|
-uIP v0.7.8.6 (Jun 27, 2019)
|
|
-=======================================================
|
|
- Fixes:
|
|
- -------
|
|
- 1. Problem: OS fails to boot after one path is
|
|
- disconnected from iSCSI MPIO config.
|
|
- Change: In the event of DHCP failure, killing of enable_nic_thread did
|
|
- not process any iscsid requests leading to error,
|
|
- iscsistart: Could not broadcast to uIP after 5 tries
|
|
- and login failure of active path.
|
|
- Added fix to not kill enable_nic_thread and allow further
|
|
- processing of iscsid requests and performing login
|
|
- to next active path.
|
|
- Impact: All
|
|
-
|
|
-uIP v0.7.8.5 (Nov 20, 2018)
|
|
-=======================================================
|
|
- Fixes:
|
|
- -------
|
|
- 1. Problem: CQ102578: observing ISCSI initiator IP ping drop
|
|
- Change: 1. Do not flush tx queue on each uio interrupt
|
|
- 2. Use UIO BD index instead on buffer index.
|
|
- 3. Set buf_size in case of ICMP and ARP packet
|
|
- Impact: QL41xxx adapters
|
|
-
|
|
- 2. Problem: CQ103034 - Unable to boot iSCSI BFS in IPv6 DHCP config
|
|
- Change: Limit retries of performing dhcpv6 before declaring dhcp failure
|
|
- Impact: All
|
|
-
|
|
- 3. Problem: CQ102438: I/O fails to resume on multipath LUN during port toggle.
|
|
- Change: lib/cnic, lib/qedi, Release xmit_mutex in error code path and
|
|
- during clear tx queue.
|
|
- Impact: QL84xx adapters
|
|
-
|
|
- 4. Problem: Netlink buffer corruption when more than one host
|
|
- try to xmit packet at the same time
|
|
- Change: Add inter-host mutex while doing xmit
|
|
- Impact: All
|
|
-
|
|
-uIP v0.7.8.4 (Feb 22, 2018)
|
|
-=======================================================
|
|
- Fixes:
|
|
- -------
|
|
- 1. Problem: CQ95605: iSCSI BFS in DHCP config intermittently fails to boot
|
|
- into the OS when source and destination addresses are in
|
|
- different networks.
|
|
- Change: Allow ARP for non-matching source and destination addresses.
|
|
- For source and destination IP addresses in different networks,
|
|
- continue with the ARP retries and further login process
|
|
- instead of assuming abrupt failure. iSCSI offload adapters
|
|
- may not rely on netmask information for successful iSCSI
|
|
- target login.
|
|
- Impact: All
|
|
-
|
|
-uIP v0.7.8.3 (May 18, 2017)
|
|
-=======================================================
|
|
- Fixes:
|
|
- -------
|
|
- 1. Problem: CQ93985: iscsiuio seg faults if discovery done to not
|
|
- reachable target
|
|
- Change: Serialize xmit_mutex lock to prevent iscsiuio seg fault.
|
|
- Impact: All
|
|
-
|
|
- 2. Problem: CQ91497 - Initiator fails to acquire IPv6 DHCP address
|
|
- from the DHCP server
|
|
- Change: Initialize the transaction-id within the dhcpv6 packet with
|
|
- correct byte order, to fix the trans-id mismatch error.
|
|
- Impact: All
|
|
-
|
|
- 3. Problem: Missing qedi ping transport hook
|
|
- Change: Add qedi ping transport hook
|
|
- Impact: 10/25/40/50GGbE Controller (iSCSI)
|
|
-
|
|
-uIP v0.7.8.3 (Sept 28, 2016)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Add support for the new qedi transport
|
|
- Impact: 10/25/40/50GGbE Controller (iSCSI)
|
|
-
|
|
-uIP v0.7.8.2 (Dec 10, 2013)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00072053 - Some hardware iSCSI paths fail during test
|
|
- Cause: The test exercised a corner case where the ARP cache flush
|
|
- mechanism didn't work properly
|
|
- Change: Fixed the ARP cache flush mechanism
|
|
- Impact: All
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added a new tx doorbell field in the uio path to work with
|
|
- the new bnx2x/cnic drivers that supports VF_RSS
|
|
- Impact: 10G only
|
|
-
|
|
- 2. Change: Fixed the iface.subnet_mask decoding for IPv6
|
|
- Impact: IPv6
|
|
-
|
|
-
|
|
-uIP v0.7.8.1b (May 01, 2013)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Performance optimization by caching the page size
|
|
- Impact: All
|
|
-
|
|
- 2. Change: Fixed a bug in the tx completion interrupt handler
|
|
- Impact: 10G only
|
|
-
|
|
-
|
|
-uIP v0.7.6.1g (Jan 14, 2013)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00067316 - IPv6 address prefix length < 32
|
|
- bits fails to connect
|
|
- Cause: CIDR notation has an order bug in the IPv6 section
|
|
- whenever the prefix length specified is < 32
|
|
- Change: Fixed the network order bug
|
|
- Impact: IPv6 only
|
|
-
|
|
-
|
|
-uIP v0.7.6.1f (Nov 14, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00065768 - RHEL5.X iscsiuio segfault possible
|
|
- if there is a specific 1024 byte size broadcast
|
|
- packet
|
|
- Cause: This is another corner case where the packet size
|
|
- is also exactly 1024 bytes + padding that exceeded
|
|
- the DMA rx buffer. The previous fix was not
|
|
- sufficient
|
|
- Change: Ensure that the packet size + padding do not
|
|
- exceed this limit.
|
|
- Impact: 10G only. 1G already has the guard against it.
|
|
-
|
|
-
|
|
-uIP v0.7.6.1e (Nov 07, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00066397 - Unable to connect to iSCSI target
|
|
- with NPAR enabled on 57840
|
|
- Cause: The PCI device ID for 57840_MF has been changed from
|
|
- 0x16ab to 0x16a4
|
|
- Change: Updated the PCI id table to match exactly what the
|
|
- bnx2x 1.76 indicates
|
|
- Impact: 57840 MF
|
|
-
|
|
-
|
|
-uIP v0.7.6.1d (Oct 31, 2012)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added support for open-iscsi-2.0.873
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.6.1c (Oct 15, 2012)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added support for 10G 57840 4x10 and 2x20
|
|
- Impact: 10G 57840
|
|
-
|
|
-
|
|
-uIP v0.7.6.1b (Oct 09, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00065690 - Vconfig method of connecting over
|
|
- tagged vlan with IPv6 failed
|
|
- Cause: The new net param support changes has prevented
|
|
- the old vconfig method from execising the IPv6
|
|
- acquisition engine properly
|
|
- Change: Ensure that this old vconfig method to run the IPv6
|
|
- acquisition engine properly and to its entirety
|
|
- Impact: IPv6 + VLAN using the network VLAN configuration
|
|
- method
|
|
-
|
|
- 2. Problem: Cont00065768 - RHEL5.X iscsiuio segfault possible
|
|
- if there is a specific 1024 byte size broadcast
|
|
- packet
|
|
- Cause: This is a corner case where the packet size is
|
|
- exactly 1024 bytes + padding that exceeded the
|
|
- DMA rx buffer. This has been there since day 1.
|
|
- Change: Ensure that the packet size + padding do not
|
|
- exceed this limit.
|
|
- Impact: 10G only. 1G already has the guard against it.
|
|
-
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Source optimization - backported source code fixes
|
|
- as reported from the upstream submission patch
|
|
- Impact: ALL
|
|
-
|
|
-
|
|
-uIP v0.7.4.2k (Aug 10, 2012)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Enable HP SD mode
|
|
- Impact: 577XX/578XX
|
|
-
|
|
-
|
|
-uIP v0.7.4.2j (Jul 18, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00064665 - Linux iSCSI connects via gateway address
|
|
- on the wrong subnet
|
|
- Cause: The gateway address used was not checked against the
|
|
- subnet mask specified before the ARP requests. Since
|
|
- this behavior deters from how L2 operates, therefore,
|
|
- a change was made to correct this.
|
|
- Change: Added check of the gateway specified against the subnet
|
|
- specified.
|
|
- Impact: Static IPv4 operation
|
|
-
|
|
- 2. Problem: Cont00064722 - Linux iSCSI unable to force IPv6 LL
|
|
- override (advanced iface parameters)
|
|
- Cause: The override LL address was not being populated to the
|
|
- IPv6 address database correctly
|
|
- Change: Added this correctly to the IPv6 initialization
|
|
- Impact: Static/DHCP IPv6 LL address override only
|
|
-
|
|
-
|
|
-uIP v0.7.4.2i (Jul 11, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00064604 - Fails to connect to routed IPv6 target
|
|
- via RA
|
|
- Cause: The default router IPv6 address was not being retrieved
|
|
- correctly.
|
|
- Change: Fixed the default router IPv6 address read
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.2h (Jun 15, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00063863 - can't boot into offload image
|
|
- when VLAN is enabled
|
|
- Cause: During the iSCSI login exchange, certain iSCSI targets
|
|
- will send an ARP request even though the TCP connection
|
|
- has been made. The bug was in this ARP reply where
|
|
- the local MAC was corrupted when VLAN is enabled.
|
|
- Change: Fixed the ARP reply packet
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.2g (Jun 08, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00063816 - The initiator is not able to connect
|
|
- to the iSCSI targets over VLAN
|
|
- Cause: The process packet routine did not consider the PCP
|
|
- of the VLAN tag to be non-zero. This created a
|
|
- mismatch when this VLAN tag was compared against the
|
|
- nic_iface->vlan_id which doesn't include the PCP.
|
|
- Change: Added the consideration of non-zero PCP
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.2f (Jun 04, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00063626 - Static IPv6 does not connect when
|
|
- the prefix len is not set explicitly
|
|
- Cause: The IPv6 prefix length was not set correctly
|
|
- for Static IPv6 operation when CIDR notation is
|
|
- not specified
|
|
- Change: Fixed the default prefix length
|
|
- Impact: Static IPv6
|
|
-
|
|
- 2. Problem: Cont00063651 - Cannot connect to iSCSI targets
|
|
- HP PTM/SF
|
|
- Cause: Switch-Dependent mode + invalid Outer VLAN was
|
|
- not supported
|
|
- Change: Allow SD+invalid OV to fallback to SF operation mode
|
|
- Impact: 5771X/578XX
|
|
-
|
|
-
|
|
-uIP v0.7.4.2e (May 30, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00063443 - Compilation error on SLES11sp1
|
|
- Cause: The iface_num field was not defined
|
|
- Change: Fixed all references to iface_num
|
|
- Impact: SLES11sp1
|
|
-
|
|
- 2. Problem: Cont00063518 - HBA fails to connect across router
|
|
- using iface.gateway address
|
|
- Cause: The gateway override code did not populate the
|
|
- address into the lower level engine
|
|
- Change: Fixed the gateway override code
|
|
- Impact: IPv4 Static IP operation
|
|
-
|
|
- 3. Problem: Cont00063567 - IPv6 LL and RA override does not work
|
|
- Cause: The IPv6 LL/RA override addresses were overwritten
|
|
- by the NDP engine
|
|
- Change: Fixed the LL/RA override code
|
|
- Impact: IPv6 operation
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Added support for jumbo MTU (independent from the L2 MTU)
|
|
-
|
|
-
|
|
-uIP v0.7.4.2d (May 21, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00063421 - Static IPv6 cannot connect via RA/LL
|
|
- Cause: The router advertise and the linklocal address
|
|
- were corrupted due to the override capabilities
|
|
- added for the newer open-iscsi util
|
|
- Change: Fixed the address override code
|
|
- Impact: Static IPv6
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Allow VLAN tag = 1 (router management) to connect offload
|
|
-
|
|
-
|
|
-uIP v0.7.4.2c (May 09, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: RHEL BZ 734010/804580 - issues found by the Coverity
|
|
- scan
|
|
- Cause: 10 code issues were flagged for revision
|
|
- Change: Fixed all area of concern
|
|
- Impact: All
|
|
-
|
|
- 2. Problem: Cont00063177 - IPv4 DHCP with VLAN specification in
|
|
- iface file gets wrong address
|
|
- Cause: The DHCPv4 handler was not discriminating the VLAN tag
|
|
- associated with the DHCP offers from multiple DHCP
|
|
- servers
|
|
- Change: Changed the DHCPv4 handler to drop DHCP offer packets
|
|
- that doesn't match the VLAN tag of the intended DHCP
|
|
- discovery packet
|
|
- Impact: DHCPv4 operation
|
|
-
|
|
-
|
|
-uIP v0.7.4.2b (May 01, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00062993 - IPv6 DHCP with VLAN specification in
|
|
- iface file gets wrong address
|
|
- Cause: The DHCPv6 request was using the same DUID as always
|
|
- so the non-VLAN DHCP server responded to our broadcast
|
|
- instead
|
|
- Change: Changed the DHCPv6 request DUID to link address + time
|
|
- instead of link address alone
|
|
- Impact: DHCPv6 operation
|
|
-
|
|
-
|
|
-uIP v0.7.4.1j (Apr 24, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00062805 - Cannot login to iSCSI targets on RHEL6.3
|
|
- Cause: The problem was caused by a change made to the iface_rec
|
|
- structure in the RHEL6.3 inbox open-iscsi util
|
|
- Change: The new changes is now incorporated
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.1i (Apr 16, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00062660 - Unable to login with VLAN iscsiuio
|
|
- on RHEL6.2
|
|
- Cause: The open-iscsi util in RHEL6.2 has a bug which
|
|
- does not pass the correct iface_num to iscsiuio
|
|
- Change: Added workaround to fall back to do the legacy
|
|
- VLAN support if iface_num and vlan_id = 0
|
|
- Impact: RHEL6.2
|
|
-
|
|
-
|
|
-uIP v0.7.4.1h (Apr 13, 2012)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Added support for the new iface_num field in the iscsi_uevent
|
|
- path
|
|
-
|
|
- 2. Fixed bug in the nic_iface search engine based on iface_num
|
|
-
|
|
-
|
|
-uIP v0.7.4.1g (Mar 22, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00061869 - Unable to setup an offload iSCSI
|
|
- connection with FLR/NPAR under ESX5.0:PDA
|
|
- Cause: The physical function ID was previously extracted
|
|
- from the sysfs of the VM which might not be consistent
|
|
- to the actual physical setup due to the function
|
|
- remapping in the hypervisor
|
|
- Change: Read the physical function ID directly from the BAR0
|
|
- ME register
|
|
- Impact: All
|
|
-
|
|
- 2. Problem: Cont00062170 - IPv6 login/logout stress fails
|
|
- Cause: The packet interrupt was lost after running the test
|
|
- for a much longer period of time. A bug in the
|
|
- packet processing routine was found to exit prematurely
|
|
- Change: Fixed the packet processing routine to process all
|
|
- packets before exiting
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.1f (Mar 19, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00062170 - IPv6 login/logout stress fails
|
|
- Cause: The packet buffer routine for IPv6 did not take
|
|
- network order <-> host order into consideration
|
|
- Change: Added a htons call to compensate for the ntohs pair
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.1e (Mar 08, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00061978 - Load/unload stress test fails
|
|
- Cause: The bnx2x open request was failing due to the module
|
|
- request procedure. However, the open failure was
|
|
- not being handled correctly.
|
|
- Change: Fixed the device open error handling
|
|
- Impact: 5771X/578XX
|
|
-
|
|
-
|
|
-uIP v0.7.4.1d (Mar 02, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00061708 - Unable to log into target after running
|
|
- driver load/unload
|
|
- Cause: A bug was introduced in the previous bug fix (CQ61459)
|
|
- where a pthread_cond_broadcast call was erroneously
|
|
- enabled
|
|
- Change: Restored this back
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.1c (Feb 16, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00061529 - Unable to connect to target after an
|
|
- initial failed login attempt until iscsi service is
|
|
- restarted
|
|
- Cause: Upon a failed DHCPv4 acquisition due to the wrong VLAN
|
|
- tag in the initial iface setup, any iscsid connect request
|
|
- from the same NIC will get dropped due to a bug.
|
|
- Change: Fixed the bug which prevented new iscsid connect requests
|
|
- from getting honored
|
|
- Impact: All
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Updated README
|
|
-
|
|
-
|
|
-uIP v0.7.4.1b (Feb 08, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00061513 - Unable to connect to target over VLAN
|
|
- interface
|
|
- Cause: The VLAN id was not properly passed back to the CNIC
|
|
- driver for the offload request
|
|
- Change: Fixed the VLAN id being passed back to the CNIC driver
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.4.1a (Feb 01, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00049383 - No mechanism in iface file to support
|
|
- gateway/routing
|
|
- Change: Added support for the additional network parameters
|
|
- as passed from the newer iscsi-util.
|
|
- These parameters include:
|
|
- IPv4: subnet_mask, gateway
|
|
- IPv6: ipv6_linklocal, ipv6_router,
|
|
- ipv6_autocfg, linklocal_autocfg, router_autocfg
|
|
- VLAN: vlan_id, vlan_priority, vlan_state
|
|
- Other: mtu, port
|
|
- Impact: All
|
|
-
|
|
- 2. Problem: Cont00060806 - Unable to connect target using DHCP over
|
|
- tagged VLAN
|
|
- Change: DHCP+VLAN is a new feature enhancement that was added
|
|
- alongside all other new iface parameters.
|
|
- Impact: All
|
|
-
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Lock iscsid's connect request with path_req so connect requests
|
|
- with DHCP/Static will no longer override each other
|
|
-
|
|
- 2. Fixed the if_down handler from global to nic specific
|
|
-
|
|
- 3. Fixed various synchronization issues
|
|
-
|
|
-
|
|
-uIP v0.7.2.1e (Jan 05, 2012)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00060734 - ifupdown-mtu change stress with active
|
|
- session causes iscsiuio to fail
|
|
- Change: Fixed a race condition between the nic enable thread
|
|
- and when DHCP fails
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.2.1d (Dec 28, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00060368 - segfault observed after failing both
|
|
- mpio paths
|
|
- Change: Various memory leaks were identified and resolved in
|
|
- the nic cleanup path
|
|
- Impact: All
|
|
-
|
|
-
|
|
-uIP v0.7.2.1c (Dec 16, 2011)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Disable HP SD mode
|
|
-
|
|
-
|
|
-uIP v0.7.2.1b (Dec 14, 2011)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Default iscsiuio logging to off. Use the '-d'
|
|
- option to enable
|
|
-
|
|
-
|
|
-uIP v0.7.0.14g (Oct 25, 2011)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Fixed the compilation under RHEL6.2
|
|
- 2. Change: Added oom_adjust call to prevent OOM Killer from killing
|
|
- iscsiuio when memory is low
|
|
- 3. Change: Added mlockall setting to prevent page swap
|
|
-
|
|
-
|
|
-uIP v0.7.0.14f (Oct 20, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00058994 - DOS vulnerability in uip during UDP flood
|
|
- Cause: The warning messages from the UDP handler was logging
|
|
- at a rate faster than the log file logrotate rate
|
|
- Therefore, the system's OOM eventually got kicked in to
|
|
- start terminating running processes which includes iscsiuio
|
|
- Change: Moved several UDP warning messages from the default log
|
|
- level to the debug log level
|
|
- Impact: All (minor)
|
|
-
|
|
- 2. Problem: Cont00059288 - Show segfault w/ SLES11 SP1 Xen kernel
|
|
- Cause: The bnx2x chip_id was not read correctly from the PCIe BAR1
|
|
- under the Xen kernel. The error was in the mmap area.
|
|
- Change: Corrected the mmapping of the PCI MMIO space.
|
|
- Impact: Xen kernels
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Changed the log file open error to a warning and let
|
|
- the daemon progress. This was only observed under iSCSI boot
|
|
-
|
|
-
|
|
-uIP v0.7.0.14e (Sep 19, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00058678 - Can not iboot target from ipv6 path
|
|
- using VLAN
|
|
- Cause: A bug was found in the path request path where the vlan
|
|
- iface's protocol family was not used correctly in the
|
|
- iface search
|
|
- Change: This has been corrected
|
|
-
|
|
-
|
|
-uIP v0.7.0.14d (Sep 16, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00058602 - Can't iboot using IPv6 offload path
|
|
- Cause: The bug was exposed by a fix in 0.7.0.14c where the
|
|
- IPv6 router solicitation timeout exceeded the nic
|
|
- enable thread timeout.
|
|
- Change: The IPv6 router solicitation timeout has been adjusted
|
|
-
|
|
-
|
|
-uIP v0.7.0.14c (Sep 01, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00058256 - Sessions fail after loginstress to via
|
|
- simultaneous ipv4 and ipv6 dhcp
|
|
- Cause: Switching between DHCPv4/v6 coupled with VLAN exposed
|
|
- a drawback in our nic_iface architecture design where
|
|
- VLAN is not specified by iscsid.
|
|
- Change: The code was optimized and improved the performance when
|
|
- switching between DHCPv4/v6+VLAN. However, the ultimate
|
|
- fix is to make use of the net config parameters introduced
|
|
- in the newer open-iscsi util which will identify the
|
|
- specific VLAN nic_iface to use.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added support for bnx2x-1.71.00
|
|
-
|
|
-
|
|
-uIP v0.7.0.14b (Aug 23, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00057840 - RHEL6.2 inbox: Unable to connect to
|
|
- targets with 5709
|
|
- Cause: For cases when the bnx2/bnx2x driver gets removed, the
|
|
- uio database that was built by cnic would have the device
|
|
- ->net reference removed. This has caused an unnecessary
|
|
- timeout of 5s for each stale uio entry in the database.
|
|
- Change: Adjusted the routine which seeks the device->net entry
|
|
- to include more logic instead of hard waiting for 5s.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added support for RHEL6.2 for out-of-box release
|
|
- 2. Change: Updated the man page with -h and -p info
|
|
- 3. Change: Updated the -h info
|
|
-
|
|
-
|
|
-uIP v0.7.0.13 (Aug 10, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00057768 - iscsiuio logrotate causes daemon failure
|
|
- Cause: The logrotate script will send a SIGUSR1 signal to notify
|
|
- the iscsiuio daemon of such action. However, the daemon
|
|
- wasn't programmed to catch this signal.
|
|
- Change: Restored the catching of this signal
|
|
-
|
|
-
|
|
-uIP v0.7.0.12 (Aug 04, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00050634 - brcm_iscsiuio Tainted: running IoZone,
|
|
- Iometer and receiving a UDP flood on 3260
|
|
- Cause: Upon iscsiuio termination, because of the UDP flood,
|
|
- the nic thread will be busy servicing those UDP packets
|
|
- while the signal handling thread will free up all nic
|
|
- resources. The two threads were not in sync.
|
|
- Change: Added a nic_remove_all routine to destroy all nic threads
|
|
- before the nic resources get freed.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Fixed all warnings as reported by RHELS' Coverity testing.
|
|
-
|
|
-
|
|
-uIP v0.7.0.11 (Aug 02, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Erroneous VLAN tag was being passed by iscsid for connect
|
|
- request
|
|
- Cause: The iscsid's iface_rec_t ipc message does not contain this
|
|
- vlan field. This field was added in uIP for future vlan
|
|
- support. Since the buffer allocated to receive such message
|
|
- in uIP didn't get initialized, therefore, garbled up VLAN
|
|
- tag was getting used.
|
|
- Change: Added the initialization of this buffer.
|
|
-
|
|
-
|
|
-uIP v0.7.0.10 (Jul 26, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Can't offload when switching from Static to DHCP then back to
|
|
- Static IPv4 when connecting through a VLAN interface
|
|
- Cause: The VLAN processing code did not reinstall the IP address
|
|
- from the default nic_iface to the associated VLAN nic_iface.
|
|
- This was only done on the very first time when the VLAN
|
|
- interface was created and not on subsequent instances.
|
|
- Change: Added code to mirror the default nic_iface IP/netmask/ip_config
|
|
- on the VLAN nic_iface on every new connection request.
|
|
-
|
|
-
|
|
-uIP v0.7.0.9 (Jul 19, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Can't offload to 57810 NPAR NIC
|
|
- Cause: The MF/VF variant of the PCI IDs were not supported previously
|
|
- Change: Added support for the MF/VF variants for 57800/57810/57840
|
|
-
|
|
-
|
|
-uIP v0.7.0.8 (Jun 30, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00056522 - Unable to connect to iSCSI target using
|
|
- netxtreme2 package 7.0.9
|
|
- Cause: The iSCSI L2 ring's CID has changed from 17 to 49
|
|
- Change: The code now gets L2 iSCSI ring CID from the l2_buf directly.
|
|
- This will work with any version of the cnic driver because
|
|
- the location is a zero before this change.
|
|
-
|
|
-
|
|
-uIP v0.7.0.7 (Jun 23, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00056460 - iSCSI Offload boot RHEL5u5 x64 dropped tagged
|
|
- packets with iSCSI Offload Boot with untagged
|
|
- Cause: The ICMP echo replies to the target was corrupted in both
|
|
- 1g and 10g mode
|
|
- Change: The code will now handle both VLAN stripped and no VLAN stripped
|
|
- incoming packets correctly. Also modified the transmit routine
|
|
- to strip out any inline VLAN tag before setting up the hw to
|
|
- insert VLAN tag.
|
|
-
|
|
-
|
|
-uIP v0.7.0.6 (Jun 21, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00056231 - DHCPv4 not working with iSCSI HBA w/
|
|
- linux-nx2 v7.0.7
|
|
- Cause: The 10g L2 FW HSI has been modified for PCIe performance
|
|
- enhancement in the 7.0.7 package (FW 1.70.20) which uIP
|
|
- has not adapted to.
|
|
- Change: The eth_rx_cqe size has been increased from 32B to 64B.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: The utility name has changed from brcm_iscsiuio to iscsiuio
|
|
- as preparation for upstream submission.
|
|
- 2. Change: Updated README
|
|
-
|
|
-
|
|
-uIP v0.7.0.5 (Jun 02, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00055915 - iSCSI does not connect on 57800 in 4-port mode
|
|
- Cause: The 4-port mode was not being determined correctly
|
|
- Change: Fixed the PORT4MODE register offset and the QZONE_ID macros
|
|
-
|
|
-
|
|
-uIP v0.7.0.4 (May 24, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00055832 - linux iscsiboot can not login to target using
|
|
- offload path (57800)
|
|
- Cause: The device ID comparison routine did not take care of the case
|
|
- when one device ID is bitwise superset of another.
|
|
- Change: Fixed the device ID comparison routine.
|
|
-
|
|
-
|
|
-uIP v0.7.0.3 (May. 19, 2011)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Updated all fixes to match the released uIP 0.6.4.17
|
|
-
|
|
- 2. Change: Modified source and Copyright info as preparation for upstream
|
|
- submission
|
|
-
|
|
-
|
|
-uIP v0.7.0.2 (May. 03, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00048972 - brcm-iscsi.log has no max size and would grow
|
|
- to consume all free space on hard disk
|
|
- Cause: There was no mechanism to rotate the log
|
|
- Change: Added logrotate entry and SIGUSR1 signal handling for log rotate
|
|
- action
|
|
-
|
|
- 2. Problem: Cont00054996 - Multi-session, multi-protocol mtu stress
|
|
- does not recover all sessions
|
|
- Cause: A segfault was observed during the load/unload module. The
|
|
- problem was caused by an illegal dereference of a pointer
|
|
- when IPv6 couldn't find the longest match address from
|
|
- the ARP (Neighbor) table.
|
|
- Change: Fixed the dereferencing error
|
|
-
|
|
- 3. Problem: Cont00054900 - Linux uIP - Please add ability to connect
|
|
- to routed target with static iface IPv6
|
|
- Cause: Static IPv6 never runs the IPv6 NDP router sol/adv engine.
|
|
- Change: IPv6 NDP router sol/adv has now been added to static IPv6
|
|
- operation.
|
|
-
|
|
- 4. Problem: Cont00054996 - Multi-session, multi-protocol mtu stress
|
|
- does not recover all sessions
|
|
- Cause: Segfaults were observed caused by the accessing of the IPv6
|
|
- NDP structure while the nic is undergoing a reset either
|
|
- due to a DHCPv4 request from iscsid or the handling of
|
|
- if_down due to the NL handler from CNIC.
|
|
- Change: The fix involves the following:
|
|
- - Fixed the handling of staggered IPv4/v6 DHCP/static requests
|
|
- - Fixed memory leak due to reallocation of IPv4 and IPv6
|
|
- DHCP structs
|
|
- - Fixed the pthread join stuck problem in the handling
|
|
- of the if_down NL message
|
|
-
|
|
- 5. Problem: Cont00054810 - Linux NMI - bnx2x_init_hw_common:PXP2 CFG
|
|
- failed running iSCSI MTU stress test
|
|
- Cause: This only happens in DHCPv4 mode. The problem was caused
|
|
- by contention between the elongated window of performing
|
|
- DHCP in the enable_nic thread while receiving the asynchronous
|
|
- if_down NL message (from the MTU change event) from the
|
|
- CNIC NL thread. The problem occurs when the enable_nic
|
|
- thread tries to call bnx2x_open while the other thread
|
|
- calls the bnx2x_close routine.
|
|
- Change: Fixed mutex lock bugs for the enable_nic thread. Also
|
|
- extended the nic_disable timeout to 10s to compensate for
|
|
- the DHCP operation.
|
|
-
|
|
- 6. Problem: Cont00054818 - RH6.0 - Unable to logout of iSCSI session
|
|
- after running PQA baseline scripts
|
|
- Cause: This was caused by the call to cancel the enable_nic
|
|
- thread when disabling the nic but failed to unlock the
|
|
- nic mutex that the enable_nic thread held.
|
|
- Change: Wake up the enable_nic thread and wait for it to complete
|
|
- instead of canceling it in the nic_disable path.
|
|
-
|
|
- 7. Problem: Cont00054725 - Previous static HBA IP will be used after
|
|
- a new static HBA IP has been created
|
|
- Cause: There was an assumption in the code where if the same
|
|
- nic_iface structure was found based on the nic/vlan pair,
|
|
- the specified IP address would not be used. Instead, it
|
|
- will continue to use the previous defined IP address.
|
|
- Change: The previous IP address will now be compared against the
|
|
- the specified IP address before finishing the parce
|
|
- iface request from iscsid. If different, the current
|
|
- nic will be disabled and then re-enabled with the newly
|
|
- specified IP address.
|
|
-
|
|
- 8. Problem: Cont00054571 - Unable to connect to routed ipv6 target
|
|
- with RA address and iface DHCPv6
|
|
- Cause: The default router address was not being employed for
|
|
- the IPv6 neighbor negotiation. Additionally, the return
|
|
- address of our neighbor advertisement was incorrect as
|
|
- it should use the best matched src address instead.
|
|
- Change: Fixed both the IPv6 neighbor solicitation and advertisement
|
|
- transmission and handling.
|
|
-
|
|
- 9. Problem: Cont00054510 - fails to login to 32 session with blanket
|
|
- login IPv6
|
|
- Cause: A bug was introduced in uIP 0.6.4.6 where the NIC_RUNNING
|
|
- flag might not be set when entering the main loop under
|
|
- certain situations depending on the nic bring up.
|
|
- Change: A new NIC_STARTED_RUNNING flag is now defined to fix CQ53511.
|
|
-
|
|
- 10. Problem: Cont00053807 - RA and link local are unable to connect if DHCPv6
|
|
- fails
|
|
- Cause: The host link local address was not being searched as one of
|
|
- the host address to be replied to CNIC for the connect request.
|
|
- Change: The path reply now includes the search of host link local
|
|
- address as well.
|
|
-
|
|
- 11. Problem: Cont00054236 - iSCSI service must be restarted before an IPv6
|
|
- connection can be made to the Equalogic target
|
|
- Cause: The problem was intermittent as it depends on which IPv6 address
|
|
- the target was redirecting to. Since uIP was only extracting
|
|
- the target's IPv6 address + MAC from the target's neighbor
|
|
- advertisement packet itself and not from the ICMPv6 option, so
|
|
- the wrong or no MAC address will get send down to CNIC for the
|
|
- connection establishment; hence the no connect.
|
|
- Change: Added the updating of the neighbor discovery table to also use
|
|
- the Target IPv6 address + MAC specified in the incoming neighbor
|
|
- advertisement's ICMPv6 option field.
|
|
-
|
|
- 12. Problem: Cont00053255 - bnx2x panic dump logging into multiple
|
|
- discovered IPv6 nodes (Equalogic IPv6 target)
|
|
- Cause: The bnx2x panic was fixed in the 10g fw 6.4.29.
|
|
- A IPv6 connectivity issue was then found and led to different
|
|
- kernel/uIP crashes. This was caused by the same IPv6
|
|
- connectivity problem mentioned above.
|
|
- Change: Same as above
|
|
-
|
|
- 13. Problem: Cont00053728 - Sessions never recover after doing initiator-side
|
|
- cable pull test with IPv6 traffic against Equalogic targets
|
|
- Cause: It was discovered that the Equalogic would send out periodic
|
|
- neighbor solicitation to maintain the connection to the
|
|
- initiator. Since uIP was responding with the assigned IPv6
|
|
- link local address in the neighbor advertisement
|
|
- unconditionally, the target was observed to stop transmitting on
|
|
- the connection specified.
|
|
- Change: The neighbor advertisement generated will now use the dst IPv6
|
|
- address from the input neighbor solicitation packet instead of
|
|
- the assigned IPv6 link local address for both the packet and the
|
|
- ICMPv6 source IPv6 address.
|
|
-
|
|
- 14. Problem: Compile error under 32-bit OS
|
|
- Cause: A bug was introduced in the previous release 0.6.4.6 which
|
|
- caused a compilation error in 32-bit OS (64-bit compiles
|
|
- fine)
|
|
- Change: Fixed the bug
|
|
-
|
|
- 15. Problem: Cont00053807 - RA and Link local are unable to connect if dhcpv6
|
|
- fails
|
|
- Cause: There was a bug in the nl reply where the RA address will never
|
|
- be sent back to CNIC for the connection request
|
|
- Change: The best matched address to the dst will now be sent back to
|
|
- CNIC in the path rsp.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Updated README to remove the 57713/E references
|
|
-
|
|
- 2. Change: Allow the ICMP option field in the IPv6 Neighbor Advertisement
|
|
- response to be included without discrimination. This fixes
|
|
- an issue connecting against the EQL via RA for DHCPv6.
|
|
-
|
|
- 3. Change: Updated README for the IPv6 operation, VLAN, and discovery.
|
|
-
|
|
-
|
|
-uIP v0.7.0.1 (Mar. 29, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00053511 - bnx2x panic dump during ifup/down stress with
|
|
- iSCSI traffic
|
|
- Cause: The panic dump was resolved by the driver's rq dbell size fix.
|
|
- After that, uIP crashed due to the asynchronous if_down event
|
|
- that took the chip resources away while the nic thread is still
|
|
- continuing to try to send DHCP request.
|
|
- Change: Added synchronization between the two threads so proper clean up
|
|
- of the threads can occur.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added support for E3 (57800, 57810, and 57840)
|
|
-
|
|
-
|
|
-uIP v0.6.4.5 (Mar. 23, 2011)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Optimized the double VLAN fix of CQ53870 to match
|
|
- what will be submitted for RHELS5.7 and RHELS6.1 inbox
|
|
-
|
|
-
|
|
-uIP v0.6.4.4 (Mar. 17, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00053870 - Unable to login to iSCSI target via offload
|
|
- through a Nexus 5020 switch with DCBx enabled
|
|
- Cause: Double VLAN tagging was observed due to DCBx enabled.
|
|
- The chip actually adds a VLAN tag if the txbd does not have
|
|
- VLAN tag enabled under the DCBx environment for PRI setting.
|
|
- Since uIP does not make use of hw assisted VLAN tagging,
|
|
- 2 VLAN tag was observed in the data stream.
|
|
- Change: Enabled hw assisted VLAN tagging in uIP for both 1g and 10g.
|
|
-
|
|
- 2. Problem: Cont00053792 - maxconnections intermittently fail and
|
|
- recover using iface DHCPv4
|
|
- Cause: The DHCPv4 engine erroneously keeps on requesting for a
|
|
- new lease which tremendously hamper normal path_req
|
|
- operation. The problem is that the lease time parameter
|
|
- has overflowed when converted to ticks count.
|
|
- Change: Expanded the lease timer ticks count parameter from 16 to
|
|
- 32 bits.
|
|
-
|
|
- 3. Problem: Cont00053807 - RA and link local are unable to connect if
|
|
- DHCPv6 fails
|
|
- Cause: The DHCPv6 engine does not have the failover to use RA
|
|
- mechanism
|
|
- Change: Expanded to use best match address instead regardless of
|
|
- DHCPv6 success or not, or using static v6.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Cont00051823 - Added man page for brcm_iscsiuio
|
|
-
|
|
-
|
|
-uIP v0.6.4.3 (Mar. 15, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00053719 - intermittent logging into targets that
|
|
- are not in the same subnet as defined in the iface
|
|
- Cause: The default route was used erroneously due to a miscompare
|
|
- Change: Fixed this comparison so if the requested dst is not in
|
|
- in the same subnet, uIP would not even ARP out.
|
|
-
|
|
- 2. Problem: Cont00053580 - Unable to do iSCSI boot into Linux OS using
|
|
- 57710 adapters
|
|
- Cause: The E1 iro USTORM_RX_PROD_OFFSET doesn't match the t6.4 fw
|
|
- Change: This is now fixed
|
|
-
|
|
-
|
|
-uIP v0.6.4.2 (Feb. 24, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00050343 - HBA does not follow RFC2131 spec for IPv4
|
|
- DHCP lease expiration
|
|
- Cause: The dhcp engine did not have this feature implemented
|
|
- Change: Added lease time tracking and renewal
|
|
-
|
|
- 2. Problem: Cont00050801 - Unable to connect to target after switching
|
|
- between DHCPv4 to static v4
|
|
- Cause: The configuration flags got corrupted when switching between
|
|
- dhcp and static or vice versa.
|
|
- Change: Fixed the flag handling. Also needed to zero out the static
|
|
- ip address in the host memory when switching to dhcp.
|
|
- Otherwise, the static ip address will get used mistakenly.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Cont00051936 - Added IPv6 NDP and DHCPv6 support.
|
|
-
|
|
-
|
|
-uIP v0.6.4.1 (Jan. 27, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00049766 - segfault seen while stopping iscsi service
|
|
- Cause: The logger output routine was accessing the log resource
|
|
- while another thread calls fini_logger to free the same
|
|
- resources
|
|
- Change: Added pthread mutex lock to the logger routine to exclude
|
|
- the initializer, user, and finisher
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added new t6.4 HSI and 57713 support.
|
|
-
|
|
-
|
|
-uIP v0.6.2.13 (Jan. 04, 2011)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00049665 - iscsiboot:linux failed to boot into iscsi
|
|
- boot image in offload path after 5 iterations
|
|
- Cause: The hw consumer index for the uIP ring got out of sync
|
|
- with the producer index. This has led to the xmit mutex
|
|
- lock be held forever so subsequent ARP requests will not
|
|
- get transmitted to the wire
|
|
- Change: Added this out of sync detection and rescue the xmit mutex
|
|
- lock
|
|
-
|
|
-uIP v0.6.2.12 (Dec. 21, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Cont00051820 - Session fails to reconnect after gateway
|
|
- fallback
|
|
- Cause: Under the HSRP test scenario, it was found that an ARP
|
|
- request from the SUT is required in order for the HSRP
|
|
- router to begin sending packets downstream to the SUT.
|
|
- The default ARP age was originally set to 20 minutes
|
|
- before a new ARP request will get sent,
|
|
- Change: Changed the ARP age default to Linux default at 5 minutes
|
|
-
|
|
-uIP v0.6.2.11 (Dec. 17, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: For IPv4, the gateway route was not being utilized
|
|
- when the subnet mask given or calculated does not
|
|
- match. This resulted in many unwanted connection
|
|
- attempts.
|
|
- Cause: A bug was found in the default gateway calculation
|
|
- logic which prevented the gateway address from being
|
|
- used.
|
|
- Change: Fixed the default gateway logic
|
|
-
|
|
- 2. Problem: For IPv6, there are scenarios where it won't connect
|
|
- Cause: The IPv6 subnet mask as extracted from the CIDR
|
|
- format might contain garbage data. This garbage data
|
|
- was then used as part of the subnet mask which would
|
|
- prevent the correct address mask.
|
|
- Change: Fixed the subnet mask
|
|
-
|
|
-uIP v0.6.2.10 (Dec. 15, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: IPv6 does not connect for non-CIDR iface.ipaddress
|
|
- specification
|
|
- Cause: A bug where all ones was used as the IPv6 netmask
|
|
- instead of all zeroes. This prevented all IPv6
|
|
- path requests from being honored
|
|
- Change: Fixed the subnet mask used
|
|
-
|
|
-uIP v0.6.2.9 (Dec. 14, 2010)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added IP address CIDR notation support for the
|
|
- iface.ipaddress field in the iface file.
|
|
- This will allow subnet mask to be defined and used.
|
|
-
|
|
-uIP v0.6.2.8 (Dec. 9, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: ipv6 + ifup/down fails to reconnect
|
|
-
|
|
- Cause: There were 2 problems found:
|
|
- - the xmit_mutex lock was being held indefinitely
|
|
- - the nl_process_if_down flag for 10g doorbell ringing
|
|
- did not get reinitialized
|
|
-
|
|
- Change: Fixed the xmit_mutex deadlock via trylock
|
|
- Added nl_process_if_down initialization in the IF_DOWN
|
|
- process
|
|
-
|
|
- 2. Problem: Added fix for the NPAR disabled for 57712
|
|
-
|
|
- Cause: The mac address was not handled correctly
|
|
-
|
|
- Change: Fixed the mac address handling. Also requires corresponding
|
|
- kernel component for the complete fix
|
|
-
|
|
-uIP v0.6.2.7 (Dec. 7, 2010)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Use the gateway address from the DHCP server the
|
|
- destination IP address is not in the current subnet.
|
|
-
|
|
-uIP v0.6.2.6 (Nov. 16, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Warning message seen in the kernel logs,
|
|
- "uio uio2: uevent: unsupported action string"
|
|
-
|
|
- Cause: The improper string was echo'ed into the UIO trigger
|
|
- field. With an improper string, this message would
|
|
- appear in the kernel logs.
|
|
-
|
|
- Change: uIP will now write the string "online" to the UIO
|
|
- trigger field. This is the string expected by the
|
|
- Linux kernel base driver.
|
|
-
|
|
- 2. Problem: uIP would segfault during a heavily login/logout
|
|
- iSCSI subsystem reset senario
|
|
-
|
|
- Cause: A double free occurred in the logging portion of the
|
|
- uIP code, but this was root cause to a double free when
|
|
- manipulating the NetLink buffers.
|
|
-
|
|
- Change: Properly look at the return code from the routine which
|
|
- will read NetLink messages. Also only free buffers
|
|
- if they are allocated.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Add ability to print kernel version and machine
|
|
- architecture to further help debug problems.
|
|
-
|
|
- 2. Change: Apply the netmask from DHCP if provided.
|
|
-
|
|
-uIP v0.6.2.5 (Nov. 10, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iscsid would try to conenct with unintended iSCSI
|
|
- targets
|
|
-
|
|
- Cause: uIP would blindly return the iSCSI target MAC address
|
|
- regardless if the iSCSI target is reachable via the
|
|
- given port.
|
|
-
|
|
- Change: uIP will try to filter the requests coming from CNIC
|
|
- by automatically generating a network mask based off
|
|
- the configured IP addressed. Then this netmask is
|
|
- masked with the destination IP address. If there is
|
|
- a match, then the path_req is allowed through.
|
|
-
|
|
- 2. Problem: Problems reconnecting back to the target when running
|
|
- MTU stress tests.
|
|
-
|
|
- Cause: cnic/bnx2i and uIP could possibly get out of sync when
|
|
- an if_down message is sent.
|
|
-
|
|
- Change: uIP will now immediately react to the if_down message,
|
|
- and flush all the path req's and then to process to
|
|
- if_close.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Fix compile warnings for src/unix/nic_nl.c,
|
|
- and src/unix/main.c
|
|
-
|
|
-uIP v0.6.2.4 (Nov. 4, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iSCSI HBA: brcm_iscsiuio segfault during ifdown
|
|
- with many active sessions
|
|
-
|
|
- Cause: uIP will segfault when traversing the error path when
|
|
- an iSCSI connection is starting but the sysfs entries
|
|
- have not been created yet.
|
|
-
|
|
- Change: Use the errno value rather then the one from the file
|
|
- descriptor because the file descriptor will be NULL and
|
|
- the NULL dereference will cause a segfault.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Added initial changes for iSCSI multi-function support for
|
|
- 10G NIC's.
|
|
- 2. Change: Add more detailed messages for error pathes in nic_utils
|
|
-
|
|
-uIP v0.6.2.3 (October 28, 2010)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Add support for bnx2x-1.62.x drivers
|
|
-
|
|
-uIP v0.6.2.2 (October 18, 2010)
|
|
-=======================================================
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Only allow iSCSI connections with known bnx2x HSI's.
|
|
-
|
|
-uIP v0.6.2.1 (October 7, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: After multiple MTU changes, the ethtool IOCTL used to
|
|
- determine the bnx2x driver version fails and eventually
|
|
- iSCSI connections would not reconnect.
|
|
-
|
|
- Cause: The socket file descriptor used during the ethtool IOCTL
|
|
- call was never closed and leaked.
|
|
-
|
|
- Change: On the error path when calling the ethtool IOCTL, the
|
|
- file descriptor is now properly closed.
|
|
-
|
|
-uIP v0.5.39 (September 15, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Could not offload IPv4 VLAN connection when the target tries
|
|
- to ARP the iSCSI initiator
|
|
-
|
|
- Cause: In the ARP reply, the ether field was incorrect.
|
|
-
|
|
- Change: Properly set the ether field to 802.1Q type (0x8100)
|
|
-
|
|
-uIP v0.5.38 (September 14, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: uIP would cause a panic dump when the NIC was going down
|
|
-
|
|
- Cause: uIP and CNIC where not synchonized on NIC state
|
|
-
|
|
- Change: Check if the RX BD's which are zero'ed by CNIC when the
|
|
- NIC is going down. If the BD addresses are zero, then
|
|
- uIP will drop the TX packets.
|
|
-
|
|
-uIP v0.5.37 (August 21, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: uIP would segfault on ifup/ifdown stress test when using
|
|
- DHCP to determine local IP address.
|
|
-
|
|
- Cause: The uIP would use a NULL buffer during data transmission.
|
|
-
|
|
- Change: Drop packets when there are no buffer avaliable.
|
|
-
|
|
-uIP v0.5.36 (August 21, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iSCSI boot would not completely login after the pivot
|
|
- root operation.
|
|
-
|
|
- Cause: The uIP would not properly start the NIC interface.
|
|
-
|
|
- Change: uIP should only check the NIC state to determine whether
|
|
- to start the NIC thread or not.
|
|
-
|
|
- 2. Problem: uIP would segfault during if'up if'down testing.
|
|
-
|
|
- Cause: The uIP would improperly start 2 NIC threads for the
|
|
- same NIC interface.
|
|
-
|
|
- Change: uIP should properly lock the NIC list when disabling/removing
|
|
- the NIC threads.
|
|
-
|
|
-
|
|
-uIP v0.5.35 (August 20, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Sessions would hang with ethtool self-test
|
|
-
|
|
- Cause: The uIP would hang because the socket layer was stuck
|
|
- because there is much contention for that socket. This
|
|
- would hang the CNIC thread.
|
|
-
|
|
- Change: Remove any IOCTL calls in uIP which may colide with
|
|
- the ethtool self test. The driver version is only
|
|
- capture during uIP initialization.
|
|
-
|
|
- 2. Problem: There were session recovery issue when using DHCP
|
|
- if up/down tests.
|
|
-
|
|
- Cause: The uIP would hang because the DHCP requests would
|
|
- timeout if the network interface is downed which would
|
|
- hang all the other uIP threads.
|
|
-
|
|
- Change: Ensure that the DHCP state machine had exit points
|
|
- if the network interface was down'ed.
|
|
-
|
|
-
|
|
-uIP v0.5.34 (August 18, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Sessions would not recover with ethtool self-test
|
|
-
|
|
- Cause: The uIP would hang because either the NetLink buffer is
|
|
- full or that any socket operations used to manipulate
|
|
- multicast addresses would block.
|
|
-
|
|
- Change: Ensure that the socket used for multicast addressing is
|
|
- set to nonblocking. Drain the NetLink buffer without
|
|
- using the eventing, but with a more aggressive poll routine.
|
|
-
|
|
- 2. Problem: Sessions would not recover with L2 driver load/unload on
|
|
- RHEL 6.0 SS9
|
|
-
|
|
- Cause: The uIP would close the NIC thread too early and would
|
|
- deadlock on cloing the NIC thread.
|
|
-
|
|
- Change: Ensure that the NIC thread is canceled/closed only in one
|
|
- location, in the NIC remove routine.
|
|
-
|
|
-
|
|
-uIP v0.5.33 (August 17, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Error message seen from the uIP stack for valid packets.
|
|
-
|
|
- Cause: The uIP was incorrectly marking logging messages for valid
|
|
- packets as errors because it didn't know how to parase them.
|
|
-
|
|
- Change: Changed the following from error to debug message
|
|
- ipv6: invalid version
|
|
- ipv4: invalid version or header length.
|
|
- icmpv6: unknown ICMP message.
|
|
- ip: neither tcp nor icmp
|
|
- Changed the following from error to warn message
|
|
- udp: bad checksum
|
|
- tcp: bad checksum
|
|
- tcp: got reset, aborting connection.
|
|
-
|
|
- 2. Problem: After multiple iterations the loading and unloading of
|
|
- the Broadcom Linux drivers with active connections
|
|
- would not cause the sessions to recover on RHEL 6.0
|
|
- snapshot 9.
|
|
-
|
|
- Cause: There was a deadlock in the nic mutex
|
|
-
|
|
- Change: Lock ordering for the nic mutex and nic list mutex must
|
|
- be inforced.
|
|
-
|
|
- 3. Problem: After multiple iterations of running the ethtool selftest
|
|
- the Broadcom Linux drivers with active connections
|
|
- would not cause the sessions to recover on RHEL 5.5.
|
|
-
|
|
- Cause: The Netlink buffer between uIP and CNIC would get full.
|
|
-
|
|
- Change: Poll more regularly for packets in the Netlink buffer
|
|
- from 4 times a second to 100 times a 1 second.
|
|
- Drain packets during the PATH_REQ packet pull.
|
|
-
|
|
-
|
|
-uIP v0.5.32 (August 14, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Error message 'nic eth0: Didn't find type 0xaa bb' seen.
|
|
-
|
|
- Cause: Valid non-DIX Ethernet packets as being passed to the
|
|
- uIP. uIP will drop these packets but should be logged
|
|
- correctly.
|
|
-
|
|
- Change: These packets are valid, and should only be logged for
|
|
- debugging purposes.
|
|
-
|
|
- 2. Problem: Error message 'Dropped previous transmitted packet' seen.
|
|
-
|
|
- Cause: The TX ring is full, and here uIP is trying to transmit a
|
|
- packet which will be dropped. This is a valid state but
|
|
- the log message is marked incorrectly
|
|
-
|
|
- Change: These messages are not warnings and should be logging when
|
|
- debugging is enabled.
|
|
-
|
|
- 3. Problem: Error message: "iscsi_ipc eth0 Transport name is not
|
|
- equal expected: got: bnx2i" seen.
|
|
-
|
|
- Cause: The iface_rec structure is different between iscsid version.
|
|
- For RHEL 5.5, iscsid is versioned 871, for RHEL 6.0 is
|
|
- versioned 872.
|
|
-
|
|
- Change: Allow uIP to compile against a different version of iscsid.
|
|
-
|
|
-
|
|
-uIP v0.5.31 (August 12, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Softlock would occur showing that the NetLink table
|
|
- lock was taken but never released.
|
|
-
|
|
- Cause: NetLink socket buffer would fill with constant PATH_REQ
|
|
- messages preventing PATH_REQ response from libiscsi
|
|
-
|
|
- Change: Now uIP will drain the NetLink buffer while looking for
|
|
- a response.
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Add documentation for VLAN configuration and restrictions.
|
|
-
|
|
-
|
|
-uIP v0.5.30 (August 6, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iscsid thread will stall if closing the uio files nodes
|
|
- is stuck
|
|
-
|
|
- Cause: uIP would indefinitely block waiting for the mutex shared
|
|
- by the close routine.
|
|
-
|
|
- Change: Now uIP will try and poll a bit for the mutex. If it can't
|
|
- get this mutex in the iscsid thread then an error is return
|
|
- rather then hold the thread.
|
|
-
|
|
- 2. Problem: IPv6 Unicast Neighbor Adveriserments would have the
|
|
- ICMPv6 option header specifying a MAC.
|
|
-
|
|
- Cause: uIP should use the source IPv6 address to detmine whether
|
|
- to strip the option header or not and not the target address
|
|
- in the ICMPv6 field.
|
|
-
|
|
- Change: The uIP stack return a unicast IPv6 Neighbor Advertisement
|
|
- without the ICMPv6 option as a response to unicast
|
|
- IPv6 Neighbor Solicitations.
|
|
-
|
|
- 3. Problem: There would be TCP SYN packets with improper MAC address.
|
|
-
|
|
- Cause: A zero'ed MAC address was not passed to CNIC to indicate an
|
|
- error or if the IP address didn't resolve.
|
|
-
|
|
- Change: The uIP stack will now return a zero'ed MAC address if it
|
|
- can't find any entries.
|
|
-
|
|
-
|
|
-uIP v0.5.29 (August 6, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: "uip udp: no matching connection found: lport: 35072"
|
|
- seen numerous times in the brcm_iscsiuio log file
|
|
-
|
|
- Cause: This message was incorrectly marked as an error
|
|
-
|
|
- Change: These messages are valid log entries especially if the
|
|
- packet was a broadcast UDP packet not destined for the SUT
|
|
- I will change the code to mark these logs entries as debug.
|
|
-
|
|
-
|
|
-uIP v0.5.28 (August 5, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Can't login into a redirected Equilogic Target
|
|
-
|
|
- Cause: The Equilogic Target uses a unicast IPv6 Neighbor
|
|
- Solicitation to test if the host is up. The uIP stack
|
|
- would return a Neighbor Advertisement with an unneeded
|
|
- ICMPv6 option.
|
|
-
|
|
- Change: Only have the uIP stack return a unicast IPv6 Neighbor
|
|
- Advertisement without the ICMPv6 option.
|
|
-
|
|
- 2. Problem: With older bnx2/bnx2x/cnic/bnx2i driver combinations
|
|
- uIP would segfault when these drivers were unloaded.
|
|
-
|
|
- Cause: When the older drivers were removed, the underlying uio
|
|
- instance was removed causing uIP to have a stale file handle.
|
|
- When uIP finally closes using this stale file handle, either
|
|
- uIP would segfault, or there would be an error in the
|
|
- uio_release() path.
|
|
-
|
|
- Change: Only have the uIP close if the UIO file node exists.
|
|
-
|
|
-
|
|
-uIP v0.5.27 (July 31, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iSCSI HBA: Unable to use DHCP address for iSCSI interface
|
|
- if a connection was previously made with a static address
|
|
- on bnx2 devices.
|
|
-
|
|
- Cause: Because the device is closed and reopen'ed the TX consumer
|
|
- indexes were not persisted
|
|
-
|
|
- Change: Only discard the TX consumer indexes only when the devices
|
|
- will be discarded or closed
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
- 1. Change: Change CNIC references to bnx2 in the bnx2 user space
|
|
- driver.
|
|
-
|
|
-
|
|
-uIP v0.5.26 (July 30, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: iSCSI HBA: Unable to use DHCP address for iSCSI interface
|
|
- if a connection was previously made with a static address on
|
|
- bnx2x devices.
|
|
-
|
|
- Cause: Because the device is closed and reopen'ed the TX consumer
|
|
- indexes were not persisted
|
|
-
|
|
- Change: Only discard the TX consumer indexes only when the devices
|
|
- will be discarded
|
|
-
|
|
- 2. Problem: IPv6 using VLAN's didn't login
|
|
-
|
|
- Cause: The uIP code used to determine if the packet was an IPv6
|
|
- or not was not working. This VLAN packets for IPv6 were
|
|
- being mis-interpreted.
|
|
-
|
|
- Change: Make the function is_ipv6() VLAN aware
|
|
-
|
|
- 3. Problem: Persistant targets was not loggin in during boot
|
|
-
|
|
- Cause: If udev was slow and the /dev/uio* were creatly slowly
|
|
- uIP would fail.
|
|
-
|
|
- Change: Poll uIP waiting for /dev/uio* file nodes.
|
|
-
|
|
-uIP v0.5.25 (July 27, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: When using IPv4 DHCP, there are no initial DHCP Discover
|
|
- packets were not seen on the wire.
|
|
-
|
|
- Cause: Packets generated from the app handler from the uIP stack
|
|
- were not placed on the wire.
|
|
-
|
|
- Change: Packets originating from the uIP stack are now always placed
|
|
- on the wire.
|
|
-
|
|
-uIP v0.5.24 (July 25, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: One would see invalid packet packets flow through the
|
|
- uIP stack, where the logs would indicate there is a packet
|
|
- with an invalid length
|
|
-
|
|
- Cause: The BD and CQE consumer indexes were not properly incremented
|
|
- and masked.
|
|
-
|
|
- Change: The BD index is now properly masked. The CQE index is not
|
|
- incremented using the CQE index rather the mistaken BD index.
|
|
-
|
|
- Impact: 10G only
|
|
-
|
|
- 2. Problem: uIP would segfault during the booting of the machine.
|
|
-
|
|
- Cause: uIP was using a NULL data pointer because there was an
|
|
- incorrect packet passed to the stack.
|
|
-
|
|
- Change: Only allow uIP to process data if the packet exists.
|
|
-
|
|
- 3. Problem: uIP would stop processing packets
|
|
-
|
|
- Cause: The uIP code would not properly drain the CQE ring causing
|
|
- it to eventually be full
|
|
-
|
|
- Change: Consume all the CQE elements even if they are ethernet types
|
|
- or not.
|
|
-
|
|
- Impact: 10G only
|
|
-
|
|
- 4. Problem: uIP would stop after if/down of the network interface.
|
|
-
|
|
- Cause: uIP was not kick starting the NIC loop thread properly.
|
|
-
|
|
- Change: Ensure that the NIC loop thread is started by when iscsid
|
|
- request that the interface start the offload. Mark the NIC
|
|
- only if the thread is truly canceled.
|
|
-
|
|
-
|
|
-uIP v0.5.23 (July 20, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Segfault during brcm_iscsiuio initialization
|
|
-
|
|
- Cause: uIP was using a NULL data pointer, because a different
|
|
- thread re-initialized the uIP stack
|
|
-
|
|
- Change: Properly synchronize the initialization of the stack
|
|
-
|
|
- 2. Problem: Deadlock during the printing of heavy debug messages
|
|
-
|
|
- Cause: The variable macro structures would point to invalid
|
|
- data
|
|
-
|
|
- Change: With each invocation of va_copy() a corresponding
|
|
- invocation of va_end() in the same function for the proper
|
|
- cleanup
|
|
-
|
|
- 3. Problem: uIP would hang when the interface could go up/down
|
|
-
|
|
- Cause: uIP would get out of sync with the state of the network
|
|
- interface
|
|
-
|
|
- Change: Instead of detriving state from the UIO file nodes, uIP
|
|
- will take direction from iscsid on when interfaces will be
|
|
- started.
|
|
-
|
|
-uIP v0.5.22 (July 15, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Unable to reconnect via iSCSI offload after
|
|
- ifup/ifdown
|
|
-
|
|
- Cause: uIP was stuck on the thread when closing the NIC main
|
|
- loop
|
|
-
|
|
- Change: Properly synchronize the NetLink CNIC and uevent threads
|
|
-
|
|
- 2. Problem: uIP would crash during boot up.
|
|
-
|
|
- Cause: uIP would overwrite a memory location which was already
|
|
- freed during nic_remove().
|
|
-
|
|
- Change: Since the NIC is freed there is no need to write to
|
|
- update the NIC flags
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Added IPv6 Link Local support
|
|
-
|
|
-
|
|
-uIP v0.5.21 (July 5, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Unable to connect via iSCSI offload after
|
|
- changing L2 address
|
|
-
|
|
- Cause: uIP didn't notice the network inferface going down
|
|
-
|
|
- Change: Allow uIP to persist the stack's IP address after
|
|
- a reset
|
|
-
|
|
- 2. Problem: Unable to connect via IPv4 and IPv6 concurrently
|
|
-
|
|
- Cause: uIP didn't notice the network inferface going down
|
|
-
|
|
- Change: Allow uIP to persist the stack's IP address after
|
|
- a reset and properly bring up the interface
|
|
-
|
|
- 3. Problem: Unable to connect via VLAN
|
|
-
|
|
- Cause: IP address was no persisted after a device reset
|
|
-
|
|
- Change: When CNIC requests a path request, uIP will use the
|
|
- VLAN passed by the CNIC.
|
|
-
|
|
-
|
|
-uIP v0.5.20 (June 24, 2010)
|
|
-
|
|
-
|
|
-uIP v0.5.20 (June 24, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Certain IPv6 addresses are not repsonded to by
|
|
- the target.
|
|
-
|
|
- Cause: The MAC was generated from the target's IPv6
|
|
- address not the deterived multicast IPv6 address.
|
|
-
|
|
- Change: The destination MAC address should be deterived
|
|
- from the packet's destination IPv6 address and
|
|
- not the target.
|
|
-
|
|
- 2. Problem: brcm_iscsiuio would segfault when L2 interface is
|
|
- bought up and down after being logged into
|
|
-
|
|
- Cause: The NIC thread was not stopped properly
|
|
-
|
|
- Change: When the UIO device is remove and when the
|
|
- cooresponding NIC tracked by brcm_iscsiuio, the
|
|
- daemon would properly wait for the NIC thread to
|
|
- stop.
|
|
-
|
|
-
|
|
-uIP v0.5.19 (June 22, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Can't login after boot
|
|
-
|
|
- Cause: If NIC interfaces are brough up and down quickly
|
|
- uIP wait on an invalid NIC thread
|
|
-
|
|
- Change: Only wait for the NIC thread if the NIC thread
|
|
- exists.
|
|
-
|
|
-uIP v0.5.18 (June 21, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Does not compile on SLES 11 SP1
|
|
-
|
|
- Cause: Automake cached files were included as part of the
|
|
- uIP-0.5.17 package
|
|
-
|
|
- Change: Remove automake cached files, and allow these files
|
|
- to be generated each time the source is compiled
|
|
-
|
|
- 2. Problem: Does not always receive multicast packets
|
|
-
|
|
- Cause: Multicast bit was not set in SORT USER 2 register
|
|
-
|
|
- Change: brcm_iscsiuio will now set the SORT USER 2 registers
|
|
- with both the broadcast and multicast bits.
|
|
-
|
|
- 3. Problem: Existing iSCSI connections do not reconnect after
|
|
- operations which require equivalent driver
|
|
- load/unload operations
|
|
-
|
|
- Cause: Multiple path requests would trample NIC configurations
|
|
-
|
|
- Change: Allow only one path request at a time
|
|
-
|
|
-uIP v0.5.17 (June 16, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: IPv6 neighbor solicitations from brcm_iscsiuio could
|
|
- not be responded to
|
|
-
|
|
- Cause: The IPv6 neighbor solicitation packet had an invalid
|
|
- multicast MAC address
|
|
-
|
|
- Change: Properly set the MAC address multicast bit and OR
|
|
- with the IPv6 destination address
|
|
-
|
|
- 2. Problem: NIC state was not properly synchronized and noticed
|
|
- by Shyam Iyer <shiyer@redhat.com>
|
|
-
|
|
- Change: Properly lock the NIC device when changing state
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Listen for iscsid before daemonizing to close a timing
|
|
- gap which might allow iscsid to start before uIP is
|
|
- completely initialized.
|
|
-
|
|
-uIP v0.5.16 (June 2, 2010)
|
|
-=======================================================
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Formally add IPv6 support. Only a static IPv6 address
|
|
- is supported.
|
|
-
|
|
-uIP v0.5.15 (May 20, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: brcm_iscsiuio would echo packets off the wire
|
|
-
|
|
- Cause: Stale packets from the uIP stack could potentially
|
|
- make it onto the wire causing a network flood
|
|
-
|
|
- Change: Only place on the wire packets uIP intended to place
|
|
- on the wire. Drop all other packets.
|
|
-
|
|
-uIP v0.5.14 (May 18, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: brcm_iscsiuio would crash when offloading using a
|
|
- bnx2x device /dev/mem could not be
|
|
- opened, (ie. SE Linux enabled)
|
|
-
|
|
- Cause: /dev/mem could not be opened, (ie. SE Linux enabled)
|
|
- and then the NIC would be improperly initialized.
|
|
-
|
|
- Change: If /dev/mem is not able to be opened, then the device
|
|
- is closed
|
|
-
|
|
- 2. Problem: brcm_iscsiuio would crash when brcm_iscsiuio is
|
|
- being shutdown
|
|
-
|
|
- Cause: The NIC mutex was deferenced imporperly when the NIC
|
|
- is being closed
|
|
-
|
|
- Change: Take the NIC mutex lock only when the NIC is closed.
|
|
-
|
|
-uIP v0.5.13 (May 16, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: brcm_iscsiuio would crash with heavy traffic directed
|
|
- at the iSCSI traffic
|
|
-
|
|
- Cause: Packets which are sized between 1006-1024 bytes would
|
|
- crash brcm_iscsiuio because brcm_iscsiuio is not sized
|
|
- to handle such large packets
|
|
-
|
|
- Change: Drop large packets, properly hold the NIC mutex lock
|
|
- for the duration when NIC fields are being used.
|
|
-
|
|
-
|
|
-uIP v0.5.12 (May 13, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: brcm_iscsiuio could crash on when L2 interface is
|
|
- ifdown'ed
|
|
-
|
|
- Cause: The local NIC pointer was not initialized properly
|
|
- in the routine parse_iface()
|
|
-
|
|
- Change: Properly initialize the NIC pointer
|
|
-
|
|
- 2. Problem: Documentation referred to older admin_client which
|
|
- doesn't exist any more because brcm_iscsiuio uses
|
|
- the iscsid iface file
|
|
-
|
|
- Change: Remove the stale references
|
|
-
|
|
-
|
|
-uIP v0.5.11 (May 11, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: brcm_iscsiuio could crash on invalid packet sizes
|
|
-
|
|
- Cause: The hardware BD could be a large value because of a
|
|
- hardware error
|
|
-
|
|
- Change: Limit the size of the packet dumped to the MTU size
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: During the running of the configure script now
|
|
- the script will check for ar and ranlib binaries
|
|
-
|
|
-
|
|
-uIP v0.5.10 (May 03, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: BCM57712 not recognized
|
|
-
|
|
- Cause: The PCI ID's in the bnx2x file were missing.
|
|
-
|
|
- Change: Added proper BCM57712, BCM57712E, BCM57713, BCM57713E
|
|
- PCI ID's
|
|
-
|
|
- 2. Problem: (CQ 47481) brcm_iscsiuio not installed in correct location
|
|
-
|
|
- Cause: Default install path for autoconf is /usr/local
|
|
-
|
|
- Change: Change the default prefix to '/' so the brcm_iscsiuio
|
|
- binary is installed to /sbin/
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Remove dependency on Yacc and Lex
|
|
-
|
|
-
|
|
-uIP v0.5.9 (April 28, 2010)
|
|
-=======================================================
|
|
-
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: bnx2x T6.0 driver would not login
|
|
-
|
|
- Cause: The bnx2x code was not using the T6.0 HSI offsets
|
|
-
|
|
- Change: Determine to bnx2x driver version eariler to properly use the
|
|
- T4.8 or T6.0 HSI
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Collapse all the various locks to use the NIC lock to shrink
|
|
- memory footprint
|
|
-
|
|
- 2. Change: Consolidate upper layer checksumming code
|
|
-
|
|
-
|
|
-uIP v0.5.5 (March 02, 2010)
|
|
-=======================================================
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Add support for T6.0 bnx2x HSI and 57712.
|
|
-
|
|
- 2. Change: Initial support for IPv6
|
|
-
|
|
-uIP v0.5.8 (April 22, 2010)
|
|
-=======================================================
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Add support for T6.0 bnx2x HSI and 57712.
|
|
-
|
|
- 2. Change: Initial support for IPv6
|
|
-
|
|
-uIP v0.5.7 (March 17, 2010)
|
|
-=======================================================
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Add to documentation on discovering on a particular
|
|
- iface before logging in
|
|
-
|
|
-uIP v0.5.6 (Mar 05, 2009)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: bnx2x panic dump would be seen when sending
|
|
- traffic to uIP
|
|
-
|
|
- Cause: The TX producer index was not properly
|
|
- incrementing when the wrapping occured
|
|
-
|
|
- Change: Do not skip the last TX producer index like the
|
|
- TX BD's
|
|
-
|
|
- Impact: None.
|
|
-
|
|
-uIP v0.5.5 (March 02, 2010)
|
|
-=======================================================
|
|
- Initial release
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Add to documentation on debugging/logging for uIP
|
|
-
|
|
-
|
|
-uIP v0.5.4 (Feb 22, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Compile error where 'ETHERTYPE_VLAN' define
|
|
- is missing
|
|
-
|
|
- Cause: Certain distributions do not define 'ETHERTYPE_VLAN'
|
|
- in the header file "net/ethernet.h".
|
|
-
|
|
- Change: Added proper defines for ETHERTYPE_VLAN when necessary
|
|
-
|
|
- Impact: None.
|
|
-
|
|
-
|
|
-uIP v0.5.3 (Feb 18, 2010)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Using VLAN's on offloaded iSCSI connections
|
|
-
|
|
- Cause: (CQ45983) VLAN tags were not being properly inserted
|
|
- when sending the ARP request packets
|
|
-
|
|
- Change: Added VLAN tags when sending ARP request packets
|
|
-
|
|
- Impact: None.
|
|
-
|
|
-
|
|
-uIP v0.5.2 (Dec 10, 2009)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: Switching between 10G and 1G iSCSI offloaded
|
|
- devices caused login connectivity problems
|
|
-
|
|
- Cause: The NIC devices within uIP were not cleanup
|
|
- properly.
|
|
-
|
|
- Change: The NIC structure is not re-initialized and the
|
|
- NIC thread is destroyed when the host network
|
|
- interface is brought down.
|
|
-
|
|
- Impact: None.
|
|
-
|
|
-
|
|
-uIP v0.5.1 (Dec 9, 2009)
|
|
-=======================================================
|
|
- Fixes
|
|
- -----
|
|
- 1. Problem: 10G devices behind PCI bridges would not collect
|
|
-
|
|
- Cause: PCI bus:slot.func string was parsed incorrectly
|
|
- because the bridge string was used
|
|
-
|
|
- Change: Parse the proper PCI bus:slot.func string.
|
|
-
|
|
- Impact: None.
|
|
-
|
|
-
|
|
-uIP v0.5.0b (Nov 24, 2009)
|
|
-=======================================================
|
|
- Initial release
|
|
-
|
|
- Enhancements
|
|
- ------------
|
|
-
|
|
- 1. Change: Add Broadcom 10G iSCSI offload support
|
|
-
|
|
- Impact: Linux
|
|
-
|
|
diff --git a/iscsiuio/configure.ac b/iscsiuio/configure.ac
|
|
deleted file mode 100644
|
|
index 9b85448..0000000
|
|
--- a/iscsiuio/configure.ac
|
|
+++ /dev/null
|
|
@@ -1,104 +0,0 @@
|
|
-dnl iscsiuio uIP user space stack configure.ac file
|
|
-dnl
|
|
-dnl Copyright (c) 2004-2013 Broadcom Corporation
|
|
-dnl Copyright (c) 2014, QLogic Corporation
|
|
-dnl
|
|
-dnl This program is free software; you can redistribute it and/or modify
|
|
-dnl it under the terms of the GNU General Public License as published by
|
|
-dnl the Free Software Foundation.
|
|
-dnl
|
|
-dnl Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
-dnl Benjamin Li (benli@broadcom.com)
|
|
-dnl
|
|
-
|
|
-PACKAGE=iscsiuio
|
|
-VERSION=0.7.8.6
|
|
-
|
|
-AC_INIT([iscsiuio], [0.7.8.6], [QLogic-Storage-Upstream@cavium.com])
|
|
-
|
|
-AM_INIT_AUTOMAKE
|
|
-AC_CONFIG_HEADER(config.h)
|
|
-AC_PATH_PROGS(BASH, bash)
|
|
-
|
|
-AC_PROG_CC
|
|
-AM_PROG_CC_C_O
|
|
-
|
|
-AC_PROG_RANLIB
|
|
-
|
|
-AC_GNU_SOURCE
|
|
-AC_PROG_INSTALL
|
|
-AC_PROG_GCC_TRADITIONAL
|
|
-
|
|
-# Checks for typedefs, structures, and compiler characteristics.
|
|
-AC_C_CONST
|
|
-AC_C_INLINE
|
|
-AC_TYPE_OFF_T
|
|
-AC_TYPE_SIZE_T
|
|
-AC_CHECK_TYPES(int8_t)
|
|
-AC_CHECK_TYPES(uint8_t)
|
|
-AC_CHECK_TYPES(int16_t)
|
|
-AC_CHECK_TYPES(uint16_t)
|
|
-AC_CHECK_TYPES(int32_t)
|
|
-AC_CHECK_TYPES(uint32_t)
|
|
-AC_CHECK_TYPES(int64_t)
|
|
-AC_CHECK_TYPES(uint64_t)
|
|
-AC_CHECK_SIZEOF(short, 2)
|
|
-AC_CHECK_SIZEOF(int, 4)
|
|
-AC_CHECK_SIZEOF(long, 4)
|
|
-
|
|
-AC_C_BIGENDIAN(AC_SUBST([ENDIAN],[BIG]),AC_SUBST([ENDIAN],[LITTLE]))
|
|
-
|
|
-AC_LIBTOOL_DLOPEN
|
|
-
|
|
-# libtool stuff
|
|
-AC_PROG_LIBTOOL
|
|
-
|
|
-: ${CFLAGS:="-O2"}
|
|
-CFLAGS="${CFLAGS} -Wall"
|
|
-## check for --enable-debug first before checking CFLAGS before
|
|
-## so that we don't mix -O and -g
|
|
-AC_ARG_ENABLE(debug,
|
|
-[ --enable-debug Turn on compiler debugging information (default=no)],
|
|
- [if eval "test x$enable_debug = xyes"; then
|
|
- CFLAGS="${CFLAGS} -g -O0"
|
|
- fi])
|
|
-AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
|
|
-## check for systemd support, default on
|
|
-AC_ARG_WITH([systemd],
|
|
- AS_HELP_STRING([--without-systemd], [Build without systemd]),
|
|
- [case "${withval}" in
|
|
- yes) with_libsystemd=yes ;;
|
|
- no) wth_libsystemd=no ;;
|
|
- *) AC_MSG_ERROR([bad value $withval for --with-systemd]) ;;
|
|
- esac],[with_libsystemd=auto])
|
|
-AS_IF([test "$with_libsystemd" != no],[
|
|
- PKG_CHECK_MODULES([LIBSYSTEMD],[libsystemd],[LDFLAGS=$LIBSYSTEMD_LIBS],[
|
|
- if test "$with_libsystemd" = yes; then
|
|
- AC_MSG_ERROR([could not find libsystemd using pkg-config])
|
|
- else
|
|
- CFLAGS="${CFLAGS} -DNO_SYSTEMD"
|
|
- fi
|
|
- ])
|
|
-],[
|
|
- CFLAGS="${CFLAGS} -DNO_SYSTEMD"
|
|
-])
|
|
-
|
|
-AC_CONFIG_COMMANDS([default],[[
|
|
- if [ -n "$SOURCE_DATE_EPOCH" ] ; then
|
|
- echo 'char *build_date = "'`LC_ALL=C.UTF-8 date --date=@$SOURCE_DATE_EPOCH -u`'";' > src/unix/build_date.c
|
|
- else
|
|
- echo 'char *build_date = "'`date`'";' > src/unix/build_date.c
|
|
- fi
|
|
- echo 'extern char *build_date;'> src/unix/build_date.h
|
|
-]],[[]])
|
|
-
|
|
-AC_PREFIX_DEFAULT()
|
|
-
|
|
-AC_OUTPUT([Makefile
|
|
-src/Makefile
|
|
-src/apps/Makefile
|
|
-src/apps/dhcpc/Makefile
|
|
-src/apps/brcm-iscsi/Makefile
|
|
-src/uip/Makefile
|
|
-src/unix/Makefile
|
|
-src/unix/libs/Makefile])
|
|
diff --git a/iscsiuio/docs/iscsiuio.8 b/iscsiuio/docs/iscsiuio.8
|
|
deleted file mode 100644
|
|
index ea2ae02..0000000
|
|
--- a/iscsiuio/docs/iscsiuio.8
|
|
+++ /dev/null
|
|
@@ -1,89 +0,0 @@
|
|
-.\" Copyright (c) 2010-2013 Broadcom Corporation
|
|
-.\" Copyright (c) 2014, QLogic Corporation
|
|
-.\" This is free documentation; you can redistribute it and/or
|
|
-.\" modify it under the terms of the GNU General Public License as
|
|
-.\" published by the Free Software Foundation.
|
|
-.\"
|
|
-.\" bnx2.4,v 0.7.8.1b
|
|
-.\"
|
|
-.TH iscsiuio 8 "12/10/2013" "QLogic Corporation"
|
|
-.\"
|
|
-.\" NAME part
|
|
-.\"
|
|
-.SH NAME
|
|
-iscsiuio \- iSCSI UserSpace I/O driver
|
|
-.\"
|
|
-.\" SYNOPSIS part
|
|
-.\"
|
|
-.SH SYNOPSIS
|
|
-.B iscsiuio
|
|
-.RB [ -d -f -v ]
|
|
-.PP
|
|
-.\"
|
|
-.\" DESCRIPTION part
|
|
-.\"
|
|
-.SH DESCRIPTION
|
|
-iscsiuio is the UserSpace I/O driver for the QLogic NetXtreme II
|
|
-BCM5706/5708/5709 series PCI/PCI-X Gigabit Ethernet Network Interface Card
|
|
-(NIC) and for the QLogic NetXtreme II BCM57710/57711/57712/57800/57810/57840
|
|
-series PCI-E 10 Gigabit Ethernet Network Interface Card.
|
|
-The driver has been tested on 2.6.28 kernels and above.
|
|
-.PP
|
|
-Refer to the README.TXT from the driver package on how to
|
|
-compile and install the driver.
|
|
-.PP
|
|
-Refer to various Linux documentations
|
|
-on how to configure network protocol and address.
|
|
-.\"
|
|
-.\" DRIVER DEPENDENCIES part
|
|
-.\"
|
|
-.SH DRIVER DEPENDENCIES
|
|
-
|
|
-.\"
|
|
-.\" PARAMETER part
|
|
-.\"
|
|
-.SH PARAMETERS
|
|
-There are very few parameters when running this application.
|
|
-.TP
|
|
-.BI -d|--debug <debug level>
|
|
-This is to enable debug mode where debug messages will be sent to stdout
|
|
-The following debug modes are supported
|
|
-.P
|
|
-.RS
|
|
-DEBUG 4 - Print all messages
|
|
-.P
|
|
-INFO 3 - Print messages needed to follow the uIP code (default)
|
|
-.P
|
|
-WARN 2 - Print warning messages
|
|
-.P
|
|
-ERROR 1 - Only print critical errors
|
|
-.RE
|
|
-.PP
|
|
-.TP
|
|
-.TP
|
|
-.BI -f|--foreground
|
|
-This is to enable foreground mode so that this application doesn't get sent
|
|
-into the background.
|
|
-.PP
|
|
-.TP
|
|
-.BI -v|--version
|
|
-This is to print the version.
|
|
-.PP
|
|
-.TP
|
|
-.BI -p|--pid <pidfile>
|
|
-Use pidfile (default /run/iscsiuio.pid )
|
|
-.PP
|
|
-.TP
|
|
-.BI -h|--help
|
|
-Display this help and exit.
|
|
-
|
|
-
|
|
-.\"
|
|
-.\" AUTHOR part
|
|
-.\"
|
|
-.SH AUTHOR
|
|
-Benjamin Li \- benli@broadcom.com
|
|
-.P
|
|
-Eddie Wai \- eddie.wai@broadcom.com
|
|
-.SH Maintained by
|
|
-QLogic-Storage-Upstream@qlogic.com
|
|
diff --git a/iscsiuio/iscsiuiolog b/iscsiuio/iscsiuiolog
|
|
deleted file mode 100644
|
|
index 360947c..0000000
|
|
--- a/iscsiuio/iscsiuiolog
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
-/var/log/iscsiuio.log {
|
|
- weekly
|
|
- missingok
|
|
- notifempty
|
|
- rotate 4
|
|
- sharedscripts
|
|
- postrotate
|
|
- pkill -USR1 iscsiuio 2> /dev/null || true
|
|
- endscript
|
|
-}
|
|
diff --git a/iscsiuio/src/.gitignore b/iscsiuio/src/.gitignore
|
|
deleted file mode 100644
|
|
index 10301e2..0000000
|
|
--- a/iscsiuio/src/.gitignore
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-*.a
|
|
diff --git a/iscsiuio/src/Makefile.am b/iscsiuio/src/Makefile.am
|
|
deleted file mode 100644
|
|
index 44b0085..0000000
|
|
--- a/iscsiuio/src/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-SUBDIRS = apps uip unix
|
|
diff --git a/iscsiuio/src/README b/iscsiuio/src/README
|
|
deleted file mode 100644
|
|
index 9fca6fb..0000000
|
|
--- a/iscsiuio/src/README
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-uIP is a very small implementation of the TCP/IP stack that is written
|
|
-by Adam Dunkels <adam@sics.se>. More information can be obtained
|
|
-at the uIP homepage at http://www.sics.se/~adam/uip/.
|
|
-
|
|
-This is version $Name: uip-1-0 $.
|
|
-
|
|
-The directory structure look as follows:
|
|
-
|
|
-apps/ - Example applications
|
|
-doc/ - Documentation
|
|
-lib/ - Library code used by some applications
|
|
-uip/ - uIP TCP/IP stack code
|
|
-unix/ - uIP as a user space process under FreeBSD or Linux
|
|
diff --git a/iscsiuio/src/apps/Makefile.am b/iscsiuio/src/apps/Makefile.am
|
|
deleted file mode 100644
|
|
index 08ed18d..0000000
|
|
--- a/iscsiuio/src/apps/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-SUBDIRS = dhcpc brcm-iscsi
|
|
diff --git a/iscsiuio/src/apps/README b/iscsiuio/src/apps/README
|
|
deleted file mode 100644
|
|
index 0096c4e..0000000
|
|
--- a/iscsiuio/src/apps/README
|
|
+++ /dev/null
|
|
@@ -1,2 +0,0 @@
|
|
-This directory contains a few example applications. They are not all
|
|
-heavily tested, however.
|
|
diff --git a/iscsiuio/src/apps/brcm-iscsi/Makefile.am b/iscsiuio/src/apps/brcm-iscsi/Makefile.am
|
|
deleted file mode 100644
|
|
index 00cbd8e..0000000
|
|
--- a/iscsiuio/src/apps/brcm-iscsi/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-AM_CFLAGS = -I${top_srcdir}/src/unix \
|
|
- -I${top_srcdir}/src/uip \
|
|
- -I${top_srcdir}/src/apps/dhcpc \
|
|
- -I${top_srcdir}/src/apps/brcm-iscsi \
|
|
- -I${top_srcdir}/../include \
|
|
- -I${top_srcdir}/../usr
|
|
-
|
|
-noinst_LIBRARIES = lib_apps_brcm_iscsi.a
|
|
-
|
|
-lib_apps_brcm_iscsi_a_SOURCES = brcm_iscsi.c
|
|
-
|
|
-lib_apps_brcm_iscsi_a_CFLAGS = $(AM_CFLAGS) \
|
|
- -DBYTE_ORDER=@ENDIAN@
|
|
diff --git a/iscsiuio/src/apps/brcm-iscsi/Makefile.brcm-iscsi b/iscsiuio/src/apps/brcm-iscsi/Makefile.brcm-iscsi
|
|
deleted file mode 100644
|
|
index 732275f..0000000
|
|
--- a/iscsiuio/src/apps/brcm-iscsi/Makefile.brcm-iscsi
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-APP_SOURCES += brcm-iscsi.c
|
|
diff --git a/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.c b/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.c
|
|
deleted file mode 100644
|
|
index 4223ca4..0000000
|
|
--- a/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.c
|
|
+++ /dev/null
|
|
@@ -1,89 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li <benli@broadcom.com>
|
|
- * Based on code example from Adam Dunkels
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- */
|
|
-/**
|
|
- * \addtogroup brcm-iscsi
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * An example of how to write uIP applications
|
|
- * with protosockets
|
|
- * \author
|
|
- * Benjamin Li <benli@broadcom.com>
|
|
- */
|
|
-
|
|
-/*
|
|
- * This is a short example of how to write uIP applications using
|
|
- * protosockets.
|
|
- */
|
|
-
|
|
-/*
|
|
- * We define the application state (struct hello_world_state) in the
|
|
- * hello-world.h file, so we need to include it here. We also include
|
|
- * uip.h (since this cannot be included in hello-world.h) and
|
|
- * <string.h>, since we use the memcpy() function in the code.
|
|
- */
|
|
-#include "brcm_iscsi.h"
|
|
-#include "uip.h"
|
|
-#include <string.h>
|
|
-#include <stdio.h>
|
|
-
|
|
-#include "uip_arp.h"
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/*
|
|
- * The initialization function. We must explicitly call this function
|
|
- * from the system initialization code, some time after uip_init() is
|
|
- * called.
|
|
- */
|
|
-void brcm_iscsi_init(void)
|
|
-{
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/*
|
|
- * In hello-world.h we have defined the UIP_APPCALL macro to
|
|
- * hello_world_appcall so that this funcion is uIP's application
|
|
- * function. This function is called whenever an uIP event occurs
|
|
- * (e.g. when a new connection is established, new data arrives, sent
|
|
- * data is acknowledged, data needs to be retransmitted, etc.).
|
|
- */
|
|
-void brcm_iscsi_appcall(struct uip_stack *ustack)
|
|
-{
|
|
-}
|
|
diff --git a/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.h b/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.h
|
|
deleted file mode 100644
|
|
index 10bfc95..0000000
|
|
--- a/iscsiuio/src/apps/brcm-iscsi/brcm_iscsi.h
|
|
+++ /dev/null
|
|
@@ -1,91 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li <benli@broadcom.com>
|
|
- * Based on code example from Adam Dunkels
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- */
|
|
-/**
|
|
- * \addtogroup apps
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \defgroup helloworld Hello, world
|
|
- * @{
|
|
- *
|
|
- * A small example showing how to write applications with
|
|
- * \ref psock "protosockets".
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Header file for an example of how to write uIP applications
|
|
- * with protosockets.
|
|
- * \author
|
|
- * Benjamin Li <benli@broadcom.com>
|
|
- */
|
|
-
|
|
-#ifndef __BRCM_ISCSI_H__
|
|
-#define __BRCM_ISCSI_H__
|
|
-
|
|
-/* Since this file will be included by uip.h, we cannot include uip.h
|
|
- here. But we might need to include uipopt.h if we need the u8_t and
|
|
- u16_t datatypes. */
|
|
-#include "uipopt.h"
|
|
-#include "uip.h"
|
|
-#include "psock.h"
|
|
-
|
|
-/* Next, we define the hello_world_state structure. This is the state
|
|
- of our application, and the memory required for this state is
|
|
- allocated together with each TCP connection. One application state
|
|
- for each TCP connection. */
|
|
-struct hello_world_state {
|
|
- struct psock p;
|
|
- u8_t inputbuffer[32];
|
|
- u8_t name[40];
|
|
-
|
|
- struct uip_udp_conn *conn;
|
|
-};
|
|
-
|
|
-/* Finally we define the application function to be called by uIP. */
|
|
-void brcm_iscsi_appcall(struct uip_stack *ustack);
|
|
-#ifndef UIP_APPCALL
|
|
-#define UIP_APPCALL brcm_iscsi_appcall
|
|
-#endif /* UIP_APPCALL */
|
|
-
|
|
-void brcm_iscsi_init(void);
|
|
-
|
|
-#endif /* __BRCM_ISCSI_H__ */
|
|
-/** @} */
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/apps/dhcpc/Makefile.am b/iscsiuio/src/apps/dhcpc/Makefile.am
|
|
deleted file mode 100644
|
|
index 1c97993..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-AM_CFLAGS = -I${top_srcdir}/src/unix \
|
|
- -I${top_srcdir}/src/uip \
|
|
- -I${top_srcdir}/src/apps/dhcpc \
|
|
- -I${top_srcdir}/src/apps/brcm-iscsi \
|
|
- -I${top_srcdir}/../include \
|
|
- -I${top_srcdir}/../usr
|
|
-
|
|
-noinst_LIBRARIES = lib_apps_dhcpc.a
|
|
-
|
|
-lib_apps_dhcpc_a_SOURCES = dhcpc.c dhcpv6.c
|
|
-
|
|
-lib_apps_dhcpc_a_CFLAGS = $(AM_CFLAGS) \
|
|
- -DBYTE_ORDER=@ENDIAN@
|
|
diff --git a/iscsiuio/src/apps/dhcpc/Makefile.dhcpc b/iscsiuio/src/apps/dhcpc/Makefile.dhcpc
|
|
deleted file mode 100644
|
|
index f84c84f..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/Makefile.dhcpc
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-APP_SOURCES += dhcpc.c timer.c
|
|
diff --git a/iscsiuio/src/apps/dhcpc/dhcpc.c b/iscsiuio/src/apps/dhcpc/dhcpc.c
|
|
deleted file mode 100644
|
|
index f4a9994..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/dhcpc.c
|
|
+++ /dev/null
|
|
@@ -1,417 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2005, Swedish Institute of Computer Science
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <stdlib.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-#include "uip.h"
|
|
-#include "dhcpc.h"
|
|
-#include "timer.h"
|
|
-#include "pt.h"
|
|
-
|
|
-#include "debug.h"
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-
|
|
-struct __attribute__ ((__packed__)) dhcp_msg {
|
|
- u8_t op, htype, hlen, hops;
|
|
- u8_t xid[4];
|
|
- u16_t secs, flags;
|
|
- u8_t ciaddr[4];
|
|
- u8_t yiaddr[4];
|
|
- u8_t siaddr[4];
|
|
- u8_t giaddr[4];
|
|
- u8_t chaddr[16];
|
|
-#ifndef UIP_CONF_DHCP_LIGHT
|
|
- u8_t sname[64];
|
|
- u8_t file[128];
|
|
-#endif
|
|
- u8_t options[312];
|
|
-};
|
|
-
|
|
-#define BOOTP_BROADCAST 0x8000
|
|
-
|
|
-#define DHCP_REQUEST 1
|
|
-#define DHCP_REPLY 2
|
|
-#define DHCP_HTYPE_ETHERNET 1
|
|
-#define DHCP_HLEN_ETHERNET 6
|
|
-#define DHCP_MSG_LEN 236
|
|
-
|
|
-#define DHCPC_SERVER_PORT 67
|
|
-#define DHCPC_CLIENT_PORT 68
|
|
-
|
|
-#define DHCPDISCOVER 1
|
|
-#define DHCPOFFER 2
|
|
-#define DHCPREQUEST 3
|
|
-#define DHCPDECLINE 4
|
|
-#define DHCPACK 5
|
|
-#define DHCPNAK 6
|
|
-#define DHCPRELEASE 7
|
|
-
|
|
-#define DHCP_OPTION_SUBNET_MASK 1
|
|
-#define DHCP_OPTION_ROUTER 3
|
|
-#define DHCP_OPTION_DNS_SERVER 6
|
|
-#define DHCP_OPTION_REQ_IPADDR 50
|
|
-#define DHCP_OPTION_LEASE_TIME 51
|
|
-#define DHCP_OPTION_MSG_TYPE 53
|
|
-#define DHCP_OPTION_SERVER_ID 54
|
|
-#define DHCP_OPTION_REQ_LIST 55
|
|
-#define DHCP_OPTION_END 255
|
|
-
|
|
-static u8_t xid[4] = { 0xad, 0xde, 0x12, 0x23 };
|
|
-static const u8_t magic_cookie[4] = { 99, 130, 83, 99 };
|
|
-
|
|
-struct dhcpc_options dhcpc_opt = {
|
|
- .enable_random_xid = 1,
|
|
-};
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t *add_msg_type(u8_t *optptr, u8_t type)
|
|
-{
|
|
- *optptr++ = DHCP_OPTION_MSG_TYPE;
|
|
- *optptr++ = 1;
|
|
- *optptr++ = type;
|
|
- return optptr;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t *add_server_id(struct dhcpc_state *s, u8_t *optptr)
|
|
-{
|
|
- *optptr++ = DHCP_OPTION_SERVER_ID;
|
|
- *optptr++ = 4;
|
|
- memcpy(optptr, s->serverid, 4);
|
|
- return optptr + 4;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t *add_req_ipaddr(struct dhcpc_state *s, u8_t *optptr)
|
|
-{
|
|
- *optptr++ = DHCP_OPTION_REQ_IPADDR;
|
|
- *optptr++ = 4;
|
|
- memcpy(optptr, s->ipaddr, 4);
|
|
- return optptr + 4;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t *add_req_options(u8_t *optptr)
|
|
-{
|
|
- *optptr++ = DHCP_OPTION_REQ_LIST;
|
|
- *optptr++ = 3;
|
|
- *optptr++ = DHCP_OPTION_SUBNET_MASK;
|
|
- *optptr++ = DHCP_OPTION_ROUTER;
|
|
- *optptr++ = DHCP_OPTION_DNS_SERVER;
|
|
- return optptr;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t *add_end(u8_t *optptr)
|
|
-{
|
|
- *optptr++ = DHCP_OPTION_END;
|
|
- return optptr;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static void create_msg(struct dhcpc_state *s, struct dhcp_msg *m)
|
|
-{
|
|
- m->op = DHCP_REQUEST;
|
|
- m->htype = DHCP_HTYPE_ETHERNET;
|
|
- m->hlen = s->mac_len;
|
|
- m->hops = 0;
|
|
- memcpy(m->xid, xid, sizeof(m->xid));
|
|
- m->secs = 0;
|
|
- m->flags = const_htons(BOOTP_BROADCAST); /* Broadcast bit. */
|
|
- /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr); */
|
|
- memcpy(m->ciaddr, s->ustack->hostaddr, sizeof(m->ciaddr));
|
|
- memset(m->yiaddr, 0, sizeof(m->yiaddr));
|
|
- memset(m->siaddr, 0, sizeof(m->siaddr));
|
|
- memset(m->giaddr, 0, sizeof(m->giaddr));
|
|
- memcpy(m->chaddr, s->mac_addr, s->mac_len);
|
|
- memset(&m->chaddr[s->mac_len], 0, sizeof(m->chaddr) - s->mac_len);
|
|
-#ifndef UIP_CONF_DHCP_LIGHT
|
|
- memset(m->sname, 0, sizeof(m->sname));
|
|
- memset(m->file, 0, sizeof(m->file));
|
|
-#endif
|
|
-
|
|
- memcpy(m->options, magic_cookie, sizeof(magic_cookie));
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static void send_discover(struct dhcpc_state *s)
|
|
-{
|
|
- u8_t *end;
|
|
- struct dhcp_msg *m = (struct dhcp_msg *)s->ustack->uip_appdata;
|
|
-
|
|
- create_msg(s, m);
|
|
-
|
|
- end = add_msg_type(&m->options[4], DHCPDISCOVER);
|
|
- end = add_req_options(end);
|
|
- end = add_end(end);
|
|
-
|
|
- uip_appsend(s->ustack, s->ustack->uip_appdata,
|
|
- end - (u8_t *) s->ustack->uip_appdata);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static void send_request(struct dhcpc_state *s)
|
|
-{
|
|
- u8_t *end;
|
|
- struct dhcp_msg *m = (struct dhcp_msg *)s->ustack->uip_appdata;
|
|
-
|
|
- create_msg(s, m);
|
|
-
|
|
- end = add_msg_type(&m->options[4], DHCPREQUEST);
|
|
- end = add_server_id(s, end);
|
|
- end = add_req_ipaddr(s, end);
|
|
- end = add_end(end);
|
|
-
|
|
- uip_appsend(s->ustack, s->ustack->uip_appdata,
|
|
- end - (u8_t *) s->ustack->uip_appdata);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t parse_options(struct dhcpc_state *s, u8_t *optptr, int len)
|
|
-{
|
|
- u8_t *end = optptr + len;
|
|
- u8_t type = 0;
|
|
-
|
|
- while (optptr < end) {
|
|
- switch (*optptr) {
|
|
- case DHCP_OPTION_SUBNET_MASK:
|
|
- memcpy(s->netmask, optptr + 2, 4);
|
|
- break;
|
|
- case DHCP_OPTION_ROUTER:
|
|
- memcpy(s->default_router, optptr + 2, 4);
|
|
- break;
|
|
- case DHCP_OPTION_DNS_SERVER:
|
|
- memcpy(s->dnsaddr, optptr + 2, 4);
|
|
- break;
|
|
- case DHCP_OPTION_MSG_TYPE:
|
|
- type = *(optptr + 2);
|
|
- break;
|
|
- case DHCP_OPTION_SERVER_ID:
|
|
- memcpy(s->serverid, optptr + 2, 4);
|
|
- break;
|
|
- case DHCP_OPTION_LEASE_TIME:
|
|
- memcpy(s->lease_time, optptr + 2, 4);
|
|
- break;
|
|
- case DHCP_OPTION_END:
|
|
- return type;
|
|
- }
|
|
-
|
|
- optptr += optptr[1] + 2;
|
|
- }
|
|
- return type;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t parse_msg(struct dhcpc_state *s)
|
|
-{
|
|
- struct dhcp_msg *m = (struct dhcp_msg *)s->ustack->uip_appdata;
|
|
-
|
|
- if (m->op == DHCP_REPLY &&
|
|
- memcmp(m->xid, xid, sizeof(xid)) == 0 &&
|
|
- memcmp(m->chaddr, s->mac_addr, s->mac_len) == 0) {
|
|
- memcpy(s->ipaddr, m->yiaddr, 4);
|
|
- return parse_options(s, &m->options[4], uip_datalen(s->ustack));
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static PT_THREAD(handle_dhcp(struct uip_stack *ustack))
|
|
-{
|
|
- struct dhcpc_state *s;
|
|
- s = ustack->dhcpc;
|
|
-
|
|
- if (s == NULL) {
|
|
- LOG_WARN("Could not find dhcpc state");
|
|
- return PT_ENDED;
|
|
- }
|
|
-
|
|
- PT_BEGIN(&s->pt);
|
|
-
|
|
- /* try_again: */
|
|
- s->state = STATE_SENDING;
|
|
- s->ticks = CLOCK_SECOND;
|
|
-
|
|
- do {
|
|
- send_discover(s);
|
|
- timer_set(&s->timer, s->ticks);
|
|
- PT_WAIT_UNTIL(&s->pt, uip_newdata(s->ustack)
|
|
- || timer_expired(&s->timer));
|
|
-
|
|
- if (uip_newdata(s->ustack) && parse_msg(s) == DHCPOFFER) {
|
|
- s->state = STATE_OFFER_RECEIVED;
|
|
- break;
|
|
- }
|
|
-
|
|
- if (s->ticks < CLOCK_SECOND * 60)
|
|
- s->ticks += CLOCK_SECOND;
|
|
- else
|
|
- PT_RESTART(&s->pt);
|
|
- } while (s->state != STATE_OFFER_RECEIVED);
|
|
-
|
|
- s->ticks = CLOCK_SECOND;
|
|
-
|
|
- do {
|
|
- send_request(s);
|
|
- timer_set(&s->timer, s->ticks);
|
|
- s->ustack->uip_flags &= ~UIP_NEWDATA;
|
|
- PT_WAIT_UNTIL(&s->pt, uip_newdata(s->ustack)
|
|
- || timer_expired(&s->timer));
|
|
-
|
|
- if (uip_newdata(s->ustack) && parse_msg(s) == DHCPACK) {
|
|
- s->state = STATE_CONFIG_RECEIVED;
|
|
- break;
|
|
- }
|
|
-
|
|
- if (s->ticks <= CLOCK_SECOND * 10)
|
|
- s->ticks += CLOCK_SECOND;
|
|
- else
|
|
- PT_RESTART(&s->pt);
|
|
- } while (s->state != STATE_CONFIG_RECEIVED);
|
|
-
|
|
- LOG_INFO("Got IP address %d.%d.%d.%d",
|
|
- uip_ipaddr1(s->ipaddr), uip_ipaddr2(s->ipaddr),
|
|
- uip_ipaddr3(s->ipaddr), uip_ipaddr4(s->ipaddr));
|
|
- LOG_INFO("Got netmask %d.%d.%d.%d",
|
|
- uip_ipaddr1(s->netmask), uip_ipaddr2(s->netmask),
|
|
- uip_ipaddr3(s->netmask), uip_ipaddr4(s->netmask));
|
|
- LOG_INFO("Got DNS server %d.%d.%d.%d",
|
|
- uip_ipaddr1(s->dnsaddr), uip_ipaddr2(s->dnsaddr),
|
|
- uip_ipaddr3(s->dnsaddr), uip_ipaddr4(s->dnsaddr));
|
|
- LOG_INFO("Got default router %d.%d.%d.%d",
|
|
- uip_ipaddr1(s->default_router), uip_ipaddr2(s->default_router),
|
|
- uip_ipaddr3(s->default_router),
|
|
- uip_ipaddr4(s->default_router));
|
|
- s->lease_time_nl32 =
|
|
- ntohs(s->lease_time[0]) * 65536ul + ntohs(s->lease_time[1]);
|
|
- LOG_INFO("Lease expires in %ld seconds", s->lease_time_nl32);
|
|
-
|
|
- s->last_update = time(NULL);
|
|
-
|
|
- set_uip_stack(s->ustack,
|
|
- (uip_ip4addr_t *) s->ipaddr,
|
|
- (uip_ip4addr_t *) s->netmask,
|
|
- (uip_ip4addr_t *) s->default_router,
|
|
- (uint8_t *) s->mac_addr);
|
|
-
|
|
- /* Put the stack thread back into a long sleep */
|
|
- s->nic->flags |= NIC_LONG_SLEEP;
|
|
-
|
|
- /* timer_stop(&s.timer); */
|
|
-
|
|
- /* Handle DHCP lease expiration */
|
|
- s->ticks = CLOCK_SECOND * s->lease_time_nl32;
|
|
- timer_set(&s->timer, s->ticks);
|
|
- PT_WAIT_UNTIL(&s->pt, timer_expired(&s->timer));
|
|
- LOG_INFO("Lease expired, re-acquire IP address");
|
|
- s->nic->flags &= ~NIC_LONG_SLEEP;
|
|
- PT_RESTART(&s->pt);
|
|
-
|
|
- /*
|
|
- * PT_END restarts the thread so we do this instead. Eventually we
|
|
- * should reacquire expired leases here.
|
|
- */
|
|
-
|
|
- while (1)
|
|
- PT_YIELD(&s->pt);
|
|
-
|
|
- PT_END(&(s->pt));
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-int dhcpc_init(nic_t *nic, struct uip_stack *ustack,
|
|
- const void *mac_addr, int mac_len)
|
|
-{
|
|
- uip_ip4addr_t addr;
|
|
- struct dhcpc_state *s = ustack->dhcpc;
|
|
-
|
|
- if (s) {
|
|
- LOG_DEBUG("DHCP: DHCP context already allocated");
|
|
- return -EALREADY;
|
|
- }
|
|
- s = malloc(sizeof(*s));
|
|
- if (s == NULL) {
|
|
- LOG_ERR("Couldn't allocate size for dhcpc info");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- memset(s, 0, sizeof(*s));
|
|
- s->nic = nic;
|
|
- s->ustack = ustack;
|
|
- s->mac_addr = mac_addr;
|
|
- s->mac_len = mac_len;
|
|
- s->state = STATE_INITIAL;
|
|
-
|
|
- /* Initialize XID to randomly */
|
|
- if (dhcpc_opt.enable_random_xid == 1) {
|
|
- u32_t gen_xid;
|
|
- gen_xid = random();
|
|
- memcpy(xid, &gen_xid, sizeof(gen_xid));
|
|
- }
|
|
- uip_ipaddr(addr, 255, 255, 255, 255);
|
|
- s->conn = uip_udp_new(ustack, &addr, const_htons(DHCPC_SERVER_PORT));
|
|
- if (s->conn != NULL)
|
|
- uip_udp_bind(s->conn, const_htons(DHCPC_CLIENT_PORT));
|
|
-
|
|
- ustack->dhcpc = s;
|
|
-
|
|
- /* Let the RX poll value take over */
|
|
- nic->flags &= ~NIC_LONG_SLEEP;
|
|
-
|
|
- PT_INIT(&s->pt);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void dhcpc_appcall(struct uip_stack *ustack)
|
|
-{
|
|
- handle_dhcp(ustack);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void dhcpc_request(struct uip_stack *ustack)
|
|
-{
|
|
- struct dhcpc_state *s = ustack->dhcpc;
|
|
-
|
|
- if (s != NULL && s->state == STATE_INITIAL)
|
|
- handle_dhcp(ustack);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
diff --git a/iscsiuio/src/apps/dhcpc/dhcpc.h b/iscsiuio/src/apps/dhcpc/dhcpc.h
|
|
deleted file mode 100644
|
|
index 89cf086..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/dhcpc.h
|
|
+++ /dev/null
|
|
@@ -1,86 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2005, Swedish Institute of Computer Science
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-#ifndef __DHCPC_H__
|
|
-#define __DHCPC_H__
|
|
-
|
|
-#include <time.h>
|
|
-
|
|
-#include "nic.h"
|
|
-#include "timer.h"
|
|
-#include "pt.h"
|
|
-#include "uip.h"
|
|
-
|
|
-#define STATE_INITIAL 0
|
|
-#define STATE_SENDING 1
|
|
-#define STATE_OFFER_RECEIVED 2
|
|
-#define STATE_CONFIG_RECEIVED 3
|
|
-
|
|
-struct dhcpc_state {
|
|
- struct pt pt;
|
|
-
|
|
- nic_t *nic;
|
|
- struct uip_stack *ustack;
|
|
- char state;
|
|
- struct uip_udp_conn *conn;
|
|
- struct timer timer;
|
|
- u32_t ticks;
|
|
- const void *mac_addr;
|
|
- int mac_len;
|
|
-
|
|
- u8_t serverid[4];
|
|
-
|
|
- u16_t lease_time[2];
|
|
- u32_t lease_time_nl32;
|
|
- u16_t ipaddr[2];
|
|
- u16_t netmask[2];
|
|
- u16_t dnsaddr[2];
|
|
- u16_t default_router[2];
|
|
-
|
|
- time_t last_update;
|
|
-};
|
|
-
|
|
-struct dhcpc_options {
|
|
- u8_t enable_random_xid;
|
|
- u8_t xid[4];
|
|
-};
|
|
-
|
|
-int dhcpc_init(nic_t *nic, struct uip_stack *ustack,
|
|
- const void *mac_addr, int mac_len);
|
|
-void dhcpc_request(struct uip_stack *ustack);
|
|
-
|
|
-void dhcpc_appcall(struct uip_stack *ustack);
|
|
-
|
|
-void dhcpc_configured(const struct dhcpc_state *s);
|
|
-
|
|
-#define UIP_UDP_APPCALL dhcpc_appcall
|
|
-
|
|
-#endif /* __DHCPC_H__ */
|
|
diff --git a/iscsiuio/src/apps/dhcpc/dhcpv6.c b/iscsiuio/src/apps/dhcpc/dhcpv6.c
|
|
deleted file mode 100644
|
|
index 461af0e..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/dhcpv6.c
|
|
+++ /dev/null
|
|
@@ -1,517 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai <eddie.wai@broadcom.com>
|
|
- * Based on code from Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * dhcpv6.c - DHCPv6 engine
|
|
- *
|
|
- */
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-
|
|
-#include "ipv6.h"
|
|
-#include "ipv6_pkt.h"
|
|
-#include "dhcpv6.h"
|
|
-#include "logger.h"
|
|
-
|
|
-/* Local function prototypes */
|
|
-static int dhcpv6_send_solicit_packet(struct dhcpv6_context *context);
|
|
-static int dhcpv6_send_request_packet(struct dhcpv6_context *context);
|
|
-static u16_t dhcpv6_init_packet(struct dhcpv6_context *context, u8_t type);
|
|
-static void dhcpv6_init_dhcpv6_server_addr(struct ipv6_addr *addr);
|
|
-static void dhcpv6_handle_advertise(struct dhcpv6_context *context,
|
|
- u16_t dhcpv6_len);
|
|
-static void dhcpv6_handle_reply(struct dhcpv6_context *context,
|
|
- u16_t dhcpv6_len);
|
|
-static int dhcpv6_process_opt_ia_na(struct dhcpv6_context *context,
|
|
- struct dhcpv6_opt_hdr *opt_hdr);
|
|
-static void dhcpv6_process_opt_dns_servers(struct dhcpv6_context *context,
|
|
- struct dhcpv6_opt_hdr *opt_hdr);
|
|
-static void dhcpv6_parse_vendor_option(struct dhcpv6_context *context,
|
|
- u8_t *option, int len);
|
|
-
|
|
-void dhcpv6_init(struct dhcpv6_context *context)
|
|
-{
|
|
- context->seconds = 0;
|
|
- context->our_mac_addr =
|
|
- ipv6_get_link_addr(context->ipv6_context);
|
|
-
|
|
- /* Use the last four bytes of MAC address as base of the transaction
|
|
- ID */
|
|
- context->dhcpv6_transaction_id = context->our_mac_addr->last_4_bytes;
|
|
-
|
|
- context->dhcpv6_done = FALSE;
|
|
- strcpy(context->dhcp_vendor_id, "BRCM ISAN");
|
|
-}
|
|
-
|
|
-int dhcpv6_do_discovery(struct dhcpv6_context *context)
|
|
-{
|
|
- int retc = ISCSI_FAILURE;
|
|
-
|
|
- context->eth =
|
|
- (struct eth_hdr *)context->ipv6_context->ustack->data_link_layer;
|
|
- context->ipv6 =
|
|
- (struct ipv6_hdr *)context->ipv6_context->ustack->network_layer;
|
|
- context->udp =
|
|
- (struct udp_hdr *)((u8_t *)context->ipv6 + sizeof(struct ipv6_hdr));
|
|
-
|
|
- /* Send out DHCPv6 Solicit packet. */
|
|
- dhcpv6_send_solicit_packet(context);
|
|
-
|
|
- return retc;
|
|
-}
|
|
-
|
|
-static int dhcpv6_send_solicit_packet(struct dhcpv6_context *context)
|
|
-{
|
|
- u16_t packet_len;
|
|
-
|
|
- LOG_DEBUG("DHCPV6: Send solicit");
|
|
- packet_len = dhcpv6_init_packet(context, DHCPV6_SOLICIT);
|
|
- context->dhcpv6_state = DHCPV6_STATE_SOLICIT_SENT;
|
|
- ipv6_send_udp_packet(context->ipv6_context, packet_len);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int dhcpv6_send_request_packet(struct dhcpv6_context *context)
|
|
-{
|
|
- u16_t packet_len;
|
|
-
|
|
- LOG_DEBUG("DHCPV6: Send request");
|
|
- packet_len = dhcpv6_init_packet(context, DHCPV6_REQUEST);
|
|
-
|
|
- context->dhcpv6_state = DHCPV6_STATE_REQ_SENT;
|
|
- ipv6_send_udp_packet(context->ipv6_context, packet_len);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static u16_t dhcpv6_init_packet(struct dhcpv6_context *context, u8_t type)
|
|
-{
|
|
- u16_t pkt_len;
|
|
- struct udp_hdr *udp = context->udp;
|
|
- union dhcpv6_hdr *dhcpv6;
|
|
- struct dhcpv6_option *opt;
|
|
- u16_t len;
|
|
-
|
|
- /* Initialize dest IP with well-known DHCP server address */
|
|
- dhcpv6_init_dhcpv6_server_addr(&context->ipv6->ipv6_dst);
|
|
- /* Initialize dest MAC based on MC dest IP */
|
|
- ipv6_mc_init_dest_mac(context->eth, context->ipv6);
|
|
-
|
|
- /* Initialize UDP header */
|
|
- udp->src_port = HOST_TO_NET16(DHCPV6_CLIENT_PORT);
|
|
- udp->dest_port = HOST_TO_NET16(DHCPV6_SERVER_PORT);
|
|
-
|
|
- /*
|
|
- * DHCPv6 section has the following format per RFC 3315
|
|
- *
|
|
- * 0 1 2 3
|
|
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | msg-type | transaction-id |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | |
|
|
- * . options .
|
|
- * . (variable) .
|
|
- * | |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- */
|
|
- dhcpv6 = (union dhcpv6_hdr *)((u8_t *)udp + sizeof(struct udp_hdr));
|
|
-
|
|
- if (dhcpv6->dhcpv6_type != type)
|
|
- context->dhcpv6_transaction_id++;
|
|
-
|
|
- dhcpv6->dhcpv6_trans_id = HOST_TO_NET16(context->dhcpv6_transaction_id);
|
|
- dhcpv6->dhcpv6_type = type;
|
|
-
|
|
- /* Keep track of length of all DHCP options. */
|
|
- pkt_len = sizeof(union dhcpv6_hdr);
|
|
-
|
|
- if (dhcpv6->dhcpv6_type == DHCPV6_REQUEST) {
|
|
- /* We will send back whatever DHCPv6 sent us */
|
|
- return ((u8_t *)udp - (u8_t *)context->eth +
|
|
- NET_TO_HOST16(udp->length));
|
|
- }
|
|
-
|
|
- opt = (struct dhcpv6_option *)((u8_t *)dhcpv6 +
|
|
- sizeof(union dhcpv6_hdr));
|
|
- /* Add client ID option */
|
|
- opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_CLIENTID);
|
|
- opt->hdr.length = HOST_TO_NET16(sizeof(struct dhcpv6_opt_client_id));
|
|
- opt->type.client_id.duid_type =
|
|
- HOST_TO_NET16(DHCPV6_DUID_TYPE_LINK_LAYER_AND_TIME);
|
|
- opt->type.client_id.hw_type = HOST_TO_NET16(DHCPV6_HW_TYPE_ETHERNET);
|
|
- opt->type.client_id.time = HOST_TO_NET32(clock_time()/1000 -
|
|
- 0x3A4FC880);
|
|
- memcpy((char *)&opt->type.client_id.link_layer_addr,
|
|
- (char *)context->our_mac_addr, sizeof(struct mac_address));
|
|
- pkt_len += sizeof(struct dhcpv6_opt_client_id) +
|
|
- sizeof(struct dhcpv6_opt_hdr);
|
|
- opt = (struct dhcpv6_option *)((u8_t *)opt +
|
|
- sizeof(struct dhcpv6_opt_client_id) +
|
|
- sizeof(struct dhcpv6_opt_hdr));
|
|
-
|
|
- /* Add Vendor Class option if it's configured */
|
|
- len = strlen(context->dhcp_vendor_id);
|
|
- if (len > 0) {
|
|
- opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_VENDOR_CLASS);
|
|
- opt->hdr.length =
|
|
- HOST_TO_NET16(sizeof(struct dhcpv6_vendor_class)
|
|
- + len - 1);
|
|
- opt->type.vendor_class.enterprise_number =
|
|
- HOST_TO_NET32(IANA_ENTERPRISE_NUM_BROADCOM);
|
|
- opt->type.vendor_class.vendor_class_length = HOST_TO_NET16(len);
|
|
- memcpy((char *)&opt->type.vendor_class.
|
|
- vendor_class_data[0],
|
|
- (char *)context->dhcp_vendor_id, len);
|
|
- pkt_len +=
|
|
- sizeof(struct dhcpv6_vendor_class) - 1 + len +
|
|
- sizeof(struct dhcpv6_opt_hdr);
|
|
- opt =
|
|
- (struct dhcpv6_option *)((u8_t *)opt +
|
|
- sizeof(struct dhcpv6_vendor_class) - 1 + len +
|
|
- sizeof(struct dhcpv6_opt_hdr));
|
|
- }
|
|
-
|
|
- /* Add IA_NA option */
|
|
- opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_IA_NA);
|
|
- opt->hdr.length = HOST_TO_NET16(sizeof(struct dhcpv6_opt_id_assoc_na));
|
|
- opt->type.ida_na.iaid = htonl(context->our_mac_addr->last_4_bytes);
|
|
- opt->type.ida_na.t1 = 0;
|
|
- opt->type.ida_na.t2 = 0;
|
|
- pkt_len += sizeof(struct dhcpv6_opt_id_assoc_na) +
|
|
- sizeof(struct dhcpv6_opt_hdr);
|
|
- opt = (struct dhcpv6_option *)((u8_t *)opt +
|
|
- sizeof(struct dhcpv6_opt_id_assoc_na) +
|
|
- sizeof(struct dhcpv6_opt_hdr));
|
|
- /* Add Elapsed Time option */
|
|
- opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_ELAPSED_TIME);
|
|
- opt->hdr.length = HOST_TO_NET16(sizeof(struct dhcpv6_opt_elapse_time));
|
|
- opt->type.elapsed_time.time = HOST_TO_NET16(context->seconds);
|
|
- pkt_len += sizeof(struct dhcpv6_opt_elapse_time) +
|
|
- sizeof(struct dhcpv6_opt_hdr);
|
|
-
|
|
- /* Add Option Request List */
|
|
- opt = (struct dhcpv6_option *)((u8_t *)opt +
|
|
- sizeof(struct dhcpv6_opt_elapse_time) +
|
|
- sizeof(struct dhcpv6_opt_hdr));
|
|
- opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_ORO);
|
|
- opt->hdr.length = HOST_TO_NET16(3 *
|
|
- sizeof(struct dhcpv6_opt_request_list));
|
|
- opt->type.list.request_code[0] = HOST_TO_NET16(DHCPV6_OPT_VENDOR_CLASS);
|
|
- opt->type.list.request_code[1] = HOST_TO_NET16(DHCPV6_OPT_VENDOR_OPTS);
|
|
- opt->type.list.request_code[2] = HOST_TO_NET16(DHCPV6_OPT_DNS_SERVERS);
|
|
- pkt_len += 3 * sizeof(struct dhcpv6_opt_request_list) +
|
|
- sizeof(struct dhcpv6_opt_hdr);
|
|
-
|
|
- udp->length = HOST_TO_NET16(sizeof(struct udp_hdr) + pkt_len);
|
|
-
|
|
- pkt_len +=
|
|
- ((u8_t *)udp - (u8_t *)context->eth) + sizeof(struct udp_hdr);
|
|
-
|
|
- return pkt_len;
|
|
-}
|
|
-
|
|
-static void dhcpv6_init_dhcpv6_server_addr(struct ipv6_addr *addr)
|
|
-{
|
|
- /* Well-known DHCPv6 server address is ff02::1:2 */
|
|
- memset((char *)addr, 0, sizeof(struct ipv6_addr));
|
|
- addr->addr8[0] = 0xff;
|
|
- addr->addr8[1] = 0x02;
|
|
- addr->addr8[13] = 0x01;
|
|
- addr->addr8[15] = 0x02;
|
|
-}
|
|
-
|
|
-void ipv6_udp_handle_dhcp(struct dhcpv6_context *context)
|
|
-{
|
|
- union dhcpv6_hdr *dhcpv6;
|
|
- u16_t dhcpv6_len;
|
|
-
|
|
- if (context->dhcpv6_done == TRUE)
|
|
- return;
|
|
-
|
|
- dhcpv6 = (union dhcpv6_hdr *)((u8_t *)context->udp +
|
|
- sizeof(struct udp_hdr));
|
|
-
|
|
- if (dhcpv6->dhcpv6_trans_id !=
|
|
- HOST_TO_NET16(context->dhcpv6_transaction_id)) {
|
|
- LOG_ERR("DHCPv6 transaction-id error, sent %x, received %x",
|
|
- HOST_TO_NET16(context->dhcpv6_transaction_id),
|
|
- dhcpv6->dhcpv6_trans_id);
|
|
- return;
|
|
- }
|
|
-
|
|
- dhcpv6_len =
|
|
- NET_TO_HOST16(context->udp->length) - sizeof(struct udp_hdr);
|
|
-
|
|
- switch (dhcpv6->dhcpv6_type) {
|
|
- case DHCPV6_ADVERTISE:
|
|
- dhcpv6_handle_advertise(context, dhcpv6_len);
|
|
- break;
|
|
-
|
|
- case DHCPV6_REPLY:
|
|
- dhcpv6_handle_reply(context, dhcpv6_len);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static void dhcpv6_handle_advertise(struct dhcpv6_context *context,
|
|
- u16_t dhcpv6_len)
|
|
-{
|
|
- union dhcpv6_hdr *dhcpv6 =
|
|
- (union dhcpv6_hdr *)((u8_t *)context->udp +
|
|
- sizeof(struct udp_hdr));
|
|
- struct dhcpv6_opt_hdr *opt;
|
|
- u16_t type;
|
|
- int i;
|
|
- int opt_len;
|
|
- u8_t *vendor_id = NULL;
|
|
- u16_t vendor_id_len = 0;
|
|
- u8_t *vendor_opt_data = NULL;
|
|
- int vendor_opt_len = 0;
|
|
- int addr_cnt = 0;
|
|
-
|
|
- /* We only handle DHCPv6 advertise if we recently sent DHCPv6 solicit */
|
|
- if (context->dhcpv6_state != DHCPV6_STATE_SOLICIT_SENT)
|
|
- return;
|
|
-
|
|
- LOG_DEBUG("DHCPV6: handle advertise");
|
|
- context->dhcpv6_state = DHCPV6_STATE_ADV_RCVD;
|
|
-
|
|
- i = 0;
|
|
- while (i < (dhcpv6_len - sizeof(union dhcpv6_hdr))) {
|
|
- opt = (struct dhcpv6_opt_hdr *)((u8_t *)dhcpv6 +
|
|
- sizeof(union dhcpv6_hdr) + i);
|
|
- opt_len = NET_TO_HOST16(opt->length);
|
|
-
|
|
- type = NET_TO_HOST16(opt->type);
|
|
-
|
|
- /* We only care about some of the options */
|
|
- switch (type) {
|
|
- case DHCPV6_OPT_IA_NA:
|
|
- if (context->
|
|
- dhcpv6_task & DHCPV6_TASK_GET_IP_ADDRESS) {
|
|
- addr_cnt +=
|
|
- dhcpv6_process_opt_ia_na(context, opt);
|
|
- }
|
|
- break;
|
|
-
|
|
- case DHCPV6_OPT_VENDOR_CLASS:
|
|
- vendor_id_len =
|
|
- NET_TO_HOST16(((struct dhcpv6_option *)opt)->type.
|
|
- vendor_class.vendor_class_length);
|
|
- vendor_id =
|
|
- &((struct dhcpv6_option *)opt)->type.vendor_class.
|
|
- vendor_class_data[0];
|
|
- break;
|
|
-
|
|
- case DHCPV6_OPT_VENDOR_OPTS:
|
|
- vendor_opt_len = opt_len - 4;
|
|
- vendor_opt_data =
|
|
- &((struct dhcpv6_option *)opt)->type.vendor_opts.
|
|
- vendor_opt_data[0];
|
|
- break;
|
|
-
|
|
- case DHCPV6_OPT_DNS_SERVERS:
|
|
- if (context->dhcpv6_task & DHCPV6_TASK_GET_OTHER_PARAMS)
|
|
- dhcpv6_process_opt_dns_servers(context, opt);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- i += NET_TO_HOST16(opt->length) + sizeof(struct dhcpv6_opt_hdr);
|
|
- }
|
|
-
|
|
- if (context->dhcpv6_task & DHCPV6_TASK_GET_OTHER_PARAMS) {
|
|
- if ((vendor_id_len > 0) &&
|
|
- (strncmp((char *)vendor_id,
|
|
- (char *)context->dhcp_vendor_id,
|
|
- vendor_id_len) == 0)) {
|
|
- dhcpv6_parse_vendor_option(context,
|
|
- vendor_opt_data,
|
|
- vendor_opt_len);
|
|
- context->dhcpv6_done = TRUE;
|
|
- }
|
|
- }
|
|
-
|
|
- if (context->dhcpv6_task & DHCPV6_TASK_GET_IP_ADDRESS) {
|
|
- if (addr_cnt > 0) {
|
|
- /*
|
|
- * If we need to acquire IP address from the server,
|
|
- * we need to send Request to server to confirm.
|
|
- */
|
|
- dhcpv6_send_request_packet(context);
|
|
- context->dhcpv6_done = TRUE;
|
|
- }
|
|
- }
|
|
-
|
|
- if (context->dhcpv6_done) {
|
|
- /* Keep track of IPv6 address of DHCHv6 server */
|
|
- memcpy((char *)&context->dhcp_server,
|
|
- (char *)&context->ipv6->ipv6_src,
|
|
- sizeof(struct ipv6_addr));
|
|
- }
|
|
-}
|
|
-
|
|
-static int dhcpv6_process_opt_ia_na(struct dhcpv6_context *context,
|
|
- struct dhcpv6_opt_hdr *opt_hdr)
|
|
-{
|
|
- int i;
|
|
- int opt_len;
|
|
- struct dhcpv6_option *opt;
|
|
- int len;
|
|
- int addr_cnt;
|
|
- opt_len = NET_TO_HOST16(opt_hdr->length) -
|
|
- sizeof(struct dhcpv6_opt_id_assoc_na);
|
|
-
|
|
- i = 0;
|
|
- addr_cnt = 0;
|
|
- while (i < opt_len) {
|
|
- opt =
|
|
- (struct dhcpv6_option *)((u8_t *)opt_hdr +
|
|
- sizeof(struct dhcpv6_opt_hdr) +
|
|
- sizeof(struct dhcpv6_opt_id_assoc_na) + i);
|
|
-
|
|
- len = NET_TO_HOST16(opt->hdr.length);
|
|
- switch (NET_TO_HOST16(opt->hdr.type)) {
|
|
- case DHCPV6_OPT_IAADDR:
|
|
- if (len >
|
|
- (sizeof(struct dhcpv6_opt_hdr) +
|
|
- sizeof(struct dhcpv6_opt_iaa_addr))) {
|
|
- struct dhcpv6_option *in_opt;
|
|
-
|
|
- in_opt = (struct dhcpv6_option *)((u8_t *)opt +
|
|
- sizeof(struct dhcpv6_opt_hdr) +
|
|
- sizeof(struct dhcpv6_opt_iaa_addr));
|
|
- if (in_opt->hdr.type ==
|
|
- HOST_TO_NET16(DHCPV6_OPT_STATUS_CODE)) {
|
|
- /* This entry has error! */
|
|
- if (in_opt->type.sts.status != 0)
|
|
- break;
|
|
- }
|
|
- }
|
|
- LOG_INFO("DHCPv6: Got IP Addr");
|
|
- /* Status is OK, let's add this addr to our address
|
|
- list */
|
|
- ipv6_add_prefix_entry(context->ipv6_context,
|
|
- &opt->type.iaa_addr.addr, 64);
|
|
-
|
|
- /* Add multicast address for this address */
|
|
- ipv6_add_solit_node_address(context->
|
|
- ipv6_context,
|
|
- &opt->type.iaa_addr.addr);
|
|
- addr_cnt++;
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- i += len + sizeof(struct dhcpv6_opt_hdr);
|
|
- }
|
|
-
|
|
- return addr_cnt;
|
|
-}
|
|
-
|
|
-static void dhcpv6_process_opt_dns_servers(struct dhcpv6_context *context,
|
|
- struct dhcpv6_opt_hdr *opt_hdr)
|
|
-{
|
|
- int opt_len;
|
|
-
|
|
- opt_len = NET_TO_HOST16(opt_hdr->length);
|
|
-
|
|
- if (opt_len >= sizeof(struct ipv6_addr))
|
|
- memcpy((char *)&context->primary_dns_server,
|
|
- (char *)&((struct dhcpv6_option *)opt_hdr)->type.dns.
|
|
- primary_addr, sizeof(struct ipv6_addr));
|
|
-
|
|
- if (opt_len >= 2 * sizeof(struct ipv6_addr))
|
|
- memcpy((char *)&context->secondary_dns_server,
|
|
- (char *)&((struct dhcpv6_option *)opt_hdr)->type.dns.
|
|
- secondary_addr, sizeof(struct ipv6_addr));
|
|
-}
|
|
-
|
|
-static void dhcpv6_handle_reply(struct dhcpv6_context *context,
|
|
- u16_t dhcpv6_len)
|
|
-{
|
|
- if (context->dhcpv6_state != DHCPV6_STATE_REQ_SENT)
|
|
- return;
|
|
-
|
|
- context->dhcpv6_done = TRUE;
|
|
-}
|
|
-
|
|
-static void dhcpv6_parse_vendor_option(struct dhcpv6_context *context,
|
|
- u8_t *option, int len)
|
|
-{
|
|
- struct dhcpv6_option *opt;
|
|
- u16_t type;
|
|
- int opt_len;
|
|
- int data_len;
|
|
- int i;
|
|
- u8_t *data;
|
|
-
|
|
- for (i = 0; i < len; i += opt_len + sizeof(struct dhcpv6_opt_hdr)) {
|
|
- opt = (struct dhcpv6_option *)((u8_t *)option + i);
|
|
- type = HOST_TO_NET16(opt->hdr.type);
|
|
- opt_len = HOST_TO_NET16(opt->hdr.length);
|
|
- data = &opt->type.data[0];
|
|
- data_len = strlen((char *)data);
|
|
-
|
|
- switch (type) {
|
|
- case 201:
|
|
- /* iSCSI target 1 */
|
|
- break;
|
|
-
|
|
- case 202:
|
|
- /* iSCSI target 2 */
|
|
- break;
|
|
-
|
|
- case 203:
|
|
- if (data_len > ISCSI_MAX_ISCSI_NAME_LENGTH)
|
|
- data_len = ISCSI_MAX_ISCSI_NAME_LENGTH;
|
|
- data[data_len] = '\0';
|
|
- strcpy(context->initiatorName, (char *)data);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
- }
|
|
-}
|
|
diff --git a/iscsiuio/src/apps/dhcpc/dhcpv6.h b/iscsiuio/src/apps/dhcpc/dhcpv6.h
|
|
deleted file mode 100644
|
|
index d4ec4b9..0000000
|
|
--- a/iscsiuio/src/apps/dhcpc/dhcpv6.h
|
|
+++ /dev/null
|
|
@@ -1,253 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai <eddie.wai@broadcom.com>
|
|
- * Based on code from Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * dhcpv6.h - DHCPv6 engine header
|
|
- *
|
|
- */
|
|
-#ifndef __IDHCPV6_H__
|
|
-#define __IDHCPV6_H__
|
|
-
|
|
-#include "ipv6_ndpc.h"
|
|
-#include "ipv6.h"
|
|
-
|
|
-#define ISCSI_MAX_ISCSI_NAME_LENGTH 128
|
|
-/* DHCPv6 Message types. */
|
|
-#define DHCPV6_SOLICIT 1
|
|
-#define DHCPV6_ADVERTISE 2
|
|
-#define DHCPV6_REQUEST 3
|
|
-#define DHCPV6_CONFIRM 4
|
|
-#define DHCPV6_RENEW 5
|
|
-#define DHCPV6_REBIND 6
|
|
-#define DHCPV6_REPLY 7
|
|
-#define DHCPV6_RELEASE 8
|
|
-#define DHCPV6_DECLINE 9
|
|
-#define DHCPV6_RECONFIGURE 10
|
|
-#define DHCPV6_INFO_REQUEST 11
|
|
-#define DHCPV6_RELAY_FORW 12
|
|
-#define DHCPV6_RELAY_REPL 13
|
|
-
|
|
-/* Option codes. */
|
|
-#define DHCPV6_OPT_CLIENTID 1 /* Client ID option - built by stack */
|
|
-#define DHCPV6_OPT_SERVERID 2 /* Server ID option - built by stack */
|
|
-#define DHCPV6_OPT_IA_NA 3 /* IA_NA option - built by user */
|
|
-#define DHCPV6_OPT_IA_TA 4 /* IA_TA option - not supported */
|
|
-#define DHCPV6_OPT_IAADDR 5 /* IA_ADDR option - built by user */
|
|
-#define DHCPV6_OPT_ORO 6 /* Option Request Option - built by
|
|
- stack */
|
|
-#define DHCPV6_OPT_PREFERENCE 7 /* Preference option - built by server
|
|
- */
|
|
-#define DHCPV6_OPT_ELAPSED_TIME 8 /* Elapsed Time option - built by stack
|
|
- */
|
|
-#define DHCPV6_OPT_RELAY_MSG 9 /* Relay Message option - not supported
|
|
- */
|
|
-#define DHCPV6_OPT_AUTH 11 /* Authentication option - built by
|
|
- stack */
|
|
-#define DHCPV6_OPT_UNICAST 12 /* Server Unicast option - built by
|
|
- server */
|
|
-#define DHCPV6_OPT_STATUS_CODE 13 /* Status Code option - built by stack
|
|
- */
|
|
-#define DHCPV6_OPT_RAPID_COMMIT 14 /* Rapid Commit option - built by user
|
|
- */
|
|
-#define DHCPV6_OPT_USER_CLASS 15 /* User Class option - built by user */
|
|
-#define DHCPV6_OPT_VENDOR_CLASS 16 /* Vendor Class option - built by user
|
|
- */
|
|
-#define DHCPV6_OPT_VENDOR_OPTS 17 /* Vendor-Specific Information option -
|
|
- build by user */
|
|
-#define DHCPV6_OPT_INTERFACE_ID 18 /* Interface ID option - not supported
|
|
- */
|
|
-#define DHCPV6_OPT_RECONF_MSG 19 /* Reconfigure Message option - built
|
|
- by server */
|
|
-#define DHCPV6_OPT_RECONF_ACCEPT 20 /* Reconfigure Accept option - built by
|
|
- user */
|
|
-#define DHCPV6_OPT_SIP_SERVER_D 21 /* NOT SUPPORTED - included for
|
|
- completeness only */
|
|
-#define DHCPV6_OPT_SIP_SERVER_A 22 /* NOT SUPPORTED - included for
|
|
- completeness only */
|
|
-#define DHCPV6_OPT_DNS_SERVERS 23 /* DNS Recursive Name Server option -
|
|
- built by server */
|
|
-#define DHCPV6_OPT_DOMAIN_LIST 24 /* Domain Search List option - not
|
|
- supported */
|
|
-#define DHCPV6_MAX_OPT_CODES 25 /* This will be the count + 1 since
|
|
- the parsing array starts
|
|
- at [1] instead of [0] */
|
|
-
|
|
-/* Authentication protocol types. */
|
|
-#define DHCPV6_DELAYED_AUTH_PROT 2 /* Delayed Authentication protocol. */
|
|
-#define DHCPV6_RECON_KEY_AUTH_PROT 3 /* Reconfigure Key Authentication
|
|
- protocol. */
|
|
-
|
|
-struct dhcpv6_context {
|
|
-#define DHCP_VENDOR_ID_LEN 128
|
|
- char dhcp_vendor_id[DHCP_VENDOR_ID_LEN];
|
|
- struct mac_address *our_mac_addr;
|
|
- u32_t dhcpv6_transaction_id;
|
|
- u16_t seconds;
|
|
- int timeout;
|
|
- int dhcpv6_done;
|
|
-
|
|
-#define DHCPV6_STATE_UNKNOWN 0
|
|
-#define DHCPV6_STATE_SOLICIT_SENT 1
|
|
-#define DHCPV6_STATE_ADV_RCVD 2
|
|
-#define DHCPV6_STATE_REQ_SENT 3
|
|
-#define DHCPV6_STATE_CONFIRM_SENT 4
|
|
- int dhcpv6_state;
|
|
- u16_t dhcpv6_task;
|
|
- struct ipv6_context *ipv6_context;
|
|
- struct eth_hdr *eth;
|
|
- struct ipv6_hdr *ipv6;
|
|
- struct udp_hdr *udp;
|
|
-
|
|
- char initiatorName[ISCSI_MAX_ISCSI_NAME_LENGTH];
|
|
- struct ipv6_addr dhcp_server;
|
|
- struct ipv6_addr primary_dns_server;
|
|
- struct ipv6_addr secondary_dns_server;
|
|
-
|
|
-};
|
|
-
|
|
-union dhcpv6_hdr {
|
|
- struct {
|
|
- u32_t type:8;
|
|
- u32_t trans_id:24;
|
|
- } field;
|
|
-
|
|
- u32_t type_transaction;
|
|
-};
|
|
-
|
|
-#define dhcpv6_type field.type
|
|
-#define dhcpv6_trans_id field.trans_id
|
|
-
|
|
-struct dhcpv6_opt_hdr {
|
|
- u16_t type;
|
|
- u16_t length;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_client_id {
|
|
- u16_t duid_type;
|
|
-#define DHCPV6_DUID_TYPE_LINK_LAYER_AND_TIME 1
|
|
-#define DHCPV6_DUID_TYPE_VENDOR_BASED 2
|
|
-#define DHCPV6_DUID_TYPE_LINK_LAYER 3
|
|
- u16_t hw_type;
|
|
-#define DHCPV6_HW_TYPE_ETHERNET 1
|
|
- u32_t time;
|
|
- struct mac_address link_layer_addr;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_id_assoc_na {
|
|
- u32_t iaid;
|
|
-#define DHCPV6_OPT_IA_NA_IAID 0x306373L
|
|
- u32_t t1;
|
|
- u32_t t2;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_elapse_time {
|
|
- u16_t time;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_iaa_addr {
|
|
- struct ipv6_addr addr;
|
|
- u32_t preferred_lifetime;
|
|
- u32_t valid_lifetime;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_status {
|
|
- u16_t status;
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_request_list {
|
|
- u16_t request_code[1];
|
|
-};
|
|
-
|
|
-struct dhcpv6_opt_dns {
|
|
- struct ipv6_addr primary_addr;
|
|
- struct ipv6_addr secondary_addr;
|
|
-};
|
|
-
|
|
-struct dhcpv6_vendor_class {
|
|
- u32_t enterprise_number;
|
|
- u16_t vendor_class_length;
|
|
- u8_t vendor_class_data[1];
|
|
-};
|
|
-
|
|
-struct dhcpv6_vendor_opts {
|
|
- u32_t enterprise_number;
|
|
- u8_t vendor_opt_data[1];
|
|
-};
|
|
-
|
|
-struct dhcpv6_option {
|
|
- struct dhcpv6_opt_hdr hdr;
|
|
- union {
|
|
- struct dhcpv6_vendor_opts vendor_opts;
|
|
- struct dhcpv6_vendor_class vendor_class;
|
|
- struct dhcpv6_opt_client_id client_id;
|
|
- struct dhcpv6_opt_id_assoc_na ida_na;
|
|
- struct dhcpv6_opt_elapse_time elapsed_time;
|
|
- struct dhcpv6_opt_iaa_addr iaa_addr;
|
|
- struct dhcpv6_opt_status sts;
|
|
- struct dhcpv6_opt_request_list list;
|
|
- struct dhcpv6_opt_dns dns;
|
|
- u8_t data[1];
|
|
- } type;
|
|
-};
|
|
-
|
|
-#define DHCPV6_NUM_OF_RETRY 4
|
|
-
|
|
-#define DHCPV6_ACK_TIMEOUT 2
|
|
-
|
|
-#define IANA_ENTERPRISE_NUM_BROADCOM 0x113d
|
|
-
|
|
-/* QLogic Extended DHCP options used in iSCSI boot */
|
|
-#define DHCPV6_TAG_FIRST_ISCSI_TARGET_NAME 201
|
|
-#define DHCPV6_TAG_SECOND_ISCSI_TARGET_NAME 202
|
|
-#define DHCPV6_TAG_ISCSI_INITIATOR_NAME 203
|
|
-
|
|
-#define MAX_DHCP_RX_OFFERS 4
|
|
-#define MAX_DHCP_OPTION43_LENGTH 1024
|
|
-
|
|
-#define DHCPV6_TASK_GET_IP_ADDRESS 0x1
|
|
-#define DHCPV6_TASK_GET_OTHER_PARAMS 0x2
|
|
-
|
|
-enum {
|
|
- ISCSI_FAILURE,
|
|
- ISCSI_USER_ABORT,
|
|
- ISCSI_SUCCESS
|
|
-};
|
|
-
|
|
-/* Function prototypes */
|
|
-int dhcpv6_do_discovery(struct dhcpv6_context *context);
|
|
-void ipv6_udp_handle_dhcp(struct dhcpv6_context *context);
|
|
-void dhcpv6_init(struct dhcpv6_context *context);
|
|
-
|
|
-#endif /* __IDHCPV6_H__ */
|
|
diff --git a/iscsiuio/src/uip-1.0-changelog.txt b/iscsiuio/src/uip-1.0-changelog.txt
|
|
deleted file mode 100644
|
|
index 800e444..0000000
|
|
--- a/iscsiuio/src/uip-1.0-changelog.txt
|
|
+++ /dev/null
|
|
@@ -1,98 +0,0 @@
|
|
-* A new API: protosockets that are similar to BSD sockets but does not
|
|
- require any underlying multithreading system.
|
|
-
|
|
-* Very rudimentary IPv6 support
|
|
-
|
|
-* New application: DHCP client. Web server rewritten with protosockets.
|
|
-
|
|
-* Removed uIP zero-copy functionality in order to simplify uIP device
|
|
- driver coding: outbound packets are now *always* stored in full in
|
|
- the uip_buf buffer.
|
|
-
|
|
-* Checksum computation is now part of uip.c, but it still is possible
|
|
- to implement them in assembly code by specifying a configuration
|
|
- option. Checksum code now runs on architectures with 2-byte alignment.
|
|
-
|
|
-* Added TCP persistent timer.
|
|
-
|
|
-* Made all IP address representations use the new uip_ipaddr_ip
|
|
- datatype for clarity.
|
|
-
|
|
-* Updated window behavior so that sending to a host with a small open
|
|
- window works better now.
|
|
-
|
|
-* UDP API change: uip_udp_new() now takes port numbers in network byte
|
|
- order like TCP functions.
|
|
-
|
|
-* Allow reception of packets when no IP address is configured to make
|
|
- DHCP work.
|
|
-
|
|
-* Moved Ethernet address into main uIP module from ARP module.
|
|
-
|
|
-* Made constants explicit #defines and moved them out of the code
|
|
- (header sizes, TCP options, TCP header length field).
|
|
-
|
|
-* If uip_len is less than that reported by the IP header, the packet
|
|
- is discarded. If uip_len is greater than the length reported by the
|
|
- IP header, uip_len is adjusted.
|
|
-
|
|
-* Moved header size definitions into header file.
|
|
-
|
|
-* Added uIP call for polling an application without triggering any
|
|
- timer events. Removed redundant assignments of uip_len and uip_slen.
|
|
-
|
|
-* Removed compiler warning about icmp_input label being defined when
|
|
- UIP_PINGADDRCONF was not used.
|
|
-
|
|
-* Added UIP_APPDATA_SIZE macro that holds the available buffer size
|
|
- for user data.
|
|
-
|
|
-* Added uip_udp_bind() call.
|
|
-
|
|
-* Moved checksum code into main uIP module.
|
|
-
|
|
-* Switched the TCP, UDP and IP header structures to be structs rather
|
|
- than typedefs.
|
|
-
|
|
-* Prefixed TCP state names with UIP_ to avoid name space
|
|
- contamination.
|
|
-
|
|
-* Changed declarations of uip_appdatap and friends to void * to avoid
|
|
- explicit typecasts.
|
|
-
|
|
-* Bugfixes
|
|
-
|
|
- o TCP: Fixed bug with high byte of peer window size.
|
|
-
|
|
- o TCP: Fixed bug that in some cases prevented concurrent reception and
|
|
- transmission of TCP data.
|
|
-
|
|
- o TCP: uip_connect() didn't correctly calculate age of TIME_WAIT
|
|
- connections.
|
|
-
|
|
- o TCP: Array index for uip_conns[] array was out of bounds in
|
|
- comparison. Comparison changed to make index within bounds.
|
|
-
|
|
- o TCP: if the remote host crashes and tries to reestablish an old
|
|
- connection, uIP should respond with an ACK with the correct
|
|
- sequence and acknowledgment numbers, to which the remote host
|
|
- should respond with an ACK. uIP did not respond with the correct
|
|
- ACK.
|
|
-
|
|
- o TCP: Fixed check for SYNACK segment: now checks only relevant TCP
|
|
- control flags and discards flags reserved for future expansion.
|
|
-
|
|
- o TCP: Fixed bug where uIP did not inform application that a connection
|
|
- had been aborted during an active open.
|
|
-
|
|
- o TCP: FIN segment was accepted even though application had stopped
|
|
- incoming data with uip_stop().
|
|
-
|
|
- o TCP: A FINACK segment would not always correctly acknowledge data.
|
|
-
|
|
- o UDP: checksums are now calculated after all fields have been
|
|
- filled in.
|
|
-
|
|
- o UDP: network byte order on lastport in uip_udp_new().
|
|
-
|
|
- o IP: memset() bugs in IP fragment reassembly code fixed.
|
|
diff --git a/iscsiuio/src/uip/Makefile.am b/iscsiuio/src/uip/Makefile.am
|
|
deleted file mode 100644
|
|
index 16170d7..0000000
|
|
--- a/iscsiuio/src/uip/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,18 +0,0 @@
|
|
-AM_CFLAGS = -I${top_srcdir}/src/unix \
|
|
- -I${top_srcdir}/src/apps/dhcpc \
|
|
- -I${top_srcdir}/src/apps/brcm-iscsi \
|
|
- -I${top_srcdir}/../include \
|
|
- -I${top_srcdir}/../usr
|
|
-
|
|
-noinst_LIBRARIES = lib_iscsi_uip.a
|
|
-
|
|
-lib_iscsi_uip_a_SOURCES = uip.c \
|
|
- uip_arp.c \
|
|
- psock.c \
|
|
- timer.c \
|
|
- uip-neighbor.c \
|
|
- uip_eth.c \
|
|
- ipv6_ndpc.c \
|
|
- ipv6.c
|
|
-
|
|
-lib_iscsi_uip_a_CFLAGS = -DBYTE_ORDER=@ENDIAN@ $(AM_CFLAGS)
|
|
diff --git a/iscsiuio/src/uip/Makefile.include b/iscsiuio/src/uip/Makefile.include
|
|
deleted file mode 100644
|
|
index aa3ac63..0000000
|
|
--- a/iscsiuio/src/uip/Makefile.include
|
|
+++ /dev/null
|
|
@@ -1,47 +0,0 @@
|
|
-
|
|
-
|
|
-ifdef APPS
|
|
- APPDIRS = $(foreach APP, $(APPS), ../apps/$(APP))
|
|
- -include $(foreach APP, $(APPS), ../apps/$(APP)/Makefile.$(APP))
|
|
- CFLAGS += $(addprefix -I../apps/,$(APPS))
|
|
-endif
|
|
-
|
|
-ifndef CCDEP
|
|
- CCDEP = $(CC)
|
|
-endif
|
|
-ifndef CCDEPCFLAGS
|
|
- CCDEPCFLAGS = $(CFLAGS)
|
|
-endif
|
|
-ifndef OBJECTDIR
|
|
- OBJECTDIR = obj
|
|
-endif
|
|
-
|
|
-ifeq (${wildcard $(OBJECTDIR)},)
|
|
- DUMMY := ${shell mkdir $(OBJECTDIR)}
|
|
-endif
|
|
-
|
|
-
|
|
-vpath %.c . ../uip ../lib $(APPDIRS)
|
|
-
|
|
-$(OBJECTDIR)/%.o: %.c
|
|
- $(CC) $(CFLAGS) -c $< -o $@
|
|
-
|
|
-$(OBJECTDIR)/%.d: %.c
|
|
- @set -e; rm -f $@; \
|
|
- $(CCDEP) -MM $(CCDEPCFLAGS) $< > $@.$$$$; \
|
|
- sed 's,\($*\)\.o[ :]*,$(OBJECTDIR)/\1.o $@ : ,g' < $@.$$$$ > $@; \
|
|
- rm -f $@.$$$$
|
|
-
|
|
-UIP_SOURCES=uip.c uip_arp.c uiplib.c psock.c timer.c uip-neighbor.c uip_eth.c ipv6_ndp.c ipv6.c
|
|
-
|
|
-
|
|
-ifneq ($(MAKECMDGOALS),clean)
|
|
--include $(addprefix $(OBJECTDIR)/,$(UIP_SOURCES:.c=.d) \
|
|
- $(APP_SOURCES:.c=.d))
|
|
-endif
|
|
-
|
|
-libuip.a: ${addprefix $(OBJECTDIR)/, $(UIP_SOURCES:.c=.o)}
|
|
- $(AR) rc $@ $^
|
|
-
|
|
-libapps.a: ${addprefix $(OBJECTDIR)/, $(APP_SOURCES:.c=.o)}
|
|
- $(AR) rc $@ $^
|
|
diff --git a/iscsiuio/src/uip/clock.h b/iscsiuio/src/uip/clock.h
|
|
deleted file mode 100644
|
|
index d79326b..0000000
|
|
--- a/iscsiuio/src/uip/clock.h
|
|
+++ /dev/null
|
|
@@ -1,87 +0,0 @@
|
|
-/**
|
|
- * \defgroup clock Clock interface
|
|
- *
|
|
- * The clock interface is the interface between the \ref timer "timer library"
|
|
- * and the platform specific clock functionality. The clock
|
|
- * interface must be implemented for each platform that uses the \ref
|
|
- * timer "timer library".
|
|
- *
|
|
- * The clock interface does only one this: it measures time. The clock
|
|
- * interface provides a macro, CLOCK_SECOND, which corresponds to one
|
|
- * second of system time.
|
|
- *
|
|
- * \sa \ref timer "Timer library"
|
|
- *
|
|
- * @{
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2004, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-#ifndef __CLOCK_H__
|
|
-#define __CLOCK_H__
|
|
-
|
|
-#include "clock-arch.h"
|
|
-
|
|
-/**
|
|
- * Initialize the clock library.
|
|
- *
|
|
- * This function initializes the clock library and should be called
|
|
- * from the main() function of the system.
|
|
- *
|
|
- */
|
|
-void clock_init(void);
|
|
-
|
|
-/**
|
|
- * Get the current clock time.
|
|
- *
|
|
- * This function returns the current system clock time.
|
|
- *
|
|
- * \return The current clock time, measured in system ticks.
|
|
- */
|
|
-clock_time_t clock_time(void);
|
|
-
|
|
-/**
|
|
- * A second, measured in system clock time.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef CLOCK_CONF_SECOND
|
|
-#define CLOCK_SECOND CLOCK_CONF_SECOND
|
|
-#else
|
|
-#define CLOCK_SECOND (clock_time_t)32
|
|
-#endif
|
|
-
|
|
-#endif /* __CLOCK_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/debug.h b/iscsiuio/src/uip/debug.h
|
|
deleted file mode 100644
|
|
index a58fa7a..0000000
|
|
--- a/iscsiuio/src/uip/debug.h
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-#ifndef __DEBUG_H__
|
|
-#define __DEBUG_H__
|
|
-
|
|
-#ifdef DEBUG
|
|
-#define UIP_DEBUG(args...) \
|
|
- do { \
|
|
- fprintf(stdout, args); \
|
|
- fflush(stdout); \
|
|
- } while (0);
|
|
-#else
|
|
-#endif
|
|
-
|
|
-#endif
|
|
diff --git a/iscsiuio/src/uip/icmpv6.h b/iscsiuio/src/uip/icmpv6.h
|
|
deleted file mode 100644
|
|
index cbf9aa8..0000000
|
|
--- a/iscsiuio/src/uip/icmpv6.h
|
|
+++ /dev/null
|
|
@@ -1,302 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- * Based on Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * icmpv6.h - This file contains macro definitions pertaining to ICMPv6
|
|
- *
|
|
- * RFC 2463 : ICMPv6 Specification
|
|
- * RFC 2461 : Neighbor Discovery for IPv6
|
|
- *
|
|
- */
|
|
-#ifndef __ICMPV6_H__
|
|
-#define __ICMPV6_H__
|
|
-
|
|
-/* Base ICMP Header sizes */
|
|
-#define IPV6_RTR_SOL_HDR_SIZE 8
|
|
-#define IPV6_RTR_ADV_HDR_SIZE 16
|
|
-#define IPV6_NEIGH_SOL_HDR_SIZE 24
|
|
-#define IPV6_NEIGH_ADV_HDR_SIZE 24
|
|
-#define IPV6_LINK_LAYER_OPT_SIZE 2
|
|
-#define IPV6_LINK_LAYER_OPT_LENGTH 8
|
|
-#define IPV6_MTU_OPT_SIZE 8
|
|
-#define IPV6_PREFIX_OPT_SIZE 32
|
|
-#define IPV6_ECHO_REQUEST_HDR_SIZE 8
|
|
-#define IPV6_ECHO_REPLY_HDR_SIZE 8
|
|
-#define IPV6_REDIRECT_SIZE 40
|
|
-#define IPV6_DHAAD_REQ_HDR_SIZE 8
|
|
-#define IPV6_DHAAD_REPLY_HDR_SIZE 8
|
|
-#define IPV6_PRFXSOL_HDR_SIZE 8
|
|
-#define IPV6_PRFXADV_HDR_SIZE 8
|
|
-#define IPV6_RTR_ADV_INT_OPT_SIZE 8
|
|
-
|
|
-/* ICMP Message Types */
|
|
-/* Error messages are always less than 128 */
|
|
-#define ICMPV6_DST_UNREACH 1 /* Destination Unreachable */
|
|
-#define ICMPV6_PACKET_TOO_BIG 2 /* Packet Too Big */
|
|
-#define ICMPV6_TIME_EXCEEDED 3 /* Time Exceeded */
|
|
-#define ICMPV6_PARAM_PROB 4 /* Parameter Problem */
|
|
-
|
|
-#define ICMPV6_RTR_SOL 133 /* Router Solicitation */
|
|
-#define ICMPV6_RTR_ADV 134 /* Router Advertisement */
|
|
-#define ICMPV6_NEIGH_SOL 135 /* Neighbor Solicitation */
|
|
-#define ICMPV6_NEIGH_ADV 136 /* Neighbor Advertisement */
|
|
-#define ICMPV6_REDIRECT 137 /* Redirect */
|
|
-#define ICMPV6_ECHO_REQUEST 128 /* Echo Request */
|
|
-#define ICMPV6_ECHO_REPLY 129 /* Echo Reply */
|
|
-#define ICMPV6_WRUREQUEST 139 /* Who Are You Request */
|
|
-#define ICMPV6_WRUREPLY 140 /* Who Are You Reply */
|
|
-#define ICMPV6_ROUTER_RENUMBERING 138 /* Router Renumbering */
|
|
-#define ICMPV6_HA_ADDR_DISC_REQ 144 /* Dynamic Home Agent Address
|
|
- Discovery Request */
|
|
-#define ICMPV6_HA_ADDR_DISC_REPLY 145 /* Dynamic Home Agent Address
|
|
- Discovery Reply */
|
|
-#define ICMPV6_MP_SOLICIT 146 /* Mobile Prefix Solicitation */
|
|
-#define ICMPV6_MP_ADV 147 /* Mobile Prefix Reply */
|
|
-
|
|
-/* Destination Unreachable Codes */
|
|
-#define ICMPV6_DST_UNREACH_NOROUTE 0
|
|
-#define ICMPV6_DST_UNREACH_ADMIN 1
|
|
-#define ICMPV6_DST_UNREACH_ADDRESS 3
|
|
-#define ICMPV6_DST_UNREACH_PORT 4
|
|
-
|
|
-/* Time Exceeded Codes */
|
|
-#define ICMPV6_TIME_EXCD_HPLMT 0 /* Hop Limit exceeded in transit */
|
|
-#define ICMPV6_TIME_EXCD_REASM 1 /* Fragment reassembly time exceeded */
|
|
-
|
|
-/* Parameter Problem Codes */
|
|
-#define ICMPV6_PARM_PROB_HEADER 0
|
|
-#define ICMPV6_PARM_PROB_NEXT_HDR 1
|
|
-#define ICMPV6_PARM_PROB_OPTION 2
|
|
-
|
|
-/* ICMP Option Types */
|
|
-#define IPV6_ICMP_OPTION_SRC_ADDR 1 /* Source Link-Layer Address */
|
|
-#define IPV6_ICMP_OPTION_TAR_ADDR 2 /* Target Link-Layer Address */
|
|
-#define IPV6_ICMP_OPTION_PREFIX 3 /* Prefix */
|
|
-#define IPV6_ICMP_OPTION_RED_HDR 4 /* Redirect Header */
|
|
-#define IPV6_ICMP_OPTION_MTU 5 /* Link MTU */
|
|
-#define IPV6_ICMP_OPTION_RTR_ADV_INT 7 /* Rtr Advertisement Interval */
|
|
-
|
|
-/* ICMP Offsets */
|
|
-#define IPV6_ICMP_TYPE_OFFSET 0
|
|
-#define IPV6_ICMP_CODE_OFFSET 1
|
|
-#define IPV6_ICMP_CKSUM_OFFSET 2
|
|
-#define IPV6_ICMP_RESERVED_OFFSET 4
|
|
-#define IPV6_ICMP_DATA_OFFSET 8
|
|
-
|
|
-/* ICMP Router Solicitation Offsets */
|
|
-#define IPV6_ICMP_RTR_SOL_RES_OFFSET 4
|
|
-#define IPV6_ICMP_RTR_SOL_OPTIONS_OFFSET 8
|
|
-
|
|
-/* ICMP Router Advertisement Offsets */
|
|
-#define IPV6_ICMP_RTR_ADV_CURHOPLMT_OFFSET 4
|
|
-#define IPV6_ICMP_RTR_ADV_MGDANDCFG_BIT_OFFSET 5
|
|
-#define IPV6_ICMP_RTR_ADV_RTR_LIFETIME_OFFSET 6
|
|
-#define IPV6_ICMP_RTR_ADV_RCHBL_TIME_OFFSET 8
|
|
-#define IPV6_ICMP_RTR_ADV_RTRNS_TMR_OFFSET 12
|
|
-#define IPV6_ICMP_RTR_ADV_OPTIONS_OFFSET 16
|
|
-
|
|
-/* ICMP Neighbor Solicitation Offsets */
|
|
-#define IPV6_ICMP_NEIGH_SOL_RES_OFFSET 4
|
|
-#define IPV6_ICMP_NEIGH_SOL_TRGT_ADDRS_OFFSET 8
|
|
-#define IPV6_ICMP_NEIGH_SOL_OPTIONS_OFFSET 24
|
|
-
|
|
-/* ICMP Neighbor Advertisement Offsets */
|
|
-#define IPV6_ICMP_NEIGH_ADV_FLAG_OFFSET 4
|
|
-#define IPV6_ICMP_NEIGH_ADV_TRGT_ADDRS_OFFSET 8
|
|
-#define IPV6_ICMP_NEIGH_ADV_OPTIONS_OFFSET 24
|
|
-
|
|
-/* ICMP Redirect Offsets */
|
|
-#define IPV6_ICMP_REDIRECT_TRGT_ADDRS_OFFSET 8
|
|
-#define IPV6_ICMP_REDIRECT_DEST_ADDRS_OFFSET 24
|
|
-#define IPV6_ICMP_REDIRECT_OPTIONS_OFFSET 40
|
|
-
|
|
-/* ICMP Option Offsets */
|
|
-#define IPV6_ICMP_OPTION_TYPE_OFFSET 0
|
|
-#define IPV6_ICMP_OPTION_LENGTH_OFFSET 1
|
|
-
|
|
-/* ICMP Link-Layer Address Option Offsets */
|
|
-#define IPV6_ICMP_LL_OPTION_ADDRESS_OFFSET 2
|
|
-
|
|
-/* ICMP Prefix Option Offsets */
|
|
-#define IPV6_ICMP_PREFIX_PRE_LENGTH_OFFSET 2
|
|
-#define IPV6_ICMP_PREFIX_FLAG_OFFSET 3
|
|
-#define IPV6_ICMP_PREFIX_VALID_LIFETIME_OFFSET 4
|
|
-#define IPV6_ICMP_PREFIX_PREF_LIFETIME_OFFSET 8
|
|
-#define IPV6_ICMP_PREFIX_RES2_OFFSET 12
|
|
-#define IPV6_ICMP_PREFIX_PREFIX_OFFSET 16
|
|
-
|
|
-/* ICMP Redirected Header Option Offsets */
|
|
-#define IPV6_ICMP_RED_OPTION_TYPE_OFFSET 0
|
|
-#define IPV6_ICMP_RED_OPTION_LEN_OFFSET 1
|
|
-#define IPV6_ICMP_RED_OPTION_RES1_OFFSET 2
|
|
-#define IPV6_ICMP_RED_OPTION_RES2_OFFSET 4
|
|
-#define IPV6_ICMP_RED_OPTION_DATA_OFFSET 8
|
|
-
|
|
-/* ICMP MTU Option Offsets */
|
|
-#define IPV6_ICMP_MTU_RESERVED_OFFSET 2
|
|
-#define IPV6_ICMP_MTU_OFFSET 4
|
|
-
|
|
-/* ICMP Echo Request Offsets */
|
|
-#define IPV6_ICMP_ECHO_ID 4
|
|
-#define IPV6_ICMP_ECHO_SEQ 6
|
|
-#define IPV6_ICMP_ECHO_DATA 8
|
|
-
|
|
-/* ICMP Destination Unreachable Offsets */
|
|
-#define IPV6_DST_UNREACH_UNUSED 4
|
|
-#define IPV6_DST_UNREACH_DATA 8
|
|
-
|
|
-/* ICMP Parameter Problem Offsets */
|
|
-#define IPV6_PARAM_PROB_PTR 4
|
|
-#define IPV6_PARAM_PROT_DATA 8
|
|
-
|
|
-/* ICMP Time Exceeded Offsets */
|
|
-#define IPV6_TIME_EXCEEDED_DATA 8
|
|
-
|
|
-/* ICMP Packet Too Big Offsets */
|
|
-#define IPV6_PKT_TOO_BIG_MTU 4
|
|
-#define IPV6_PKT_TOO_BIG_DATA 8
|
|
-
|
|
-/* Home Agent Address Discovery Request Header Offsets */
|
|
-#define ICMPV6_HA_ADDR_DISC_REQ_ID_OFFSET 4
|
|
-#define ICMPV6_HA_ADDR_DISC_REQ_RSVD_OFFSET 6
|
|
-
|
|
-/* Home Agent Address Discovery Reply Header Offsets */
|
|
-#define ICMPV6_HA_ADDR_DISC_REPLY_ID_OFFSET 4
|
|
-#define ICMPV6_HA_ADDR_DISC_REPLY_RSVD_OFFSET 6
|
|
-#define ICMPV6_HA_ADDR_DISC_REPLY_HA_ADDR_OFFSET 8
|
|
-
|
|
-/* Mobile Prefix Solicitation Header Offsets */
|
|
-#define ICMPV6_MP_SOLICIT_ID_OFFSET 4
|
|
-#define ICMPV6_MP_SOLICIT_RSVD_OFFSET 6
|
|
-
|
|
-/* Mobile Prefix Advertisement Header Offsets */
|
|
-#define ICMPV6_MP_ADV_ID_OFFSET 4
|
|
-#define ICMPV6_MP_ADV_MGDANDCFG_BIT_OFFSET 6
|
|
-#define ICMPV6_MP_ADV_OPT_OFFSET 8
|
|
-
|
|
-/* Advertisement Interval Option Header Offsets */
|
|
-#define ICMPV6_ADV_INT_TYPE_OFFSET 0
|
|
-#define ICMPV6_ADV_INT_LEN_OFFSET 1
|
|
-#define ICMPV6_ADV_INT_RSVD_OFFSET 2
|
|
-#define ICMPV6_ADV_INT_ADV_INT_OFFSET 4
|
|
-
|
|
-#define ICMPV6_HEADER_LEN 4
|
|
-
|
|
-#define IPV6_PREFIX_FLAG_ONLINK 0x80
|
|
-#define IPV6_PREFIX_FLAG_AUTO 0x40
|
|
-#define IPV6_PREFIX_FLAG_ROUTER 0x20
|
|
-
|
|
-#define IPV6_NA_FLAG_ROUTER 0x80
|
|
-#define IPV6_NA_FLAG_SOLICITED 0x40
|
|
-#define IPV6_NA_FLAG_OVERRIDE 0x20
|
|
-
|
|
-/* Router Advertisement Flags */
|
|
-#define IPV6_RA_MANAGED_FLAG 0x80
|
|
-#define IPV6_RA_CONFIG_FLAG 0x40
|
|
-
|
|
-/* Mobile Prefix Advertisement Flags */
|
|
-#define IPV6_PA_MANAGED_FLAG 0x80
|
|
-#define IPV6_PA_CONFIG_FLAG 0x40
|
|
-
|
|
-/* Validation Values */
|
|
-#define ICMPV6_VALID_HOP_LIMIT 255 /* Valid Hop Limit */
|
|
-#define ICMPV6_VALID_CODE 0 /* Valid Code */
|
|
-#define ICMPV6_RTRSOL_MIN_LENGTH 8 /* Minimum valid length for
|
|
- Router Solicitation */
|
|
-#define ICMPV6_RTRADV_MIN_LENGTH 16 /* Minimum valid length for
|
|
- Router Advertisement */
|
|
-#define ICMPV6_NEIGHSOL_MIN_LENGTH 24 /* Minimum valid length for
|
|
- Neighbor Solicitation */
|
|
-#define ICMPV6_NEIGHADV_MIN_LENGTH 24 /* Minimum valid length for
|
|
- Neighbor Advertisement */
|
|
-#define ICMPV6_REDIRECT_MIN_LENGTH 40 /* Minimum valid length for
|
|
- Neighbor Advertisement */
|
|
-
|
|
-/* ICMPV6 Header */
|
|
-struct icmpv6_hdr {
|
|
- u8_t icmpv6_type; /* type field */
|
|
- u8_t icmpv6_code; /* code field */
|
|
- u16_t icmpv6_cksum; /* checksum field */
|
|
- union {
|
|
- u32_t icmpv6_un_data32[1]; /* type-specific field */
|
|
- u16_t icmpv6_un_data16[2]; /* type-specific field */
|
|
- u8_t icmpv6_un_data8[4]; /* type-specific field */
|
|
- } data;
|
|
-};
|
|
-
|
|
-#define icmpv6_data data.icmpv6_un_data32[0]
|
|
-
|
|
-struct icmpv6_opt_hdr {
|
|
- u8_t type;
|
|
- u8_t len;
|
|
-};
|
|
-
|
|
-struct icmpv6_opt_link_addr {
|
|
- struct icmpv6_opt_hdr hdr;
|
|
- u8_t link_addr[6];
|
|
-};
|
|
-
|
|
-struct icmpv6_opt_prefix {
|
|
- struct icmpv6_opt_hdr hdr;
|
|
- u8_t prefix_len;
|
|
- u8_t flags;
|
|
-#define ICMPV6_OPT_PREFIX_FLAG_ON_LINK (1 << 7)
|
|
-#define ICMPV6_OPT_PREFIX_FLAG_BIT_A (1 << 6)
|
|
- u32_t valid_lifetime;
|
|
- u32_t preferred_lifetime;
|
|
- u32_t reserved;
|
|
- struct ipv6_addr prefix;
|
|
-};
|
|
-
|
|
-/* Neighbor Solicitation */
|
|
-struct icmpv6_nd_solicit {
|
|
- struct icmpv6_hdr nd_ns_hdr;
|
|
-};
|
|
-
|
|
-/* Router Advertisement */
|
|
-struct icmpv6_router_advert {
|
|
- struct icmpv6_hdr header;
|
|
- u32_t reachable_time;
|
|
- u32_t retransmit_timer;
|
|
-};
|
|
-
|
|
-#define nd_ra_type header.icmpv6_type
|
|
-#define nd_ra_code header.icmpv6_code
|
|
-#define nd_ra_cksum header.icmpv6_cksum
|
|
-#define nd_ra_curhoplimit header.data.icmpv6_un_data8[0]
|
|
-#define nd_ra_flags_reserved header.data.icmpv6_un_data8[1]
|
|
-#define nd_ra_router_lifetime header.data.icmpv6_un_data16[1]
|
|
-
|
|
-#endif /* __ICMPV6_H__ */
|
|
diff --git a/iscsiuio/src/uip/ipv6.c b/iscsiuio/src/uip/ipv6.c
|
|
deleted file mode 100644
|
|
index 11cb4e9..0000000
|
|
--- a/iscsiuio/src/uip/ipv6.c
|
|
+++ /dev/null
|
|
@@ -1,1306 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- * Based on Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ipv6.c - This file contains simplifed IPv6 processing code.
|
|
- *
|
|
- */
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <arpa/inet.h>
|
|
-#include "logger.h"
|
|
-#include "uip.h"
|
|
-#include "ipv6.h"
|
|
-#include "ipv6_pkt.h"
|
|
-#include "icmpv6.h"
|
|
-#include "uipopt.h"
|
|
-#include "dhcpv6.h"
|
|
-#include "ping.h"
|
|
-
|
|
-static inline int best_match_bufcmp(u8_t *a, u8_t *b, int len)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < len; i++) {
|
|
- if (a[i] != b[i])
|
|
- break;
|
|
- }
|
|
- return i;
|
|
-}
|
|
-
|
|
-/* Local function prototypes */
|
|
-static int ipv6_is_it_our_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-static void ipv6_insert_protocol_chksum(struct ipv6_hdr *ipv6);
|
|
-static void ipv6_update_arp_table(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr,
|
|
- struct mac_address *mac_addr);
|
|
-static void ipv6_icmp_init_link_option(struct ipv6_context *context,
|
|
- struct icmpv6_opt_link_addr *link_opt,
|
|
- u8_t type);
|
|
-static void ipv6_icmp_rx(struct ipv6_context *context);
|
|
-static void ipv6_icmp_handle_nd_adv(struct ipv6_context *context);
|
|
-static void ipv6_icmp_handle_nd_sol(struct ipv6_context *context);
|
|
-static void ipv6_icmp_handle_echo_request(struct ipv6_context *context);
|
|
-static void ipv6_icmp_handle_router_adv(struct ipv6_context *context);
|
|
-static void ipv6_icmp_process_prefix(struct ipv6_context *context,
|
|
- struct icmpv6_opt_prefix *icmp_prefix);
|
|
-static void ipv6_udp_rx(struct ipv6_context *context);
|
|
-
|
|
-int iscsiL2Send(struct ipv6_context *context, int pkt_len)
|
|
-{
|
|
- LOG_DEBUG("IPv6: iscsiL2Send");
|
|
- uip_send(context->ustack,
|
|
- (void *)context->ustack->data_link_layer, pkt_len);
|
|
-
|
|
- return pkt_len;
|
|
-}
|
|
-
|
|
-int iscsiL2AddMcAddr(struct ipv6_context *context,
|
|
- struct mac_address *new_mc_addr)
|
|
-{
|
|
- int i;
|
|
- struct mac_address *mc_addr;
|
|
- const struct mac_address all_zeroes_mc = { { { 0, 0, 0, 0, 0, 0 } } };
|
|
-
|
|
- mc_addr = context->mc_addr;
|
|
- for (i = 0; i < MAX_MCADDR_TABLE; i++, mc_addr++)
|
|
- if (!memcmp((char *)mc_addr,
|
|
- (char *)new_mc_addr, sizeof(struct mac_address)))
|
|
- return TRUE; /* Already in the mc table */
|
|
-
|
|
- mc_addr = context->mc_addr;
|
|
- for (i = 0; i < MAX_MCADDR_TABLE; i++, mc_addr++) {
|
|
- if (!memcmp((char *)mc_addr,
|
|
- (char *)&all_zeroes_mc, sizeof(struct mac_address))) {
|
|
- memcpy((char *)mc_addr,
|
|
- (char *)new_mc_addr, sizeof(struct mac_address));
|
|
- LOG_DEBUG("IPv6: mc_addr added "
|
|
- "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
- *(u8_t *)new_mc_addr,
|
|
- *((u8_t *)new_mc_addr + 1),
|
|
- *((u8_t *)new_mc_addr + 2),
|
|
- *((u8_t *)new_mc_addr + 3),
|
|
- *((u8_t *)new_mc_addr + 4),
|
|
- *((u8_t *)new_mc_addr + 5));
|
|
- return TRUE;
|
|
- }
|
|
- }
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
-int iscsiL2IsOurMcAddr(struct ipv6_context *context,
|
|
- struct mac_address *dest_mac)
|
|
-{
|
|
- int i;
|
|
- struct mac_address *mc_addr;
|
|
-
|
|
- mc_addr = context->mc_addr;
|
|
- for (i = 0; i < MAX_MCADDR_TABLE; i++, mc_addr++)
|
|
- if (!memcmp((char *)mc_addr,
|
|
- (char *)dest_mac->addr, sizeof(struct mac_address)))
|
|
- return TRUE;
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
-void ipv6_init(struct ndpc_state *ndp, int cfg)
|
|
-{
|
|
- int i;
|
|
- struct ipv6_context *context = (struct ipv6_context *)ndp->ipv6_context;
|
|
- struct mac_address *mac_addr = (struct mac_address *)ndp->mac_addr;
|
|
- struct ipv6_arp_entry *ipv6_arp_table;
|
|
- struct ipv6_prefix_entry *ipv6_prefix_table;
|
|
- struct mac_address mc_addr;
|
|
-
|
|
- if (context == NULL) {
|
|
- LOG_ERR("IPV6: INIT ipv6_context is NULL");
|
|
- return;
|
|
- }
|
|
-
|
|
- memset((char *)context, 0, sizeof(struct ipv6_context));
|
|
-
|
|
- /* Associate the nic_iface's ustack to this ipv6_context */
|
|
- context->ustack = ndp->ustack;
|
|
-
|
|
- ipv6_arp_table = &context->ipv6_arp_table[0];
|
|
- ipv6_prefix_table = &context->ipv6_prefix_table[0];
|
|
-
|
|
- memset((char *)ipv6_arp_table, 0, sizeof(*ipv6_arp_table));
|
|
- memset((char *)ipv6_prefix_table, 0, sizeof(*ipv6_prefix_table));
|
|
- memcpy((char *)&context->mac_addr,
|
|
- (char *)mac_addr, sizeof(struct mac_address));
|
|
- /*
|
|
- * Per RFC 2373.
|
|
- * There are two types of local-use unicast addresses defined. These
|
|
- * are Link-Local and Site-Local. The Link-Local is for use on a single
|
|
- * link and the Site-Local is for use in a single site. Link-Local
|
|
- * addresses have the following format:
|
|
- *
|
|
- * | 10 |
|
|
- * | bits | 54 bits | 64 bits |
|
|
- * +----------+-------------------------+----------------------------+
|
|
- * |1111111010| 0 | interface ID |
|
|
- * +----------+-------------------------+----------------------------+
|
|
- */
|
|
- if (context->ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF) {
|
|
- context->link_local_addr.addr8[0] = 0xfe;
|
|
- context->link_local_addr.addr8[1] = 0x80;
|
|
- /* Bit 1 is 1 to indicate universal scope. */
|
|
- context->link_local_addr.addr8[8] = mac_addr->addr[0] | 0x2;
|
|
- context->link_local_addr.addr8[9] = mac_addr->addr[1];
|
|
- context->link_local_addr.addr8[10] = mac_addr->addr[2];
|
|
- context->link_local_addr.addr8[11] = 0xff;
|
|
- context->link_local_addr.addr8[12] = 0xfe;
|
|
- context->link_local_addr.addr8[13] = mac_addr->addr[3];
|
|
- context->link_local_addr.addr8[14] = mac_addr->addr[4];
|
|
- context->link_local_addr.addr8[15] = mac_addr->addr[5];
|
|
-
|
|
- context->link_local_multi.addr8[0] = 0xff;
|
|
- context->link_local_multi.addr8[1] = 0x02;
|
|
- context->link_local_multi.addr8[11] = 0x01;
|
|
- context->link_local_multi.addr8[12] = 0xff;
|
|
- context->link_local_multi.addr8[13] |=
|
|
- context->link_local_addr.addr8[13];
|
|
- context->link_local_multi.addr16[7] =
|
|
- context->link_local_addr.addr16[7];
|
|
-
|
|
- /* Default Prefix length is 64 */
|
|
- /* Add Link local address to the head of the ipv6 address
|
|
- list */
|
|
- ipv6_add_prefix_entry(context,
|
|
- &context->link_local_addr, 64);
|
|
- }
|
|
- /*
|
|
- * Convert Multicast IP address to Multicast MAC adress per
|
|
- * RFC 2464: Transmission of IPv6 Packets over Ethernet Networks
|
|
- *
|
|
- * An IPv6 packet with a multicast destination address DST, consisting
|
|
- * of the sixteen octets DST[1] through DST[16], is transmitted to the
|
|
- * Ethernet multicast address whose first two octets are the value 3333
|
|
- * hexadecimal and whose last four octets are the last four octets of
|
|
- * DST.
|
|
- *
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * |0 0 1 1 0 0 1 1|0 0 1 1 0 0 1 1|
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | DST[13] | DST[14] |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | DST[15] | DST[16] |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- *
|
|
- * IPv6 requires the following Multicast IP addresses setup per node.
|
|
- */
|
|
- for (i = 0; i < 3; i++) {
|
|
- mc_addr.addr[0] = 0x33;
|
|
- mc_addr.addr[1] = 0x33;
|
|
- mc_addr.addr[2] = 0x0;
|
|
- mc_addr.addr[3] = 0x0;
|
|
- mc_addr.addr[4] = 0x0;
|
|
-
|
|
- switch (i) {
|
|
- case 0:
|
|
- /* All Nodes Multicast IPv6 address : ff02::1 */
|
|
- mc_addr.addr[5] = 0x1;
|
|
- break;
|
|
-
|
|
- case 1:
|
|
- /* All Host Multicast IPv6 address : ff02::3 */
|
|
- mc_addr.addr[5] = 0x3;
|
|
- break;
|
|
-
|
|
- case 2:
|
|
- /* Solicited Node Multicast Address: ff02::01:ffxx:yyzz
|
|
- */
|
|
- mc_addr.addr[2] = 0xff;
|
|
- mc_addr.addr[3] = mac_addr->addr[3];
|
|
- mc_addr.addr[4] = mac_addr->addr[4];
|
|
- mc_addr.addr[5] = mac_addr->addr[5];
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
- iscsiL2AddMcAddr(context, &mc_addr);
|
|
- }
|
|
-
|
|
- /* Default HOP number */
|
|
- context->hop_limit = IPV6_HOP_LIMIT;
|
|
-}
|
|
-
|
|
-int ipv6_add_prefix_entry(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr, u8_t prefix_len)
|
|
-{
|
|
- int i;
|
|
- struct ipv6_prefix_entry *prefix_entry;
|
|
- struct ipv6_prefix_entry *ipv6_prefix_table =
|
|
- context->ipv6_prefix_table;
|
|
- char addr_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- /* Check if there is an valid entry already. */
|
|
- for (i = 0; i < IPV6_NUM_OF_ADDRESS_ENTRY; i++) {
|
|
- prefix_entry = &ipv6_prefix_table[i];
|
|
-
|
|
- if (prefix_entry->prefix_len != 0) {
|
|
- if (memcmp((char *)&prefix_entry->ip_addr,
|
|
- (char *)ip_addr,
|
|
- sizeof(struct ipv6_addr)) == 0) {
|
|
- /* We already initialize on this interface.
|
|
- There is nothing to do */
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Find an unused entry */
|
|
- for (i = 0; i < IPV6_NUM_OF_ADDRESS_ENTRY; i++) {
|
|
- prefix_entry = &ipv6_prefix_table[i];
|
|
-
|
|
- if (prefix_entry->prefix_len == 0)
|
|
- break;
|
|
- }
|
|
-
|
|
- if (prefix_entry->prefix_len != 0)
|
|
- return -1;
|
|
-
|
|
- prefix_entry->prefix_len = prefix_len / 8;
|
|
-
|
|
- memcpy((char *)&prefix_entry->ip_addr,
|
|
- (char *)ip_addr, sizeof(struct ipv6_addr));
|
|
-
|
|
- inet_ntop(AF_INET6, &prefix_entry->ip_addr.addr8, addr_str,
|
|
- sizeof(addr_str));
|
|
-
|
|
- LOG_DEBUG("IPv6: add prefix IP addr %s", addr_str);
|
|
-
|
|
- /* Put it on the list on head of the list. */
|
|
- if (context->addr_list != NULL)
|
|
- prefix_entry->next = context->addr_list;
|
|
- else
|
|
- prefix_entry->next = NULL;
|
|
-
|
|
- context->addr_list = prefix_entry;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void ipv6_rx_packet(struct ipv6_context *context, u16_t len)
|
|
-{
|
|
- struct ipv6_hdr *ipv6;
|
|
- u16_t protocol;
|
|
-
|
|
- if (!context->ustack) {
|
|
- LOG_WARN("ipv6 rx pkt ipv6_context = %p ustack = %p", context,
|
|
- context->ustack);
|
|
- return;
|
|
- }
|
|
- ipv6 = (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- /* Make sure it's an IPv6 packet */
|
|
- if ((ipv6->ipv6_version_fc & 0xf0) != IPV6_VERSION) {
|
|
- /* It's not an IPv6 packet. Drop it. */
|
|
- LOG_WARN("IPv6 version 0x%x not IPv6", ipv6->ipv6_version_fc);
|
|
- return;
|
|
- }
|
|
- protocol = ipv6_process_rx(ipv6);
|
|
-
|
|
- switch (protocol) {
|
|
- case IPPROTO_ICMPV6:
|
|
- ipv6_icmp_rx(context);
|
|
- break;
|
|
-
|
|
- case IPPROTO_UDP:
|
|
- /* Indicate to UDP processing code */
|
|
- ipv6_udp_rx(context);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-void ipv6_mc_init_dest_mac(struct eth_hdr *eth, struct ipv6_hdr *ipv6)
|
|
-{
|
|
- int i;
|
|
- /*
|
|
- * Initialize address mapping of IPV6 Multicast to multicast MAC
|
|
- * address per RFC 2464.
|
|
- *
|
|
- * An IPv6 packet with a multicast destination address DST, consisting
|
|
- * of the sixteen octets DST[1] through DST[16], is transmitted to the
|
|
- * Ethernet multicast address whose first two octets are the value 3333
|
|
- * hexadecimal and whose last four octets are the last four octets of
|
|
- * DST.
|
|
- *
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * |0 0 1 1 0 0 1 1|0 0 1 1 0 0 1 1|
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | DST[13] | DST[14] |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- * | DST[15] | DST[16] |
|
|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
- */
|
|
- eth->dest_mac.addr[0] = 0x33;
|
|
- eth->dest_mac.addr[1] = 0x33;
|
|
- for (i = 0; i < 4; i++)
|
|
- eth->dest_mac.addr[2 + i] = ipv6->ipv6_dst.addr8[12 + i];
|
|
-}
|
|
-
|
|
-int ipv6_autoconfig(struct ipv6_context *context)
|
|
-{
|
|
- return ipv6_discover_address(context);
|
|
-}
|
|
-
|
|
-int ipv6_discover_address(struct ipv6_context *context)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_hdr *icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- int rc = 0;
|
|
-
|
|
- /* Retrieve tx buffer */
|
|
- if (eth == NULL || ipv6 == NULL)
|
|
- return -EAGAIN;
|
|
-
|
|
- /* Setup IPv6 All Routers Multicast address : ff02::2 */
|
|
- memset((char *)&ipv6->ipv6_dst, 0, sizeof(struct ipv6_addr));
|
|
- ipv6->ipv6_dst.addr8[0] = 0xff;
|
|
- ipv6->ipv6_dst.addr8[1] = 0x02;
|
|
- ipv6->ipv6_dst.addr8[15] = 0x02;
|
|
- ipv6->ipv6_hop_limit = 255;
|
|
-
|
|
- /* Initialize MAC header based on destination MAC address */
|
|
- ipv6_mc_init_dest_mac(eth, ipv6);
|
|
- ipv6->ipv6_nxt_hdr = IPPROTO_ICMPV6;
|
|
-
|
|
- icmp->icmpv6_type = ICMPV6_RTR_SOL;
|
|
- icmp->icmpv6_code = 0;
|
|
- icmp->icmpv6_data = 0;
|
|
- icmp->icmpv6_cksum = 0;
|
|
- ipv6_icmp_init_link_option(context,
|
|
- (struct icmpv6_opt_link_addr *)((u8_t *)icmp
|
|
- + sizeof(struct icmpv6_hdr)),
|
|
- IPV6_ICMP_OPTION_SRC_ADDR);
|
|
- ipv6->ipv6_plen = HOST_TO_NET16((sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct icmpv6_opt_link_addr)));
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&context->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
-
|
|
- icmp->icmpv6_cksum = 0;
|
|
- LOG_DEBUG("IPv6: Send rtr sol");
|
|
- ipv6_send(context, (u8_t *) icmp - (u8_t *) eth +
|
|
- sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct icmpv6_opt_link_addr));
|
|
- return rc;
|
|
-}
|
|
-
|
|
-u16_t ipv6_process_rx(struct ipv6_hdr *ipv6)
|
|
-{
|
|
- return ipv6->ipv6_nxt_hdr;
|
|
-}
|
|
-
|
|
-int ipv6_send(struct ipv6_context *context, u16_t packet_len)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
-
|
|
- ipv6_setup_hdrs(context, eth, ipv6, packet_len);
|
|
-
|
|
- return iscsiL2Send(context, packet_len);
|
|
-}
|
|
-
|
|
-void ipv6_send_udp_packet(struct ipv6_context *context, u16_t packet_len)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct udp_hdr *udp = (struct udp_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
-
|
|
- ipv6->ipv6_nxt_hdr = IPPROTO_UDP;
|
|
- ipv6->ipv6_plen =
|
|
- HOST_TO_NET16(packet_len - ((u8_t *)udp - (u8_t *)eth));
|
|
-
|
|
- udp->chksum = 0;
|
|
-
|
|
- /*
|
|
- * We only use UDP packet for DHCPv6. The source address is always
|
|
- * link-local address.
|
|
- */
|
|
- ipv6->ipv6_src.addr[0] = 0;
|
|
-
|
|
- /* Hop limit is always 1 for DHCPv6 packet. */
|
|
- ipv6->ipv6_hop_limit = 1;
|
|
-
|
|
- ipv6_send(context, packet_len);
|
|
-}
|
|
-
|
|
-void ipv6_setup_hdrs(struct ipv6_context *context, struct eth_hdr *eth,
|
|
- struct ipv6_hdr *ipv6, u16_t packet_len)
|
|
-{
|
|
- struct ipv6_addr *our_address;
|
|
-
|
|
- /* VLAN will be taken cared of in the nic layer */
|
|
- eth->len_type = HOST_TO_NET16(LAYER2_TYPE_IPV6);
|
|
- memcpy((char *)ð->src_mac,
|
|
- (char *)&context->mac_addr, sizeof(struct mac_address));
|
|
-
|
|
- /* Put the traffic class into the packet. */
|
|
- memset(&ipv6->ipv6_version_fc, 0, sizeof(u32_t));
|
|
- ipv6->ipv6_version_fc = IPV6_VERSION;
|
|
- if (ipv6->ipv6_hop_limit == 0)
|
|
- ipv6->ipv6_hop_limit = context->hop_limit;
|
|
-
|
|
- if (ipv6->ipv6_src.addr[0] == 0) {
|
|
- /* Need to initialize source IP address. */
|
|
- our_address = ipv6_our_address(context);
|
|
- if (our_address != NULL) {
|
|
- /* Assume that caller has filled in the destination
|
|
- IP address */
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)our_address, sizeof(struct ipv6_addr));
|
|
- }
|
|
- }
|
|
-
|
|
- ipv6_insert_protocol_chksum(ipv6);
|
|
-}
|
|
-
|
|
-static void ipv6_insert_protocol_chksum(struct ipv6_hdr *ipv6)
|
|
-{
|
|
- u32_t sum;
|
|
- u16_t *ptr;
|
|
- u16_t *protocol_data_ptr;
|
|
- int i;
|
|
- u16_t protocol_data_len;
|
|
- u16_t checksum;
|
|
-
|
|
- /*
|
|
- * This routine assumes that there is no extension header. This driver
|
|
- * doesn't user extension header to keep driver small and simple.
|
|
- *
|
|
- * Pseudo check consists of the following:
|
|
- * SRC IP, DST IP, Protocol Data Length, and Next Header.
|
|
- */
|
|
- sum = 0;
|
|
- ptr = (u16_t *)&ipv6->ipv6_src.addr16[0];
|
|
-
|
|
- for (i = 0; i < sizeof(struct ipv6_addr); i++) {
|
|
- sum += HOST_TO_NET16(*ptr);
|
|
- ptr++;
|
|
- }
|
|
-
|
|
- /* Keep track where the layer header is */
|
|
- protocol_data_ptr = ptr;
|
|
-
|
|
- protocol_data_len = HOST_TO_NET16(ipv6->ipv6_plen);
|
|
- sum += protocol_data_len;
|
|
- sum += ipv6->ipv6_nxt_hdr;
|
|
- /* Sum now contains sum of IPv6 pseudo header. Let's add the data
|
|
- streams. */
|
|
- if (protocol_data_len & 1) {
|
|
- /* Length of data is odd */
|
|
- *((u8_t *) ptr + protocol_data_len) = 0;
|
|
- protocol_data_len++;
|
|
- }
|
|
-
|
|
- for (i = 0; i < protocol_data_len / 2; i++) {
|
|
- sum += HOST_TO_NET16(*ptr);
|
|
- ptr++;
|
|
- }
|
|
-
|
|
- sum = (sum >> 16) + (sum & 0xffff);
|
|
- sum += (sum >> 16);
|
|
- sum &= 0xffff;
|
|
- checksum = (u16_t) (~sum);
|
|
- checksum = HOST_TO_NET16(checksum);
|
|
-
|
|
- switch (ipv6->ipv6_nxt_hdr) {
|
|
- case IPPROTO_ICMPV6:
|
|
- /* Insert correct ICMPv6 checksum */
|
|
- ((struct icmpv6_hdr *)(protocol_data_ptr))->icmpv6_cksum =
|
|
- checksum;
|
|
- break;
|
|
- case IPPROTO_UDP:
|
|
- /* Insert correct UDP checksum */
|
|
- ((struct udp_hdr *)protocol_data_ptr)->chksum = checksum;
|
|
- break;
|
|
- default:
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-int ipv6_is_it_our_link_local_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr)
|
|
-{
|
|
- u8_t *test_addr = (u8_t *) ip_addr->addr8;
|
|
- u8_t test_remainder;
|
|
-
|
|
- if (test_addr[0] != context->link_local_addr.addr8[0])
|
|
- return FALSE;
|
|
-
|
|
- test_remainder = (test_addr[1] & 0xC0) >> 6;
|
|
- if (test_remainder != 2)
|
|
- return FALSE;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-static int ipv6_is_it_our_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ipv6_addr)
|
|
-{
|
|
- struct ipv6_prefix_entry *ipv6_prefix;
|
|
-
|
|
- for (ipv6_prefix = context->addr_list; ipv6_prefix != NULL;
|
|
- ipv6_prefix = ipv6_prefix->next) {
|
|
- if (IPV6_ARE_ADDR_EQUAL(&ipv6_prefix->ip_addr, ipv6_addr))
|
|
- return TRUE;
|
|
- }
|
|
-
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
-struct ipv6_addr *ipv6_our_address(struct ipv6_context *context)
|
|
-{
|
|
- return &context->link_local_addr;
|
|
-}
|
|
-
|
|
-int ipv6_ip_in_arp_table(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr,
|
|
- struct mac_address *mac_addr)
|
|
-{
|
|
- struct ipv6_arp_entry *arp_entry;
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; i++) {
|
|
- arp_entry = &context->ipv6_arp_table[i];
|
|
-
|
|
- if (IPV6_ARE_ADDR_EQUAL(&arp_entry->ip_addr, ip_addr)) {
|
|
- memcpy((char *)mac_addr, &arp_entry->mac_addr,
|
|
- sizeof(struct mac_address));
|
|
- return 1;
|
|
- }
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-struct ipv6_addr *ipv6_find_longest_match(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr)
|
|
-{
|
|
- struct ipv6_prefix_entry *ipv6_prefix;
|
|
- struct ipv6_prefix_entry *best_match = NULL;
|
|
- int longest_len = -1;
|
|
- int len;
|
|
-
|
|
- for (ipv6_prefix = context->addr_list; ipv6_prefix != NULL;
|
|
- ipv6_prefix = ipv6_prefix->next) {
|
|
- if (!IPV6_IS_ADDR_LINKLOCAL(&ipv6_prefix->ip_addr)) {
|
|
- len = best_match_bufcmp((u8_t *)&ipv6_prefix->ip_addr,
|
|
- (u8_t *)ip_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- if (len > longest_len) {
|
|
- best_match = ipv6_prefix;
|
|
- longest_len = len;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (best_match)
|
|
- return &best_match->ip_addr;
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-void ipv6_arp_out(struct ipv6_context *context, int *uip_len)
|
|
-{
|
|
- /* Empty routine */
|
|
-}
|
|
-
|
|
-
|
|
-static void ipv6_update_arp_table(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr,
|
|
- struct mac_address *mac_addr)
|
|
-{
|
|
- struct ipv6_arp_entry *arp_entry;
|
|
- int i;
|
|
- struct ipv6_arp_entry *ipv6_arp_table = context->ipv6_arp_table;
|
|
-
|
|
- LOG_DEBUG("IPv6: Neighbor update");
|
|
- /*
|
|
- * Walk through the ARP mapping table and try to find an entry to
|
|
- * update. If none is found, the IP -> MAC address mapping is
|
|
- * inserted in the ARP table.
|
|
- */
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; i++) {
|
|
- arp_entry = &ipv6_arp_table[i];
|
|
-
|
|
- /* Only check those entries that are actually in use. */
|
|
- if (arp_entry->ip_addr.addr[0] != 0) {
|
|
- /*
|
|
- * Check if the source IP address of the incoming
|
|
- * packet matches the IP address in this ARP table
|
|
- * entry.
|
|
- */
|
|
- if (IPV6_ARE_ADDR_EQUAL(&arp_entry->ip_addr, ip_addr)) {
|
|
- /* An old entry found, update this and return */
|
|
- memcpy((char *)&arp_entry->mac_addr,
|
|
- (char *)mac_addr,
|
|
- sizeof(struct mac_address));
|
|
- arp_entry->time = context->arptime;
|
|
- return;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /*
|
|
- * If we get here, no existing ARP table entry was found, so we
|
|
- * create one.
|
|
- *
|
|
- * First, we try to find an unused entry in the ARP table.
|
|
- */
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; i++) {
|
|
- arp_entry = &ipv6_arp_table[i];
|
|
-
|
|
- if (arp_entry->ip_addr.addr[0] == 0)
|
|
- break;
|
|
- }
|
|
-
|
|
- if (i == UIP_ARPTAB_SIZE)
|
|
- return;
|
|
-
|
|
- /* Index j is the entry that is least used */
|
|
- arp_entry = &ipv6_arp_table[i];
|
|
- memcpy((char *)&arp_entry->ip_addr, (char *)ip_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- memcpy((char *)&arp_entry->mac_addr,
|
|
- (char *)mac_addr, sizeof(struct mac_address));
|
|
-
|
|
- arp_entry->time = context->arptime;
|
|
-}
|
|
-
|
|
-/* DestIP is intact */
|
|
-int ipv6_send_nd_solicited_packet(struct ipv6_context *context,
|
|
- struct eth_hdr *eth, struct ipv6_hdr *ipv6)
|
|
-{
|
|
- struct icmpv6_hdr *icmp;
|
|
- int pkt_len = 0;
|
|
- struct ipv6_addr *longest_match_addr;
|
|
- char addr_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- ipv6->ipv6_nxt_hdr = IPPROTO_ICMPV6;
|
|
-
|
|
- /* Depending on the IPv6 address of the target, we'll need to determine
|
|
- whether we use the assigned IPv6 address/RA or the link local address
|
|
- */
|
|
- /* Use Link-local as source address */
|
|
- if (ipv6_is_it_our_link_local_address(context, &ipv6->ipv6_dst) ==
|
|
- TRUE) {
|
|
- LOG_DEBUG("IPv6: NS using link local");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&context->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- } else {
|
|
- longest_match_addr =
|
|
- ipv6_find_longest_match(context, &ipv6->ipv6_dst);
|
|
- if (longest_match_addr) {
|
|
- LOG_DEBUG("IPv6: NS using longest match addr");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)longest_match_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- } else {
|
|
- LOG_DEBUG("IPv6: NS using link local instead");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&context->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- }
|
|
- }
|
|
- icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 + sizeof(struct ipv6_hdr));
|
|
-
|
|
- inet_ntop(AF_INET6, &ipv6->ipv6_src.addr8, addr_str, sizeof(addr_str));
|
|
- LOG_DEBUG("IPv6: NS host IP addr: %s", addr_str);
|
|
- /*
|
|
- * Destination IP address to be resolved is after the ICMPv6
|
|
- * header.
|
|
- */
|
|
- memcpy((char *)((u8_t *)icmp + sizeof(struct icmpv6_hdr)),
|
|
- (char *)&ipv6->ipv6_dst, sizeof(struct ipv6_addr));
|
|
-
|
|
- /*
|
|
- * Destination IP in the IPv6 header contains solicited-node multicast
|
|
- * address corresponding to the target address.
|
|
- *
|
|
- * ff02::01:ffxx:yyzz. Where xyz are least
|
|
- * significant of 24-bit MAC address.
|
|
- */
|
|
- memset((char *)&ipv6->ipv6_dst, 0, sizeof(struct ipv6_addr) - 3);
|
|
- ipv6->ipv6_dst.addr8[0] = 0xff;
|
|
- ipv6->ipv6_dst.addr8[1] = 0x02;
|
|
- ipv6->ipv6_dst.addr8[11] = 0x01;
|
|
- ipv6->ipv6_dst.addr8[12] = 0xff;
|
|
- ipv6_mc_init_dest_mac(eth, ipv6);
|
|
- ipv6->ipv6_hop_limit = 255;
|
|
-
|
|
- icmp->icmpv6_type = ICMPV6_NEIGH_SOL;
|
|
- icmp->icmpv6_code = 0;
|
|
- icmp->icmpv6_data = 0;
|
|
- icmp->icmpv6_cksum = 0;
|
|
- ipv6_icmp_init_link_option(context,
|
|
- (struct icmpv6_opt_link_addr *)((u8_t *)icmp
|
|
- + sizeof(struct icmpv6_hdr)
|
|
- + sizeof(struct ipv6_addr)),
|
|
- IPV6_ICMP_OPTION_SRC_ADDR);
|
|
- ipv6->ipv6_plen = HOST_TO_NET16((sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct icmpv6_opt_link_addr) +
|
|
- sizeof(struct ipv6_addr)));
|
|
- /* Total packet size */
|
|
- pkt_len = (u8_t *) icmp - (u8_t *) eth +
|
|
- sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct icmpv6_opt_link_addr) + sizeof(struct ipv6_addr);
|
|
- ipv6_setup_hdrs(context, eth, ipv6, pkt_len);
|
|
- return pkt_len;
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_init_link_option(struct ipv6_context *context,
|
|
- struct icmpv6_opt_link_addr *link_opt,
|
|
- u8_t type)
|
|
-{
|
|
- link_opt->hdr.type = type;
|
|
- link_opt->hdr.len = sizeof(struct icmpv6_opt_link_addr) / 8;
|
|
- memcpy((char *)&link_opt->link_addr,
|
|
- (char *)&context->mac_addr, sizeof(struct mac_address));
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_rx(struct ipv6_context *context)
|
|
-{
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_hdr *icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- uip_icmp_echo_hdr_t *icmp_echo_hdr =
|
|
- (uip_icmp_echo_hdr_t *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
-
|
|
- switch (icmp->icmpv6_type) {
|
|
- case ICMPV6_RTR_ADV:
|
|
- ipv6_icmp_handle_router_adv(context);
|
|
- break;
|
|
-
|
|
- case ICMPV6_NEIGH_SOL:
|
|
- ipv6_icmp_handle_nd_sol(context);
|
|
- break;
|
|
-
|
|
- case ICMPV6_NEIGH_ADV:
|
|
- ipv6_icmp_handle_nd_adv(context);
|
|
- break;
|
|
-
|
|
- case ICMPV6_ECHO_REQUEST:
|
|
- /* Response with ICMP reply */
|
|
- ipv6_icmp_handle_echo_request(context);
|
|
- break;
|
|
-
|
|
- case ICMPV6_ECHO_REPLY:
|
|
- /* Handle ICMP reply */
|
|
- process_icmp_packet(icmp_echo_hdr, context->ustack);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_handle_router_adv(struct ipv6_context *context)
|
|
-{
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_router_advert *icmp =
|
|
- (struct icmpv6_router_advert *)((u8_t *)ipv6 + sizeof(struct ipv6_hdr));
|
|
- struct icmpv6_opt_hdr *icmp_opt;
|
|
- u16_t opt_len;
|
|
- u16_t len;
|
|
- char addr_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- if (context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)
|
|
- return;
|
|
-
|
|
- opt_len = HOST_TO_NET16(ipv6->ipv6_plen) -
|
|
- sizeof(struct icmpv6_router_advert);
|
|
-
|
|
- icmp_opt = (struct icmpv6_opt_hdr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_router_advert));
|
|
- len = 0;
|
|
- while (len < opt_len) {
|
|
- icmp_opt = (struct icmpv6_opt_hdr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_router_advert) +
|
|
- len);
|
|
-
|
|
- switch (icmp_opt->type) {
|
|
- case IPV6_ICMP_OPTION_PREFIX:
|
|
- ipv6_icmp_process_prefix(context,
|
|
- (struct icmpv6_opt_prefix *)icmp_opt);
|
|
- context->flags |= IPV6_FLAGS_ROUTER_ADV_RECEIVED;
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- len += icmp_opt->len * 8;
|
|
- }
|
|
-
|
|
- if (context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED) {
|
|
- LOG_DEBUG("IPv6: RTR ADV nd_ra_flags = 0x%x",
|
|
- icmp->nd_ra_flags_reserved);
|
|
- if (icmp->nd_ra_curhoplimit > 0)
|
|
- context->hop_limit = icmp->nd_ra_curhoplimit;
|
|
-
|
|
- if (icmp->nd_ra_flags_reserved & IPV6_RA_MANAGED_FLAG)
|
|
- context->flags |= IPV6_FLAGS_MANAGED_ADDR_CONFIG;
|
|
-
|
|
- if (icmp->nd_ra_flags_reserved & IPV6_RA_CONFIG_FLAG)
|
|
- context->flags |= IPV6_FLAGS_OTHER_STATEFUL_CONFIG;
|
|
-
|
|
- if (icmp->nd_ra_router_lifetime != 0) {
|
|
- /* There is a default router. */
|
|
- if (context->ustack->router_autocfg !=
|
|
- IPV6_RTR_AUTOCFG_OFF)
|
|
- memcpy(
|
|
- (char *)&context->default_router,
|
|
- (char *)&ipv6->ipv6_src,
|
|
- sizeof(struct ipv6_addr));
|
|
- inet_ntop(AF_INET6, &context->default_router,
|
|
- addr_str, sizeof(addr_str));
|
|
- LOG_DEBUG("IPv6: Got default router IP addr: %s",
|
|
- addr_str);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_process_prefix(struct ipv6_context *context,
|
|
- struct icmpv6_opt_prefix *icmp_prefix)
|
|
-{
|
|
- struct ipv6_addr addr;
|
|
- char addr_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- /* we only process on-link address info */
|
|
- if (!(icmp_prefix->flags & ICMPV6_OPT_PREFIX_FLAG_ON_LINK))
|
|
- return;
|
|
-
|
|
- /*
|
|
- * We only process prefix length of 64 since our Identifier is 64-bit
|
|
- */
|
|
- if (icmp_prefix->prefix_len == 64) {
|
|
- /* Copy 64-bit from the local-link address to create
|
|
- IPv6 address */
|
|
- memcpy((char *)&addr,
|
|
- (char *)&icmp_prefix->prefix, 8);
|
|
- memcpy((char *)&addr.addr8[8],
|
|
- &context->link_local_addr.addr8[8], 8);
|
|
- inet_ntop(AF_INET6, &addr, addr_str, sizeof(addr_str));
|
|
- LOG_DEBUG("IPv6: Got RA ICMP option IP addr: %s", addr_str);
|
|
- ipv6_add_prefix_entry(context, &addr, 64);
|
|
- }
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_handle_nd_adv(struct ipv6_context *context)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_hdr *icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- struct icmpv6_opt_link_addr *link_opt =
|
|
- (struct icmpv6_opt_link_addr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_hdr) + sizeof(struct ipv6_addr));
|
|
- struct ipv6_addr *tar_addr6;
|
|
- char addr_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- /* Added the multicast check for ARP table update */
|
|
- /* Should we qualify for only our host's multicast and our
|
|
- link_local_multicast?? */
|
|
- LOG_DEBUG("IPv6: Handle nd adv");
|
|
- if ((ipv6_is_it_our_address(context, &ipv6->ipv6_dst) == TRUE) ||
|
|
- (memcmp((char *)&context->link_local_multi,
|
|
- (char *)&ipv6->ipv6_dst, sizeof(struct ipv6_addr)) == 0) ||
|
|
- (memcmp((char *)&context->multi,
|
|
- (char *)&ipv6->ipv6_dst, sizeof(struct ipv6_addr)) == 0)) {
|
|
- /*
|
|
- * This is an ARP reply for our addresses. Let's update the
|
|
- * ARP table.
|
|
- */
|
|
- ipv6_update_arp_table(context, &ipv6->ipv6_src,
|
|
- ð->src_mac);
|
|
-
|
|
- /* Now check for the target address option and update that as
|
|
- well */
|
|
- if (link_opt->hdr.type == IPV6_ICMP_OPTION_TAR_ADDR) {
|
|
- tar_addr6 = (struct ipv6_addr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_hdr));
|
|
- LOG_DEBUG("IPV6: Target MAC "
|
|
- "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
- link_opt->link_addr[0], link_opt->link_addr[1],
|
|
- link_opt->link_addr[2], link_opt->link_addr[3],
|
|
- link_opt->link_addr[4], link_opt->link_addr[5]);
|
|
- inet_ntop(AF_INET6, &tar_addr6->addr8, addr_str,
|
|
- sizeof(addr_str));
|
|
- LOG_DEBUG("IPv6: Target IP addr %s", addr_str);
|
|
- ipv6_update_arp_table(context, tar_addr6,
|
|
- (struct mac_address *)link_opt->link_addr);
|
|
- }
|
|
-
|
|
- }
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_handle_nd_sol(struct ipv6_context *context)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_hdr *icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- struct icmpv6_opt_link_addr *link_opt =
|
|
- (struct icmpv6_opt_link_addr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_hdr) + sizeof(struct ipv6_addr));
|
|
- int icmpv6_opt_len = 0;
|
|
- struct ipv6_addr tmp;
|
|
- struct ipv6_addr *longest_match_addr, *tar_addr6;
|
|
-
|
|
- LOG_DEBUG("IPv6: Handle nd sol");
|
|
-
|
|
- if ((memcmp((char *)&context->mac_addr,
|
|
- (char *)ð->dest_mac, sizeof(struct mac_address)) != 0) &&
|
|
- (iscsiL2IsOurMcAddr(context, (struct mac_address *)ð->dest_mac)
|
|
- == FALSE)) {
|
|
- /* This packet is not for us to handle */
|
|
- LOG_DEBUG("IPv6: MAC not addressed to us "
|
|
- "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
- eth->dest_mac.addr[0], eth->dest_mac.addr[1],
|
|
- eth->dest_mac.addr[2], eth->dest_mac.addr[3],
|
|
- eth->dest_mac.addr[4], eth->dest_mac.addr[5]);
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Also check for the icmpv6_data before generating the reply */
|
|
- if (ipv6_is_it_our_address(context,
|
|
- (struct ipv6_addr *) ((u8_t *) icmp +
|
|
- sizeof(struct icmpv6_hdr)))
|
|
- == FALSE) {
|
|
- /* This packet is not for us to handle */
|
|
- LOG_DEBUG("IPv6: IP not addressed to us");
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Copy source MAC to Destination MAC */
|
|
- memcpy((char *)ð->dest_mac,
|
|
- (char *)ð->src_mac, sizeof(struct mac_address));
|
|
-
|
|
- /* Dest IP contains source IP */
|
|
- memcpy((char *)&tmp,
|
|
- (char *)&ipv6->ipv6_dst, sizeof(struct ipv6_addr));
|
|
- memcpy((char *)&ipv6->ipv6_dst,
|
|
- (char *)&ipv6->ipv6_src, sizeof(struct ipv6_addr));
|
|
-
|
|
- /* Examine the Neighbor Solicitation ICMPv6 target address field.
|
|
- If target address exist, use that to find best match src address
|
|
- for the reply */
|
|
- if (link_opt->hdr.type == IPV6_ICMP_OPTION_SRC_ADDR) {
|
|
- tar_addr6 = (struct ipv6_addr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_hdr));
|
|
- if (ipv6_is_it_our_link_local_address(context, tar_addr6)
|
|
- == TRUE) {
|
|
- LOG_DEBUG("IPv6: NA using link local");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&context->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- } else {
|
|
- longest_match_addr =
|
|
- ipv6_find_longest_match(context, tar_addr6);
|
|
- if (longest_match_addr) {
|
|
- LOG_DEBUG("IPv6: NA using longest match addr");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)longest_match_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- } else {
|
|
- LOG_DEBUG("IPv6: NA using link local instead");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&context->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- }
|
|
- }
|
|
- } else {
|
|
- /* No target link address, just use whatever it sent to us */
|
|
- LOG_DEBUG("IPv6: NA use dst addr");
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&tmp,
|
|
- sizeof(struct ipv6_addr));
|
|
- }
|
|
- ipv6->ipv6_hop_limit = 255;
|
|
- icmp->icmpv6_type = ICMPV6_NEIGH_ADV;
|
|
- icmp->icmpv6_code = 0;
|
|
- icmp->icmpv6_data = 0;
|
|
- icmp->icmpv6_cksum = 0;
|
|
- icmp->data.icmpv6_un_data8[0] =
|
|
- IPV6_NA_FLAG_SOLICITED | IPV6_NA_FLAG_OVERRIDE;
|
|
- memcpy((char *)((u8_t *)icmp + sizeof(struct icmpv6_hdr)),
|
|
- (char *)&ipv6->ipv6_src,
|
|
- sizeof(struct ipv6_addr));
|
|
-
|
|
- /* Add the target link address option only for all solicitation */
|
|
- ipv6_icmp_init_link_option(context,
|
|
- (struct icmpv6_opt_link_addr *)((u8_t *)icmp +
|
|
- sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct ipv6_addr)),
|
|
- IPV6_ICMP_OPTION_TAR_ADDR);
|
|
- icmpv6_opt_len = sizeof(struct icmpv6_opt_link_addr);
|
|
- ipv6->ipv6_plen = HOST_TO_NET16((sizeof(struct icmpv6_hdr) +
|
|
- icmpv6_opt_len + sizeof(struct ipv6_addr)));
|
|
- LOG_DEBUG("IPv6: Send nd adv");
|
|
- ipv6_send(context,
|
|
- (u8_t *) icmp - (u8_t *) eth +
|
|
- sizeof(struct icmpv6_hdr) +
|
|
- sizeof(struct icmpv6_opt_link_addr) +
|
|
- sizeof(struct ipv6_addr));
|
|
- return;
|
|
-}
|
|
-
|
|
-static void ipv6_icmp_handle_echo_request(struct ipv6_context *context)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct icmpv6_hdr *icmp = (struct icmpv6_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- struct ipv6_addr temp;
|
|
-
|
|
- /* Copy source MAC to Destination MAC */
|
|
- memcpy((char *)ð->dest_mac,
|
|
- (char *)ð->src_mac, sizeof(struct mac_address));
|
|
-
|
|
- memcpy((char *)&temp,
|
|
- (char *)&ipv6->ipv6_dst, sizeof(struct ipv6_addr));
|
|
-
|
|
- /* Dest IP contains source IP */
|
|
- memcpy((char *)&ipv6->ipv6_dst,
|
|
- (char *)&ipv6->ipv6_src, sizeof(struct ipv6_addr));
|
|
- /* Use Link-local as source address */
|
|
- memcpy((char *)&ipv6->ipv6_src,
|
|
- (char *)&temp, sizeof(struct ipv6_addr));
|
|
-
|
|
- ipv6->ipv6_hop_limit = context->hop_limit;
|
|
- icmp->icmpv6_type = ICMPV6_ECHO_REPLY;
|
|
- icmp->icmpv6_code = 0;
|
|
- icmp->icmpv6_cksum = 0;
|
|
- LOG_DEBUG("IPv6: Send echo reply");
|
|
- ipv6_send(context, (u8_t *) icmp - (u8_t *) eth +
|
|
- sizeof(struct ipv6_hdr) + HOST_TO_NET16(ipv6->ipv6_plen));
|
|
- return;
|
|
-}
|
|
-
|
|
-void ipv6_set_ip_params(struct ipv6_context *context,
|
|
- struct ipv6_addr *src_ip, u8_t prefix_len,
|
|
- struct ipv6_addr *default_gateway,
|
|
- struct ipv6_addr *linklocal)
|
|
-{
|
|
- if (!(IPV6_IS_ADDR_UNSPECIFIED(src_ip))) {
|
|
- ipv6_add_prefix_entry(context, src_ip, prefix_len);
|
|
- /* Create the multi_dest address */
|
|
- memset(&context->multi_dest, 0, sizeof(struct ipv6_addr));
|
|
- context->multi_dest.addr8[0] = 0xff;
|
|
- context->multi_dest.addr8[1] = 0x02;
|
|
- context->multi_dest.addr8[11] = 0x01;
|
|
- context->multi_dest.addr8[12] = 0xff;
|
|
- context->multi_dest.addr8[13] = src_ip->addr8[13];
|
|
- context->multi_dest.addr16[7] = src_ip->addr16[7];
|
|
- /* Create the multi address */
|
|
- memset(&context->multi, 0, sizeof(struct ipv6_addr));
|
|
- context->multi.addr8[0] = 0xfc;
|
|
- context->multi.addr8[2] = 0x02;
|
|
- context->multi.addr16[7] = src_ip->addr16[7];
|
|
- }
|
|
-
|
|
- if (!(IPV6_IS_ADDR_UNSPECIFIED(default_gateway))) {
|
|
- /* Override the default gateway addr */
|
|
- memcpy((char *)&context->default_router,
|
|
- (char *)default_gateway, sizeof(struct ipv6_addr));
|
|
- ipv6_add_prefix_entry(context, default_gateway,
|
|
- prefix_len);
|
|
- }
|
|
- if (!(IPV6_IS_ADDR_UNSPECIFIED(linklocal))) {
|
|
- /* Override the linklocal addr */
|
|
- memcpy((char *)&context->link_local_addr,
|
|
- (char *)linklocal, sizeof(struct ipv6_addr));
|
|
- context->link_local_multi.addr8[0] = 0xff;
|
|
- context->link_local_multi.addr8[1] = 0x02;
|
|
- context->link_local_multi.addr8[11] = 0x01;
|
|
- context->link_local_multi.addr8[12] = 0xff;
|
|
- context->link_local_multi.addr8[13] |=
|
|
- context->link_local_addr.addr8[13];
|
|
- context->link_local_multi.addr16[7] =
|
|
- context->link_local_addr.addr16[7];
|
|
-
|
|
- /* Default Prefix length is 64 */
|
|
- /* Add Link local address to the head of the ipv6 address
|
|
- list */
|
|
- ipv6_add_prefix_entry(context,
|
|
- &context->link_local_addr, 64);
|
|
- }
|
|
-}
|
|
-
|
|
-int ipv6_get_source_ip_addrs(struct ipv6_context *context,
|
|
- struct ipv6_addr_entry *addr_list)
|
|
-{
|
|
- struct ipv6_prefix_entry *ipv6_prefix;
|
|
- int i;
|
|
-
|
|
- for (i = 0, ipv6_prefix = context->addr_list; ipv6_prefix != NULL;
|
|
- ipv6_prefix = ipv6_prefix->next) {
|
|
- memcpy((char *)&addr_list->ip_addr,
|
|
- (char *)&ipv6_prefix->ip_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- addr_list->prefix_len = ipv6_prefix->prefix_len * 8;
|
|
-
|
|
- i++;
|
|
- addr_list++;
|
|
- }
|
|
-
|
|
- return i;
|
|
-}
|
|
-
|
|
-int ipv6_get_default_router_ip_addrs(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr)
|
|
-{
|
|
- /* This is a default router. */
|
|
- memcpy((char *)ip_addr,
|
|
- (char *)&context->default_router,
|
|
- sizeof(struct ipv6_addr));
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static void ipv6_udp_rx(struct ipv6_context *context)
|
|
-{
|
|
- struct eth_hdr *eth =
|
|
- (struct eth_hdr *)context->ustack->data_link_layer;
|
|
- struct ipv6_hdr *ipv6 =
|
|
- (struct ipv6_hdr *)context->ustack->network_layer;
|
|
- struct udp_hdr *udp = (struct udp_hdr *)((u8_t *)ipv6 +
|
|
- sizeof(struct ipv6_hdr));
|
|
- struct dhcpv6_context *dhcpv6c;
|
|
-
|
|
- /*
|
|
- * We only care about DHCPv6 packets from the DHCPv6 server. We drop
|
|
- * all others.
|
|
- */
|
|
- if (!(context->flags & IPV6_FLAGS_DISABLE_DHCPV6)) {
|
|
- if ((udp->src_port == HOST_TO_NET16(DHCPV6_SERVER_PORT)) &&
|
|
- (udp->dest_port == HOST_TO_NET16(DHCPV6_CLIENT_PORT))) {
|
|
- dhcpv6c = context->dhcpv6_context;
|
|
- dhcpv6c->eth = eth;
|
|
- dhcpv6c->ipv6 = ipv6;
|
|
- dhcpv6c->udp = udp;
|
|
- ipv6_udp_handle_dhcp(dhcpv6c);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-struct mac_address *ipv6_get_link_addr(struct ipv6_context *context)
|
|
-{
|
|
- return &context->mac_addr;
|
|
-}
|
|
-
|
|
-u16_t ipv6_do_stateful_dhcpv6(struct ipv6_context *context, u32_t flags)
|
|
-{
|
|
- u16_t task = 0;
|
|
- u16_t ra_flags;
|
|
-
|
|
- ra_flags = context->flags &
|
|
- (IPV6_FLAGS_MANAGED_ADDR_CONFIG | IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
|
|
-
|
|
- if (!(context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)) {
|
|
- LOG_DEBUG("IPv6: There is no IPv6 router on the network");
|
|
- ra_flags |=
|
|
- (IPV6_FLAGS_MANAGED_ADDR_CONFIG |
|
|
- IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
|
|
- }
|
|
-
|
|
- if ((flags & ISCSI_FLAGS_DHCP_TCPIP_CONFIG) &&
|
|
- (ra_flags & IPV6_FLAGS_MANAGED_ADDR_CONFIG))
|
|
- task |= DHCPV6_TASK_GET_IP_ADDRESS;
|
|
-
|
|
- if ((flags & ISCSI_FLAGS_DHCP_ISCSI_CONFIG) &&
|
|
- (ra_flags & IPV6_FLAGS_OTHER_STATEFUL_CONFIG))
|
|
- task |= DHCPV6_TASK_GET_OTHER_PARAMS;
|
|
-
|
|
- LOG_DEBUG("IPv6: Stateful flags = 0x%x, ra_flags = 0x%x, task = 0x%x",
|
|
- flags, ra_flags, task);
|
|
-
|
|
- return task;
|
|
-}
|
|
-
|
|
-void ipv6_add_solit_node_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr)
|
|
-{
|
|
- struct mac_address mac_addr;
|
|
-
|
|
- /*
|
|
- * Add Solicited Node Multicast Address for statically configured IPv6
|
|
- * address.
|
|
- */
|
|
- mac_addr.addr[0] = 0x33;
|
|
- mac_addr.addr[1] = 0x33;
|
|
- mac_addr.addr[2] = 0xff;
|
|
- mac_addr.addr[3] = ip_addr->addr8[13];
|
|
- mac_addr.addr[4] = ip_addr->addr8[14];
|
|
- mac_addr.addr[5] = ip_addr->addr8[15];
|
|
- iscsiL2AddMcAddr(context, (struct mac_address *)&mac_addr);
|
|
-}
|
|
-
|
|
-void ipv6_cfg_link_local_addr(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr)
|
|
-{
|
|
- memcpy((char *)&context->link_local_addr,
|
|
- (char *)ip_addr, sizeof(struct ipv6_addr));
|
|
-}
|
|
-
|
|
-void ipv6_disable_dhcpv6(struct ipv6_context *context)
|
|
-{
|
|
- context->flags |= IPV6_FLAGS_DISABLE_DHCPV6;
|
|
-}
|
|
diff --git a/iscsiuio/src/uip/ipv6.h b/iscsiuio/src/uip/ipv6.h
|
|
deleted file mode 100644
|
|
index 3586437..0000000
|
|
--- a/iscsiuio/src/uip/ipv6.h
|
|
+++ /dev/null
|
|
@@ -1,332 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- * Based on Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ipv6.h - This file contains macro definitions pertaining to IPv6.
|
|
- *
|
|
- * RFC 2460 : IPv6 Specification.
|
|
- * RFC 2373 : IPv6 Addressing Architecture.
|
|
- * RFC 2462 : IPv6 Stateless Address Autoconfiguration.
|
|
- * RFC 2464 : Transmission of IPv6 Packets over Ethernet Networks.
|
|
- *
|
|
- */
|
|
-#ifndef __IPV6_H__
|
|
-#define __IPV6_H__
|
|
-
|
|
-#include "ipv6_ndpc.h"
|
|
-
|
|
-#define FALSE 0
|
|
-#define TRUE 1
|
|
-
|
|
-#define LINK_LOCAL_PREFIX_LENGTH 2
|
|
-#define LAYER2_HEADER_LENGTH 14
|
|
-#define LAYER2_VLAN_HEADER_LENGTH 16
|
|
-#define LAYER2_TYPE_IPV6 0x86dd
|
|
-
|
|
-struct ipv6_addr {
|
|
- union {
|
|
- u8_t addr8[16];
|
|
- u16_t addr16[8];
|
|
- u32_t addr[4];
|
|
- };
|
|
-};
|
|
-
|
|
-struct udp_hdr {
|
|
- u16_t src_port;
|
|
- u16_t dest_port;
|
|
- u16_t length;
|
|
- u16_t chksum;
|
|
-};
|
|
-
|
|
-struct mac_address {
|
|
- union {
|
|
- u8_t addr[6];
|
|
- struct {
|
|
- u16_t first_2_bytes;
|
|
- u32_t last_4_bytes;
|
|
- } __attribute__ ((packed));
|
|
- };
|
|
-};
|
|
-
|
|
-#define HOST_TO_NET16(a) htons(a)
|
|
-#define HOST_TO_NET32(a) htonl(a)
|
|
-#define NET_TO_HOST16(a) ntohs(a)
|
|
-/*
|
|
- * Local definition for masks
|
|
- */
|
|
-#define IPV6_MASK0 { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } }
|
|
-#define IPV6_MASK32 { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
|
|
-#define IPV6_MASK64 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
|
|
-#define IPV6_MASK96 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
|
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }
|
|
-#define IPV6_MASK128 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
|
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }
|
|
-
|
|
-#ifdef BIG_ENDIAN
|
|
-#define IPV6_ADDR_INT32_ONE 1
|
|
-#define IPV6_ADDR_INT32_TWO 2
|
|
-#define IPV6_ADDR_INT32_MNL 0xff010000
|
|
-#define IPV6_ADDR_INT32_MLL 0xff020000
|
|
-#define IPV6_ADDR_INT32_SMP 0x0000ffff
|
|
-#define IPV6_ADDR_INT16_ULL 0xfe80
|
|
-#define IPV6_ADDR_INT16_USL 0xfec0
|
|
-#define IPV6_ADDR_INT16_MLL 0xff02
|
|
-#else /* LITTE ENDIAN */
|
|
-#define IPV6_ADDR_INT32_ONE 0x01000000
|
|
-#define IPV6_ADDR_INT32_TWO 0x02000000
|
|
-#define IPV6_ADDR_INT32_MNL 0x000001ff
|
|
-#define IPV6_ADDR_INT32_MLL 0x000002ff
|
|
-#define IPV6_ADDR_INT32_SMP 0xffff0000
|
|
-#define IPV6_ADDR_INT16_ULL 0x80fe
|
|
-#define IPV6_ADDR_INT16_USL 0xc0fe
|
|
-#define IPV6_ADDR_INT16_MLL 0x02ff
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * Definition of some useful macros to handle IP6 addresses
|
|
- */
|
|
-#define IPV6_ADDR_ANY_INIT \
|
|
- { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
|
|
-#define IPV6_ADDR_LOOPBACK_INIT \
|
|
- { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
|
|
-#define IPV6_ADDR_NODELOCAL_ALLNODES_INIT \
|
|
- { { { 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
|
|
-#define IPV6_ADDR_INTFACELOCAL_ALLNODES_INIT \
|
|
- { { { 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
|
|
-#define IPV6_ADDR_LINKLOCAL_ALLNODES_INIT \
|
|
- { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
|
|
-#define IPV6_ADDR_LINKLOCAL_ALLROUTERS_INIT \
|
|
- { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
|
|
-
|
|
-#define IPV6_ARE_ADDR_EQUAL(a, b) \
|
|
- (memcmp((char *)a, (char *)b, sizeof(struct ipv6_addr)) == 0)
|
|
-
|
|
-/* Unspecified IPv6 address */
|
|
-#define IPV6_IS_ADDR_UNSPECIFIED(a) \
|
|
- ((((a)->addr[0]) == 0) && \
|
|
- (((a)->addr[1]) == 0) && \
|
|
- (((a)->addr[2]) == 0) && \
|
|
- (((a)->addr[3]) == 0))
|
|
-
|
|
-/* IPv6 Scope Values */
|
|
-#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01 /* Node-local scope */
|
|
-#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 /* Link-local scope */
|
|
-#define IPV6_ADDR_SCOPE_SITELOCAL 0x05 /* Site-local scope */
|
|
-#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* Organization-local scope */
|
|
-#define IPV6_ADDR_SCOPE_GLOBAL 0x0e /* Global scope */
|
|
-
|
|
-/* Link-local Unicast : 10-bits much be 1111111010b --> 0xfe80. */
|
|
-#define IPV6_IS_ADDR_LINKLOCAL(a) \
|
|
- (((a)->addr8[0] == 0xfe) && (((a)->addr8[1] & 0xc0) == 0x80))
|
|
-
|
|
-/* Site-local Unicast : 10-bits much be 1111111011b --> 0xfec0. */
|
|
-#define IPV6_IS_ADDR_SITELOCAL(a) \
|
|
- (((a)->addr8[0] == 0xfe) && (((a)->addr8[1] & 0xc0) == 0xc0))
|
|
-
|
|
-/* Multicast : 10bits much be 11111111b. Next 4 bits is flags | 4-bit scope */
|
|
-#define IPV6_IS_ADDR_MULTICAST(a) ((a)->addr8[0] == 0xff)
|
|
-
|
|
-#define IPV6_ADDR_MC_SCOPE(a) ((a)->addr8[1] & 0x0f)
|
|
-
|
|
-/* Multicast Scope */
|
|
-
|
|
-struct eth_hdr {
|
|
- struct mac_address dest_mac;
|
|
- struct mac_address src_mac;
|
|
- u16_t len_type;
|
|
-};
|
|
-
|
|
-struct ipv6_hdr {
|
|
- union {
|
|
- struct {
|
|
- u32_t ipv6_flow; /* Version (4-bit) |
|
|
- Traffic Class (8-bit) |
|
|
- Flow ID (20-bit) */
|
|
- u16_t ipv6_plen; /* Payload length */
|
|
- u8_t ipv6_nxt_hdr; /* Next Header */
|
|
- u8_t ipv6_hop_limit; /* hop limit */
|
|
- } ipv6_dw1;
|
|
-
|
|
- u8_t ipv6_version_fc; /* 4 bits version, top 4 bits class */
|
|
- } ipv6_ctrl;
|
|
-
|
|
- struct ipv6_addr ipv6_src; /* Source address */
|
|
- struct ipv6_addr ipv6_dst; /* Destination address */
|
|
-};
|
|
-
|
|
-#define ipv6_version_fc ipv6_ctrl.ipv6_version_fc
|
|
-#define ipv6_flow ipv6_ctrl.ipv6_dw1.ipv6_flow
|
|
-#define ipv6_plen ipv6_ctrl.ipv6_dw1.ipv6_plen
|
|
-#define ipv6_nxt_hdr ipv6_ctrl.ipv6_dw1.ipv6_nxt_hdr
|
|
-#define ipv6_hop_limit ipv6_ctrl.ipv6_dw1.ipv6_hop_limit
|
|
-
|
|
-#define IPV6_VERSION 0x60
|
|
-#define IPV6_VERSION_MASK 0xf0
|
|
-#define IPV6_HOP_LIMIT 64
|
|
-
|
|
-/* Length of the IP header with no next header */
|
|
-#define IPV6_HEADER_LEN sizeof(struct ipv6_hdr)
|
|
-
|
|
-#ifdef BIG_ENDIAN
|
|
-#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */
|
|
-#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */
|
|
-#else /* LITTLE_ENDIAN */
|
|
-#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */
|
|
-#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
|
|
-#endif
|
|
-
|
|
-struct packet_ipv6 {
|
|
- struct mac_address dest_mac;
|
|
- struct mac_address src_mac;
|
|
- u16_t len_type;
|
|
- struct ipv6_hdr ipv6;
|
|
- union {
|
|
- struct udp_hdr udp;
|
|
- } layer4_prot;
|
|
-};
|
|
-
|
|
-struct packet_ipv6_vlan {
|
|
- struct mac_address dest_mac;
|
|
- struct mac_address src_mac;
|
|
- u16_t len_type;
|
|
- u16_t vlan_id;
|
|
- struct ipv6_hdr ipv6;
|
|
- union {
|
|
- struct udp_hdr udp;
|
|
- } layer4_prot;
|
|
-};
|
|
-
|
|
-struct ipv6_arp_entry {
|
|
- struct ipv6_addr ip_addr;
|
|
- struct mac_address mac_addr;
|
|
- u8_t time;
|
|
-};
|
|
-
|
|
-#define IPV6_NUM_OF_ADDRESS_ENTRY 4
|
|
-
|
|
-struct ipv6_prefix_entry {
|
|
- struct ipv6_prefix_entry *next;
|
|
- struct ipv6_addr ip_addr;
|
|
- u8_t prefix_len;
|
|
-};
|
|
-
|
|
-struct ipv6_addr_entry {
|
|
- struct ipv6_addr ip_addr;
|
|
- u8_t prefix_len;
|
|
-};
|
|
-
|
|
-struct ipv6_context {
|
|
- u16_t flags;
|
|
-#define IPV6_FLAGS_MANAGED_ADDR_CONFIG (1 << 0)
|
|
-#define IPV6_FLAGS_OTHER_STATEFUL_CONFIG (1 << 1)
|
|
-#define IPV6_FLAGS_ROUTER_ADV_RECEIVED (1 << 2)
|
|
-#define IPV6_FLAGS_DISABLE_DHCPV6 (1 << 3)
|
|
-
|
|
- struct mac_address mac_addr;
|
|
- struct ipv6_addr link_local_addr;
|
|
- struct ipv6_addr link_local_multi;
|
|
- struct ipv6_addr multi; /* For Static IPv6 only */
|
|
- struct ipv6_addr multi_dest; /* For Static IPv6 only */
|
|
- struct ipv6_addr default_router;
|
|
- struct ipv6_prefix_entry *addr_list;
|
|
- u8_t hop_limit;
|
|
-#define UIP_ARPTAB_SIZE 16
|
|
-
|
|
- struct uip_stack *ustack;
|
|
-#define MAX_MCADDR_TABLE 5
|
|
- struct mac_address mc_addr[MAX_MCADDR_TABLE];
|
|
- u8_t arptime;
|
|
- struct ipv6_arp_entry ipv6_arp_table[UIP_ARPTAB_SIZE];
|
|
- struct ipv6_prefix_entry ipv6_prefix_table[IPV6_NUM_OF_ADDRESS_ENTRY];
|
|
-
|
|
- /* VLAN support */
|
|
-
|
|
- void *dhcpv6_context;
|
|
-};
|
|
-
|
|
-#define ISCSI_FLAGS_DHCP_TCPIP_CONFIG (1<<0)
|
|
-#define ISCSI_FLAGS_DHCP_ISCSI_CONFIG (1<<1)
|
|
-
|
|
-#define IPV6_MAX_ROUTER_SOL_DELAY 4
|
|
-#define IPV6_MAX_ROUTER_SOL_RETRY 3
|
|
-
|
|
-#define DHCPV6_CLIENT_PORT 546
|
|
-#define DHCPV6_SERVER_PORT 547
|
|
-
|
|
-/* Function prototype */
|
|
-void ipv6_init(struct ndpc_state *ndp, int cfg);
|
|
-int ipv6_autoconfig(struct ipv6_context *context);
|
|
-int ipv6_discover_address(struct ipv6_context *context);
|
|
-struct ipv6_addr *ipv6_our_address(struct ipv6_context *context);
|
|
-int ipv6_ip_in_arp_table(struct ipv6_context *context,
|
|
- struct ipv6_addr *ipv6_addr,
|
|
- struct mac_address *mac_addr);
|
|
-void ipv6_arp_timer(struct ipv6_context *context);
|
|
-void ipv6_arp_out(struct ipv6_context *context, int *uip_len);
|
|
-int ipv6_add_prefix_entry(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr, u8_t prefix_len);
|
|
-void ipv6_set_ip_params(struct ipv6_context *context,
|
|
- struct ipv6_addr *src_ip, u8_t prefix_len,
|
|
- struct ipv6_addr *default_gateway,
|
|
- struct ipv6_addr *linklocal);
|
|
-void ipv6_set_host_addr(struct ipv6_context *context, struct ipv6_addr *src_ip);
|
|
-int ipv6_get_default_router_ip_addrs(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-struct mac_address *ipv6_get_link_addr(struct ipv6_context *context);
|
|
-u16_t ipv6_do_stateful_dhcpv6(struct ipv6_context *context, u32_t flags);
|
|
-void ipv6_add_solit_node_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-int ipv6_get_source_ip_addrs(struct ipv6_context *context,
|
|
- struct ipv6_addr_entry *addr_list);
|
|
-void ipv6_cfg_link_local_addr(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-void ipv6_disable_dhcpv6(struct ipv6_context *context);
|
|
-int ipv6_send_nd_solicited_packet(struct ipv6_context *context,
|
|
- struct eth_hdr *eth, struct ipv6_hdr *ipv6);
|
|
-int ipv6_is_it_our_link_local_address(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-void ipv6_mc_init_dest_mac(struct eth_hdr *eth, struct ipv6_hdr *ipv6);
|
|
-struct ipv6_addr *ipv6_find_longest_match(struct ipv6_context *context,
|
|
- struct ipv6_addr *ip_addr);
|
|
-
|
|
-#endif /* __IPV6_H__ */
|
|
diff --git a/iscsiuio/src/uip/ipv6_ndpc.c b/iscsiuio/src/uip/ipv6_ndpc.c
|
|
deleted file mode 100644
|
|
index bb07c1d..0000000
|
|
--- a/iscsiuio/src/uip/ipv6_ndpc.c
|
|
+++ /dev/null
|
|
@@ -1,432 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- * Based on the Swedish Institute of Computer Science's
|
|
- * dhcpc.c code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ipv6_ndpc.c - Top level IPv6 Network Discovery Protocol Engine (RFC4861)
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <stdlib.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-#include "uip.h"
|
|
-#include "ipv6_ndpc.h"
|
|
-#include "timer.h"
|
|
-#include "pt.h"
|
|
-
|
|
-#include "debug.h"
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "ipv6.h"
|
|
-#include "ipv6_pkt.h"
|
|
-#include "dhcpv6.h"
|
|
-
|
|
-const int dhcpv6_retry_timeout[DHCPV6_NUM_OF_RETRY] = { 1, 2, 4, 8 };
|
|
-
|
|
-static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
|
|
-{
|
|
- struct ndpc_state *s;
|
|
- struct ipv6_context *ipv6c;
|
|
- struct dhcpv6_context *dhcpv6c = NULL;
|
|
- u16_t task = 0;
|
|
- char buf[INET6_ADDRSTRLEN];
|
|
-
|
|
- s = ustack->ndpc;
|
|
- if (s == NULL) {
|
|
- LOG_DEBUG("NDP: Could not find ndpc state");
|
|
- return PT_ENDED;
|
|
- }
|
|
-
|
|
- ipv6c = s->ipv6_context;
|
|
- if (!ipv6c)
|
|
- goto ndpc_state_null;
|
|
-
|
|
- dhcpv6c = s->dhcpv6_context;
|
|
-
|
|
- PT_BEGIN(&s->pt);
|
|
-
|
|
- if (s->state == NDPC_STATE_BACKGROUND_LOOP)
|
|
- goto ipv6_loop;
|
|
-
|
|
- if (s->state == NDPC_STATE_RTR_ADV)
|
|
- goto rtr_adv;
|
|
-
|
|
- /* For AUTOCFG == DHCPv6, do all
|
|
- For == ND, skip DHCP only and do RTR
|
|
- For == UNUSED/UNSPEC, do all as according to DHCP or not */
|
|
- s->state = NDPC_STATE_RTR_SOL;
|
|
- /* try_again: */
|
|
- s->ticks = CLOCK_SECOND * IPV6_MAX_ROUTER_SOL_DELAY;
|
|
- s->retry_count = 0;
|
|
- do {
|
|
- /* Perform router solicitation and wait for
|
|
- router advertisement */
|
|
- LOG_DEBUG("%s: ndpc_handle send rtr sol", s->nic->log_name);
|
|
- ipv6_autoconfig(s->ipv6_context);
|
|
-
|
|
- timer_set(&s->timer, s->ticks);
|
|
-wait_rtr:
|
|
- s->ustack->uip_flags &= ~UIP_NEWDATA;
|
|
- LOG_DEBUG("%s: ndpc_handle wait for rtr adv flags=0x%x",
|
|
- s->nic->log_name, ipv6c->flags);
|
|
- PT_WAIT_UNTIL(&s->pt, uip_newdata(s->ustack)
|
|
- || timer_expired(&s->timer) || force);
|
|
-
|
|
- if (uip_newdata(s->ustack)) {
|
|
- /* Validate incoming packets
|
|
- Note that the uip_len is init from nic loop */
|
|
- ipv6_rx_packet(ipv6c, (u16_t) uip_datalen(s->ustack));
|
|
- if (ipv6c->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED) {
|
|
- LOG_INFO("%s: ROUTER_ADV_RECEIVED",
|
|
- s->nic->log_name);
|
|
- /* Success */
|
|
- break;
|
|
- } else if (!timer_expired(&s->timer)) {
|
|
- /* Yes new data, but not what we want,
|
|
- check for timer expiration before bumping
|
|
- tick */
|
|
- goto wait_rtr;
|
|
- }
|
|
- }
|
|
- s->retry_count++;
|
|
- if (s->retry_count >= IPV6_MAX_ROUTER_SOL_RETRY)
|
|
- /* Max router solicitation retry reached. Move to
|
|
- IPv6 loop (no DHCPv6) */
|
|
- goto no_rtr_adv;
|
|
-
|
|
- } while (!(ipv6c->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED));
|
|
-
|
|
- LOG_DEBUG("%s: ndpc_handle got rtr adv", s->nic->log_name);
|
|
- s->retry_count = 0;
|
|
-
|
|
-no_rtr_adv:
|
|
- s->state = NDPC_STATE_RTR_ADV;
|
|
-
|
|
-rtr_adv:
|
|
- if (!(ustack->ip_config & IPV6_CONFIG_DHCP))
|
|
- goto staticv6;
|
|
-
|
|
- /* Only DHCPv6 comes here */
|
|
- task = ipv6_do_stateful_dhcpv6(ipv6c, ISCSI_FLAGS_DHCP_TCPIP_CONFIG);
|
|
- if (task) {
|
|
- /* Run the DHCPv6 engine */
|
|
-
|
|
- if (!dhcpv6c)
|
|
- goto ipv6_loop;
|
|
-
|
|
- dhcpv6c->dhcpv6_task = task;
|
|
- s->retry_count = 0;
|
|
- s->state = NDPC_STATE_DHCPV6_DIS;
|
|
- do {
|
|
- /* Do dhcpv6 */
|
|
- dhcpv6c->timeout = dhcpv6_retry_timeout[s->retry_count];
|
|
- s->ticks = CLOCK_SECOND * dhcpv6c->timeout;
|
|
- LOG_DEBUG("%s: ndpc_handle send dhcpv6 sol retry "
|
|
- "cnt=%d", s->nic->log_name, s->retry_count);
|
|
- dhcpv6_do_discovery(dhcpv6c);
|
|
-
|
|
- timer_set(&s->timer, s->ticks);
|
|
-wait_dhcp:
|
|
- s->ustack->uip_flags &= ~UIP_NEWDATA;
|
|
- PT_WAIT_UNTIL(&s->pt, uip_newdata(s->ustack)
|
|
- || timer_expired(&s->timer) || force);
|
|
-
|
|
- if (uip_newdata(s->ustack)) {
|
|
- /* Validate incoming packets
|
|
- Note that the uip_len is init from nic
|
|
- loop */
|
|
- ipv6_rx_packet(ipv6c,
|
|
- (u16_t) uip_datalen(s->ustack));
|
|
- if (dhcpv6c->dhcpv6_done == TRUE)
|
|
- break;
|
|
- else if (!timer_expired(&s->timer)) {
|
|
- /* Yes new data, but not what we want,
|
|
- check for timer expiration before
|
|
- bumping tick */
|
|
- goto wait_dhcp;
|
|
- }
|
|
- }
|
|
- s->retry_count++;
|
|
- if (s->retry_count < DHCPV6_NUM_OF_RETRY) {
|
|
- dhcpv6c->seconds += dhcpv6c->timeout;
|
|
- } else {
|
|
- LOG_DEBUG("%s: ndpc_handle DHCP failed",
|
|
- s->nic->log_name);
|
|
- /* Allow to goto background loop */
|
|
- goto ipv6_loop;
|
|
- }
|
|
- } while (dhcpv6c->dhcpv6_done == FALSE);
|
|
- s->state = NDPC_STATE_DHCPV6_DONE;
|
|
-
|
|
- LOG_DEBUG("%s: ndpc_handle got dhcpv6", s->nic->log_name);
|
|
-
|
|
- /* End of DHCPv6 engine */
|
|
- } else {
|
|
- /* Static IPv6 */
|
|
- if (ustack->ip_config == IPV6_CONFIG_DHCP) {
|
|
- s->retry_count++;
|
|
- if (s->retry_count > DHCPV6_NUM_OF_RETRY) {
|
|
- LOG_DEBUG("%s: ndpc_handle DHCP failed",
|
|
- s->nic->log_name);
|
|
- } else {
|
|
- PT_RESTART(&s->pt);
|
|
- }
|
|
- }
|
|
-staticv6:
|
|
- ipv6_disable_dhcpv6(ipv6c);
|
|
- }
|
|
- /* Copy out the default_router_addr6 and ll */
|
|
- if (ustack->router_autocfg != IPV6_RTR_AUTOCFG_OFF)
|
|
- memcpy(&ustack->default_route_addr6,
|
|
- &ipv6c->default_router, sizeof(struct ipv6_addr));
|
|
- inet_ntop(AF_INET6, &ustack->default_route_addr6,
|
|
- buf, sizeof(buf));
|
|
- LOG_INFO("%s: Default router IP: %s", s->nic->log_name,
|
|
- buf);
|
|
-
|
|
- if (ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF)
|
|
- memcpy(&ustack->linklocal6, &ipv6c->link_local_addr,
|
|
- sizeof(struct ipv6_addr));
|
|
- inet_ntop(AF_INET6, &ustack->linklocal6,
|
|
- buf, sizeof(buf));
|
|
- LOG_INFO("%s: Linklocal IP: %s", s->nic->log_name,
|
|
- buf);
|
|
-
|
|
-ipv6_loop:
|
|
- s->state = NDPC_STATE_BACKGROUND_LOOP;
|
|
- LOG_DEBUG("%s: Loop", s->nic->log_name);
|
|
- /* Background IPv6 loop */
|
|
- while (1) {
|
|
- /* Handle all neightbor solicitation/advertisement here */
|
|
- s->ustack->uip_flags &= ~UIP_NEWDATA;
|
|
- PT_WAIT_UNTIL(&s->pt, uip_newdata(s->ustack));
|
|
-
|
|
- /* Validate incoming packets */
|
|
- ipv6_rx_packet(ipv6c, (u16_t) uip_datalen(s->ustack));
|
|
- }
|
|
-
|
|
-ndpc_state_null:
|
|
-
|
|
- while (1)
|
|
- PT_YIELD(&s->pt);
|
|
-
|
|
- PT_END(&(s->pt));
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-int ndpc_init(nic_t *nic, struct uip_stack *ustack,
|
|
- const void *mac_addr, int mac_len)
|
|
-{
|
|
- struct ipv6_context *ipv6c;
|
|
- struct dhcpv6_context *dhcpv6c;
|
|
- struct ndpc_state *s = ustack->ndpc;
|
|
- struct ipv6_addr src, gw, ll;
|
|
- char buf[INET6_ADDRSTRLEN];
|
|
-
|
|
- if (s) {
|
|
- LOG_DEBUG("NDP: NDP context already allocated");
|
|
- /* Already allocated, skip*/
|
|
- return -EALREADY;
|
|
- }
|
|
- s = malloc(sizeof(*s));
|
|
- if (s == NULL) {
|
|
- LOG_ERR("%s: Couldn't allocate size for ndpc info",
|
|
- nic->log_name);
|
|
- goto error;
|
|
- }
|
|
- memset(s, 0, sizeof(*s));
|
|
-
|
|
- if (s->ipv6_context) {
|
|
- LOG_DEBUG("NDP: IPv6 context already allocated");
|
|
- ipv6c = s->ipv6_context;
|
|
- goto init1;
|
|
- }
|
|
- ipv6c = malloc(sizeof(struct ipv6_context));
|
|
- if (ipv6c == NULL) {
|
|
- LOG_ERR("%s: Couldn't allocate mem for IPv6 context info",
|
|
- nic->log_name);
|
|
- goto error1;
|
|
- }
|
|
-init1:
|
|
- if (s->dhcpv6_context) {
|
|
- LOG_DEBUG("NDP: DHCPv6 context already allocated");
|
|
- dhcpv6c = s->dhcpv6_context;
|
|
- goto init2;
|
|
- }
|
|
- dhcpv6c = malloc(sizeof(struct dhcpv6_context));
|
|
- if (dhcpv6c == NULL) {
|
|
- LOG_ERR("%s: Couldn't allocate mem for DHCPv6 context info",
|
|
- nic->log_name);
|
|
- goto error2;
|
|
- }
|
|
-init2:
|
|
- memset(s, 0, sizeof(*s));
|
|
- memset(ipv6c, 0, sizeof(*ipv6c));
|
|
- memset(dhcpv6c, 0, sizeof(*dhcpv6c));
|
|
-
|
|
- s->ipv6_context = ipv6c;
|
|
- s->dhcpv6_context = dhcpv6c;
|
|
-
|
|
- s->nic = nic;
|
|
- s->ustack = ustack;
|
|
- s->mac_addr = (void *)mac_addr;
|
|
- s->mac_len = mac_len;
|
|
- s->state = NDPC_STATE_INIT;
|
|
-
|
|
- /* Init IPV6_CONTEXT */
|
|
- ipv6_init(s, ustack->ip_config);
|
|
-
|
|
- dhcpv6c->ipv6_context = ipv6c;
|
|
- ipv6c->dhcpv6_context = dhcpv6c;
|
|
-
|
|
- /* Init DHCPV6_CONTEXT */
|
|
- dhcpv6_init(dhcpv6c);
|
|
-
|
|
- ustack->ndpc = s;
|
|
-
|
|
- PT_INIT(&s->pt);
|
|
-
|
|
- if (ustack->ip_config == IPV6_CONFIG_DHCP) {
|
|
- /* DHCPv6 specific */
|
|
- memset(&src, 0, sizeof(src));
|
|
- } else {
|
|
- /* Static v6 specific */
|
|
- memcpy(&src.addr8, &ustack->hostaddr6,
|
|
- sizeof(struct ipv6_addr));
|
|
- ipv6_add_solit_node_address(ipv6c, &src);
|
|
-
|
|
- inet_ntop(AF_INET6, &src.addr8, buf, sizeof(buf));
|
|
- LOG_INFO("%s: Static hostaddr IP: %s", s->nic->log_name,
|
|
- buf);
|
|
- }
|
|
- /* Copy out the default_router_addr6 and ll */
|
|
- if (ustack->router_autocfg == IPV6_RTR_AUTOCFG_OFF)
|
|
- memcpy(&gw.addr8, &ustack->default_route_addr6,
|
|
- sizeof(struct ipv6_addr));
|
|
- else
|
|
- memset(&gw, 0, sizeof(gw));
|
|
-
|
|
- if (ustack->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
|
|
- memcpy(&ll.addr8, &ustack->linklocal6,
|
|
- sizeof(struct ipv6_addr));
|
|
- else
|
|
- memset(&ll, 0, sizeof(ll));
|
|
- ipv6_set_ip_params(ipv6c, &src,
|
|
- ustack->prefix_len, &gw, &ll);
|
|
-
|
|
- return 0;
|
|
-error2:
|
|
- free(ipv6c);
|
|
- s->ipv6_context = NULL;
|
|
-error1:
|
|
- free(s);
|
|
- ustack->ndpc = NULL;
|
|
-error:
|
|
- return -ENOMEM;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void ndpc_call(struct uip_stack *ustack)
|
|
-{
|
|
- handle_ndp(ustack, 0);
|
|
-}
|
|
-
|
|
-void ndpc_exit(struct ndpc_state *ndp)
|
|
-{
|
|
- LOG_DEBUG("NDP - Exit ndpc_state = %p", ndp);
|
|
- if (!ndp)
|
|
- return;
|
|
- if (ndp->ipv6_context)
|
|
- free(ndp->ipv6_context);
|
|
- if (ndp->dhcpv6_context)
|
|
- free(ndp->dhcpv6_context);
|
|
- free(ndp);
|
|
-}
|
|
-
|
|
-int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
|
|
-{
|
|
- struct ndpc_state *s;
|
|
- struct ipv6_context *ipv6c;
|
|
- int ret = 0;
|
|
-
|
|
- if (!ustack) {
|
|
- LOG_DEBUG("NDP: ustack == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
- s = ustack->ndpc;
|
|
- if (s == NULL) {
|
|
- LOG_DEBUG("NDP: Could not find ndpc state for request %d",
|
|
- request);
|
|
- return -EINVAL;
|
|
- }
|
|
- while (s->state != NDPC_STATE_BACKGROUND_LOOP) {
|
|
- LOG_DEBUG("%s: ndpc state not in background loop, run handler "
|
|
- "request = %d", s->nic->log_name, request);
|
|
- handle_ndp(ustack, 1);
|
|
- }
|
|
-
|
|
- ipv6c = s->ipv6_context;
|
|
- switch (request) {
|
|
- case NEIGHBOR_SOLICIT:
|
|
- *(int *)out = ipv6_send_nd_solicited_packet(ipv6c,
|
|
- (struct eth_hdr *)((struct ndpc_reqptr *)in)->eth,
|
|
- (struct ipv6_hdr *)((struct ndpc_reqptr *)in)->ipv6);
|
|
- break;
|
|
- case CHECK_LINK_LOCAL_ADDR:
|
|
- *(int *)out = ipv6_is_it_our_link_local_address(ipv6c,
|
|
- (struct ipv6_addr *)in);
|
|
- break;
|
|
- case CHECK_ARP_TABLE:
|
|
- *(int *)out = ipv6_ip_in_arp_table(ipv6c,
|
|
- (struct ipv6_addr *)((struct ndpc_reqptr *)in)->ipv6,
|
|
- (struct mac_address *)((struct ndpc_reqptr *)in)->eth);
|
|
- break;
|
|
- case GET_HOST_ADDR:
|
|
- *(struct ipv6_addr **)out = ipv6_find_longest_match(ipv6c,
|
|
- (struct ipv6_addr *)in);
|
|
- break;
|
|
- default:
|
|
- ret = -EINVAL;
|
|
- break;
|
|
- }
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
diff --git a/iscsiuio/src/uip/ipv6_ndpc.h b/iscsiuio/src/uip/ipv6_ndpc.h
|
|
deleted file mode 100644
|
|
index 709a050..0000000
|
|
--- a/iscsiuio/src/uip/ipv6_ndpc.h
|
|
+++ /dev/null
|
|
@@ -1,98 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ipv6_ndpc.h - Top level IPv6 Network Discovery Protocol Engine (RFC4861)
|
|
- *
|
|
- */
|
|
-#ifndef __NDPC_H__
|
|
-#define __NDPC_H__
|
|
-
|
|
-#include <time.h>
|
|
-
|
|
-#include "nic.h"
|
|
-#include "timer.h"
|
|
-#include "pt.h"
|
|
-
|
|
-struct ndpc_reqptr {
|
|
- void *eth;
|
|
- void *ipv6;
|
|
-};
|
|
-
|
|
-struct ndpc_state {
|
|
- struct pt pt;
|
|
-
|
|
- nic_t *nic;
|
|
- struct uip_stack *ustack;
|
|
- char state;
|
|
- struct timer timer;
|
|
- u16_t ticks;
|
|
- void *mac_addr;
|
|
- int mac_len;
|
|
- int retry_count;
|
|
-
|
|
- time_t last_update;
|
|
-
|
|
- void *ipv6_context;
|
|
- void *dhcpv6_context;
|
|
-};
|
|
-
|
|
-enum {
|
|
- NDPC_STATE_INIT,
|
|
- NDPC_STATE_RTR_SOL,
|
|
- NDPC_STATE_RTR_ADV,
|
|
- NDPC_STATE_DHCPV6_DIS,
|
|
- NDPC_STATE_DHCPV6_DONE,
|
|
- NDPC_STATE_BACKGROUND_LOOP
|
|
-};
|
|
-
|
|
-int ndpc_init(nic_t *nic, struct uip_stack *ustack,
|
|
- const void *mac_addr, int mac_len);
|
|
-void ndpc_call(struct uip_stack *ustack);
|
|
-void ndpc_exit(struct ndpc_state *ndp);
|
|
-
|
|
-enum {
|
|
- NEIGHBOR_SOLICIT,
|
|
- CHECK_LINK_LOCAL_ADDR,
|
|
- GET_LINK_LOCAL_ADDR,
|
|
- GET_DEFAULT_ROUTER_ADDR,
|
|
- CHECK_ARP_TABLE,
|
|
- GET_HOST_ADDR
|
|
-};
|
|
-
|
|
-int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request);
|
|
-
|
|
-#define UIP_NDP_CALL ndpc_call
|
|
-
|
|
-#endif /* __NDPC_H__ */
|
|
diff --git a/iscsiuio/src/uip/ipv6_pkt.h b/iscsiuio/src/uip/ipv6_pkt.h
|
|
deleted file mode 100644
|
|
index b42f1aa..0000000
|
|
--- a/iscsiuio/src/uip/ipv6_pkt.h
|
|
+++ /dev/null
|
|
@@ -1,50 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Eddie Wai (eddie.wai@broadcom.com)
|
|
- * Based on Kevin Tran's iSCSI boot code
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ipv6_packet.h - IPv6 routine include file
|
|
- *
|
|
- */
|
|
-#ifndef __IPV6_PKT_H__
|
|
-#define __IPV6_PKT_H__
|
|
-
|
|
-u16_t ipv6_process_rx(struct ipv6_hdr *ipv6);
|
|
-void ipv6_rx_packet(struct ipv6_context *context, u16_t len);
|
|
-void ipv6_setup_hdrs(struct ipv6_context *context, struct eth_hdr *eth,
|
|
- struct ipv6_hdr *ipv6, u16_t packet_len);
|
|
-int ipv6_send(struct ipv6_context *context, u16_t packet_len);
|
|
-void ipv6_send_udp_packet(struct ipv6_context *context, u16_t packet_len);
|
|
-
|
|
-#endif /* __IPV6_PKT_H__ */
|
|
diff --git a/iscsiuio/src/uip/lc-addrlabels.h b/iscsiuio/src/uip/lc-addrlabels.h
|
|
deleted file mode 100644
|
|
index c394b22..0000000
|
|
--- a/iscsiuio/src/uip/lc-addrlabels.h
|
|
+++ /dev/null
|
|
@@ -1,80 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \addtogroup lc
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Implementation of local continuations based on the "Labels as
|
|
- * values" feature of gcc
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- * This implementation of local continuations is based on a special
|
|
- * feature of the GCC C compiler called "labels as values". This
|
|
- * feature allows assigning pointers with the address of the code
|
|
- * corresponding to a particular C label.
|
|
- *
|
|
- * For more information, see the GCC documentation:
|
|
- * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
|
|
- *
|
|
- * Thanks to dividuum for finding the nice local scope label
|
|
- * implementation.
|
|
- */
|
|
-
|
|
-#ifndef __LC_ADDRLABELS_H__
|
|
-#define __LC_ADDRLABELS_H__
|
|
-
|
|
-/** \hideinitializer */
|
|
-
|
|
-#define LC_INIT(s) (s = NULL)
|
|
-
|
|
-#define LC_RESUME(s) \
|
|
- do { \
|
|
- if (s != NULL) { \
|
|
- goto *s; \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-#define LC_SET(s) \
|
|
- do { ({ __label__ resume; resume: (s) = &&resume; }); } while (0)
|
|
-
|
|
-#define LC_END(s)
|
|
-
|
|
-#endif /* __LC_ADDRLABELS_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/lc-switch.h b/iscsiuio/src/uip/lc-switch.h
|
|
deleted file mode 100644
|
|
index 1839b36..0000000
|
|
--- a/iscsiuio/src/uip/lc-switch.h
|
|
+++ /dev/null
|
|
@@ -1,73 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \addtogroup lc
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Implementation of local continuations based on switch() statment
|
|
- * \author Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- * This implementation of local continuations uses the C switch()
|
|
- * statement to resume execution of a function somewhere inside the
|
|
- * function's body. The implementation is based on the fact that
|
|
- * switch() statements are able to jump directly into the bodies of
|
|
- * control structures such as if() or while() statmenets.
|
|
- *
|
|
- * This implementation borrows heavily from Simon Tatham's coroutines
|
|
- * implementation in C:
|
|
- * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
|
|
- */
|
|
-
|
|
-#ifndef __LC_SWITCH_H__
|
|
-#define __LC_SWTICH_H__
|
|
-
|
|
-/* WARNING! lc implementation using switch() does not work if an
|
|
- LC_SET() is done within another switch() statement! */
|
|
-
|
|
-/** \hideinitializer */
|
|
-#define LC_INIT(s) s = 0;
|
|
-
|
|
-#define LC_RESUME(s) switch (s) { case 0:
|
|
-
|
|
-#define LC_SET(s) s = __LINE__; case __LINE__:
|
|
-
|
|
-#define LC_END(s) }
|
|
-
|
|
-#endif /* __LC_SWITCH_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/lc.h b/iscsiuio/src/uip/lc.h
|
|
deleted file mode 100644
|
|
index 2e4a7bb..0000000
|
|
--- a/iscsiuio/src/uip/lc.h
|
|
+++ /dev/null
|
|
@@ -1,130 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \addtogroup pt
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \defgroup lc Local continuations
|
|
- * @{
|
|
- *
|
|
- * Local continuations form the basis for implementing protothreads. A
|
|
- * local continuation can be <i>set</i> in a specific function to
|
|
- * capture the state of the function. After a local continuation has
|
|
- * been set can be <i>resumed</i> in order to restore the state of the
|
|
- * function at the point where the local continuation was set.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file lc.h
|
|
- * Local continuations
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-#ifdef DOXYGEN
|
|
-/**
|
|
- * Initialize a local continuation.
|
|
- *
|
|
- * This operation initializes the local continuation, thereby
|
|
- * unsetting any previously set continuation state.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define LC_INIT(lc)
|
|
-
|
|
-/**
|
|
- * Set a local continuation.
|
|
- *
|
|
- * The set operation saves the state of the function at the point
|
|
- * where the operation is executed. As far as the set operation is
|
|
- * concerned, the state of the function does <b>not</b> include the
|
|
- * call-stack or local (automatic) variables, but only the program
|
|
- * counter and such CPU registers that needs to be saved.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define LC_SET(lc)
|
|
-
|
|
-/**
|
|
- * Resume a local continuation.
|
|
- *
|
|
- * The resume operation resumes a previously set local continuation, thus
|
|
- * restoring the state in which the function was when the local
|
|
- * continuation was set. If the local continuation has not been
|
|
- * previously set, the resume operation does nothing.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define LC_RESUME(lc)
|
|
-
|
|
-/**
|
|
- * Mark the end of local continuation usage.
|
|
- *
|
|
- * The end operation signifies that local continuations should not be
|
|
- * used any more in the function. This operation is not needed for
|
|
- * most implementations of local continuation, but is required by a
|
|
- * few implementations.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define LC_END(lc)
|
|
-
|
|
-/**
|
|
- * \var typedef lc_t;
|
|
- *
|
|
- * The local continuation type.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#endif /* DOXYGEN */
|
|
-
|
|
-#ifndef __LC_H__
|
|
-#define __LC_H__
|
|
-
|
|
-#ifdef LC_CONF_INCLUDE
|
|
-#include LC_CONF_INCLUDE
|
|
-#else
|
|
-#include "lc-switch.h"
|
|
-#endif /* LC_CONF_INCLUDE */
|
|
-
|
|
-#endif /* __LC_H__ */
|
|
-
|
|
-/** @} */
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/psock.c b/iscsiuio/src/uip/psock.c
|
|
deleted file mode 100644
|
|
index fcffbe7..0000000
|
|
--- a/iscsiuio/src/uip/psock.c
|
|
+++ /dev/null
|
|
@@ -1,339 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-
|
|
-#include "uipopt.h"
|
|
-#include "psock.h"
|
|
-#include "uip.h"
|
|
-
|
|
-#define STATE_NONE 0
|
|
-#define STATE_ACKED 1
|
|
-#define STATE_READ 2
|
|
-#define STATE_BLOCKED_NEWDATA 3
|
|
-#define STATE_BLOCKED_CLOSE 4
|
|
-#define STATE_BLOCKED_SEND 5
|
|
-#define STATE_DATA_SENT 6
|
|
-
|
|
-/*
|
|
- * Return value of the buffering functions that indicates that a
|
|
- * buffer was not filled by incoming data.
|
|
- *
|
|
- */
|
|
-#define BUF_NOT_FULL 0
|
|
-#define BUF_NOT_FOUND 0
|
|
-
|
|
-/*
|
|
- * Return value of the buffering functions that indicates that a
|
|
- * buffer was completely filled by incoming data.
|
|
- *
|
|
- */
|
|
-#define BUF_FULL 1
|
|
-
|
|
-/*
|
|
- * Return value of the buffering functions that indicates that an
|
|
- * end-marker byte was found.
|
|
- *
|
|
- */
|
|
-#define BUF_FOUND 2
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static void buf_setup(struct psock_buf *buf, u8_t *bufptr, u16_t bufsize)
|
|
-{
|
|
- buf->ptr = bufptr;
|
|
- buf->left = bufsize;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t
|
|
-buf_bufdata(struct psock_buf *buf, u16_t len, u8_t **dataptr, u16_t *datalen)
|
|
-{
|
|
- if (*datalen < buf->left) {
|
|
- memcpy(buf->ptr, *dataptr, *datalen);
|
|
- buf->ptr += *datalen;
|
|
- buf->left -= *datalen;
|
|
- *dataptr += *datalen;
|
|
- *datalen = 0;
|
|
- return BUF_NOT_FULL;
|
|
- } else if (*datalen == buf->left) {
|
|
- memcpy(buf->ptr, *dataptr, *datalen);
|
|
- buf->ptr += *datalen;
|
|
- buf->left = 0;
|
|
- *dataptr += *datalen;
|
|
- *datalen = 0;
|
|
- return BUF_FULL;
|
|
- } else {
|
|
- memcpy(buf->ptr, *dataptr, buf->left);
|
|
- buf->ptr += buf->left;
|
|
- *datalen -= buf->left;
|
|
- *dataptr += buf->left;
|
|
- buf->left = 0;
|
|
- return BUF_FULL;
|
|
- }
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u8_t
|
|
-buf_bufto(register struct psock_buf *buf, u8_t endmarker,
|
|
- register u8_t **dataptr, register u16_t *datalen)
|
|
-{
|
|
- u8_t c;
|
|
- while (buf->left > 0 && *datalen > 0) {
|
|
- c = *buf->ptr = **dataptr;
|
|
- ++*dataptr;
|
|
- ++buf->ptr;
|
|
- --*datalen;
|
|
- --buf->left;
|
|
-
|
|
- if (c == endmarker)
|
|
- return BUF_FOUND;
|
|
- }
|
|
-
|
|
- if (*datalen == 0)
|
|
- return BUF_NOT_FOUND;
|
|
-
|
|
- while (*datalen > 0) {
|
|
- c = **dataptr;
|
|
- --*datalen;
|
|
- ++*dataptr;
|
|
-
|
|
- if (c == endmarker)
|
|
- return BUF_FOUND | BUF_FULL;
|
|
- }
|
|
-
|
|
- return BUF_FULL;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static char send_data(register struct psock *s)
|
|
-{
|
|
- if (s->state != STATE_DATA_SENT || uip_rexmit(s->ustack)) {
|
|
- if (s->sendlen > uip_mss(s->ustack))
|
|
- uip_appsend(s->ustack, s->sendptr, uip_mss(s->ustack));
|
|
- else
|
|
- uip_appsend(s->ustack, s->sendptr, s->sendlen);
|
|
- s->state = STATE_DATA_SENT;
|
|
- return 1;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static char data_acked(struct psock *s)
|
|
-{
|
|
- if (s->state == STATE_DATA_SENT && uip_acked(s->ustack)) {
|
|
- if (s->sendlen > uip_mss(s->ustack)) {
|
|
- s->sendlen -= uip_mss(s->ustack);
|
|
- s->sendptr += uip_mss(s->ustack);
|
|
- } else {
|
|
- s->sendptr += s->sendlen;
|
|
- s->sendlen = 0;
|
|
- }
|
|
- s->state = STATE_ACKED;
|
|
- return 1;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-PT_THREAD(psock_send(struct uip_stack *ustack,
|
|
- register struct psock *s, const u8_t *buf,
|
|
- unsigned int len))
|
|
-{
|
|
- PT_BEGIN(&s->psockpt);
|
|
-
|
|
- /* If there is no data to send, we exit immediately. */
|
|
- if (len == 0) {
|
|
- PT_EXIT(&s->psockpt);
|
|
- }
|
|
-
|
|
- /* Save the length of and a pointer to the data that is to be
|
|
- sent. */
|
|
- s->sendptr = buf;
|
|
- s->sendlen = len;
|
|
-
|
|
- s->state = STATE_NONE;
|
|
-
|
|
- /* We loop here until all data is sent. The s->sendlen variable is
|
|
- updated by the data_sent() function. */
|
|
- while (s->sendlen > 0) {
|
|
-
|
|
- /*
|
|
- * The condition for this PT_WAIT_UNTIL is a little tricky: the
|
|
- * protothread will wait here until all data has been acked
|
|
- * (data_acked() returns true) and until all data has been sent
|
|
- * (send_data() returns true). The two functions data_acked()
|
|
- * and send_data() must be called in succession to ensure that
|
|
- * all data is sent. Therefore the & operator is used instead of
|
|
- * the && operator, which would cause only the data_acked()
|
|
- * function to be called when it returns false.
|
|
- */
|
|
- PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
|
|
- }
|
|
-
|
|
- s->state = STATE_NONE;
|
|
-
|
|
- PT_END(&s->psockpt);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-PT_THREAD(psock_generator_send(register struct psock *s,
|
|
- unsigned short (*generate) (void *), void *arg))
|
|
-{
|
|
- PT_BEGIN(&s->psockpt);
|
|
-
|
|
- /* Ensure that there is a generator function to call. */
|
|
- if (generate == NULL) {
|
|
- PT_EXIT(&s->psockpt);
|
|
- }
|
|
-
|
|
- /* Call the generator function to generate the data in the
|
|
- uip_appdata buffer. */
|
|
- s->sendlen = generate(arg);
|
|
- s->sendptr = s->ustack->uip_appdata;
|
|
-
|
|
- s->state = STATE_NONE;
|
|
- do {
|
|
- /* Call the generator function again if we are called to perform
|
|
- a retransmission. */
|
|
- if (uip_rexmit(s->ustack))
|
|
- generate(arg);
|
|
- /* Wait until all data is sent and acknowledged. */
|
|
- PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
|
|
- } while (s->sendlen > 0);
|
|
-
|
|
- s->state = STATE_NONE;
|
|
-
|
|
- PT_END(&s->psockpt);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-u16_t psock_datalen(struct psock *psock)
|
|
-{
|
|
- return psock->bufsize - psock->buf.left;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-char psock_newdata(struct psock *s)
|
|
-{
|
|
- if (s->readlen > 0) {
|
|
- /* There is data in the uip_appdata buffer that has not yet been
|
|
- read with the PSOCK_READ functions. */
|
|
- return 1;
|
|
- } else if (s->state == STATE_READ) {
|
|
- /* All data in uip_appdata buffer already consumed. */
|
|
- s->state = STATE_BLOCKED_NEWDATA;
|
|
- return 0;
|
|
- } else if (uip_newdata(s->ustack)) {
|
|
- /* There is new data that has not been consumed. */
|
|
- return 1;
|
|
- } else {
|
|
- /* There is no new data. */
|
|
- return 0;
|
|
- }
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-PT_THREAD(psock_readto(register struct psock *psock, u8_t c))
|
|
-{
|
|
- PT_BEGIN(&psock->psockpt);
|
|
-
|
|
- buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
|
|
-
|
|
- /* XXX: Should add buf_checkmarker() before do{} loop, if
|
|
- incoming data has been handled while waiting for a write. */
|
|
-
|
|
- do {
|
|
- if (psock->readlen == 0) {
|
|
- PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
|
|
- psock->state = STATE_READ;
|
|
- psock->readptr = (u8_t *) psock->ustack->uip_appdata;
|
|
- psock->readlen = uip_datalen(psock->ustack);
|
|
- }
|
|
- } while ((buf_bufto(&psock->buf, c,
|
|
- &psock->readptr,
|
|
- &psock->readlen) & BUF_FOUND) == 0);
|
|
-
|
|
- if (psock_datalen(psock) == 0) {
|
|
- psock->state = STATE_NONE;
|
|
- PT_RESTART(&psock->psockpt);
|
|
- }
|
|
- PT_END(&psock->psockpt);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-PT_THREAD(psock_readbuf(register struct psock *psock))
|
|
-{
|
|
- PT_BEGIN(&psock->psockpt);
|
|
-
|
|
- buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
|
|
-
|
|
- /* XXX: Should add buf_checkmarker() before do{} loop, if
|
|
- incoming data has been handled while waiting for a write. */
|
|
-
|
|
- do {
|
|
- if (psock->readlen == 0) {
|
|
- PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
|
|
- printf("Waited for newdata\n");
|
|
- psock->state = STATE_READ;
|
|
- psock->readptr = (u8_t *) psock->ustack->uip_appdata;
|
|
- psock->readlen = uip_datalen(psock->ustack);
|
|
- }
|
|
- } while (buf_bufdata(&psock->buf, psock->bufsize,
|
|
- &psock->readptr, &psock->readlen) != BUF_FULL);
|
|
-
|
|
- if (psock_datalen(psock) == 0) {
|
|
- psock->state = STATE_NONE;
|
|
- PT_RESTART(&psock->psockpt);
|
|
- }
|
|
- PT_END(&psock->psockpt);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void
|
|
-psock_init(struct uip_stack *ustack,
|
|
- register struct psock *psock, u8_t *buffer, unsigned int buffersize)
|
|
-{
|
|
- psock->state = STATE_NONE;
|
|
- psock->readlen = 0;
|
|
- psock->bufptr = buffer;
|
|
- psock->bufsize = buffersize;
|
|
- psock->ustack = ustack;
|
|
- buf_setup(&psock->buf, buffer, buffersize);
|
|
- PT_INIT(&psock->pt);
|
|
- PT_INIT(&psock->psockpt);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
diff --git a/iscsiuio/src/uip/psock.h b/iscsiuio/src/uip/psock.h
|
|
deleted file mode 100644
|
|
index ea86ef5..0000000
|
|
--- a/iscsiuio/src/uip/psock.h
|
|
+++ /dev/null
|
|
@@ -1,383 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \defgroup psock Protosockets library
|
|
- * @{
|
|
- *
|
|
- * The protosocket library provides an interface to the uIP stack that is
|
|
- * similar to the traditional BSD socket interface. Unlike programs
|
|
- * written for the ordinary uIP event-driven interface, programs
|
|
- * written with the protosocket library are executed in a sequential
|
|
- * fashion and does not have to be implemented as explicit state
|
|
- * machines.
|
|
- *
|
|
- * Protosockets only work with TCP connections.
|
|
- *
|
|
- * The protosocket library uses \ref pt protothreads to provide
|
|
- * sequential control flow. This makes the protosockets lightweight in
|
|
- * terms of memory, but also means that protosockets inherits the
|
|
- * functional limitations of protothreads. Each protosocket lives only
|
|
- * within a single function. Automatic variables (stack variables) are
|
|
- * not retained across a protosocket library function call.
|
|
- *
|
|
- * \note Because the protosocket library uses protothreads, local
|
|
- * variables will not always be saved across a call to a protosocket
|
|
- * library function. It is therefore advised that local variables are
|
|
- * used with extreme care.
|
|
- *
|
|
- * The protosocket library provides functions for sending data without
|
|
- * having to deal with retransmissions and acknowledgements, as well
|
|
- * as functions for reading data without having to deal with data
|
|
- * being split across more than one TCP segment.
|
|
- *
|
|
- * Because each protosocket runs as a protothread, the protosocket has to be
|
|
- * started with a call to PSOCK_BEGIN() at the start of the function
|
|
- * in which the protosocket is used. Similarly, the protosocket protothread can
|
|
- * be terminated by a call to PSOCK_EXIT().
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Protosocket library header file
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __PSOCK_H__
|
|
-#define __PSOCK_H__
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uipopt.h"
|
|
-#include "pt.h"
|
|
-
|
|
- /*
|
|
- * The structure that holds the state of a buffer.
|
|
- *
|
|
- * This structure holds the state of a uIP buffer. The structure has
|
|
- * no user-visible elements, but is used through the functions
|
|
- * provided by the library.
|
|
- *
|
|
- */
|
|
-struct psock_buf {
|
|
- u8_t *ptr;
|
|
- unsigned short left;
|
|
-};
|
|
-
|
|
-/**
|
|
- * The representation of a protosocket.
|
|
- *
|
|
- * The protosocket structrure is an opaque structure with no user-visible
|
|
- * elements.
|
|
- */
|
|
-struct psock {
|
|
- struct pt pt, psockpt; /* Protothreads - one that's using the psock
|
|
- functions, and one that runs inside the
|
|
- psock functions. */
|
|
- const u8_t *sendptr; /* Pointer to the next data to be sent. */
|
|
- u8_t *readptr; /* Pointer to the next data to be read. */
|
|
-
|
|
- u8_t *bufptr; /* Pointer to the buffer used for buffering
|
|
- incoming data. */
|
|
-
|
|
- u16_t sendlen; /* The number of bytes left to be sent. */
|
|
- u16_t readlen; /* The number of bytes left to be read. */
|
|
-
|
|
- struct psock_buf buf; /* The structure holding the state of the
|
|
- input buffer. */
|
|
- unsigned int bufsize; /* The size of the input buffer. */
|
|
-
|
|
- unsigned char state; /* The state of the protosocket. */
|
|
-
|
|
- struct uip_stack *ustack;
|
|
-};
|
|
-
|
|
-void psock_init(struct uip_stack *ustack,
|
|
- struct psock *psock, u8_t *buffer, unsigned int buffersize);
|
|
-/**
|
|
- * Initialize a protosocket.
|
|
- *
|
|
- * This macro initializes a protosocket and must be called before the
|
|
- * protosocket is used. The initialization also specifies the input buffer
|
|
- * for the protosocket.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket to be
|
|
- * initialized
|
|
- *
|
|
- * \param buffer (char *) A pointer to the input buffer for the
|
|
- * protosocket.
|
|
- *
|
|
- * \param buffersize (unsigned int) The size of the input buffer.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_INIT(psock, buffer, buffersize) \
|
|
- psock_init(psock, buffer, buffersize)
|
|
-
|
|
-/**
|
|
- * Start the protosocket protothread in a function.
|
|
- *
|
|
- * This macro starts the protothread associated with the protosocket and
|
|
- * must come before other protosocket calls in the function it is used.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket to be
|
|
- * started.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
|
|
-
|
|
-PT_THREAD(psock_send(struct uip_stack *ustack,
|
|
- struct psock *psock, const u8_t *buf, unsigned int len));
|
|
-/**
|
|
- * Send data.
|
|
- *
|
|
- * This macro sends data over a protosocket. The protosocket protothread blocks
|
|
- * until all data has been sent and is known to have been received by
|
|
- * the remote end of the TCP connection.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket over which
|
|
- * data is to be sent.
|
|
- *
|
|
- * \param data (char *) A pointer to the data that is to be sent.
|
|
- *
|
|
- * \param datalen (unsigned int) The length of the data that is to be
|
|
- * sent.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_SEND(psock, data, datalen) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
|
|
-
|
|
-/**
|
|
- * \brief Send a null-terminated string.
|
|
- * \param psock Pointer to the protosocket.
|
|
- * \param str The string to be sent.
|
|
- *
|
|
- * This function sends a null-terminated string over the
|
|
- * protosocket.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_SEND_STR(psock, str) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
|
|
-
|
|
-PT_THREAD(psock_generator_send(struct psock *psock,
|
|
- unsigned short (*f) (void *), void *arg));
|
|
-
|
|
-/**
|
|
- * \brief Generate data with a function and send it
|
|
- * \param psock Pointer to the protosocket.
|
|
- * \param generator Pointer to the generator function
|
|
- * \param arg Argument to the generator function
|
|
- *
|
|
- * This function generates data and sends it over the
|
|
- * protosocket. This can be used to dynamically generate
|
|
- * data for a transmission, instead of generating the data
|
|
- * in a buffer beforehand. This function reduces the need for
|
|
- * buffer memory. The generator function is implemented by
|
|
- * the application, and a pointer to the function is given
|
|
- * as an argument with the call to PSOCK_GENERATOR_SEND().
|
|
- *
|
|
- * The generator function should place the generated data
|
|
- * directly in the uip_appdata buffer, and return the
|
|
- * length of the generated data. The generator function is
|
|
- * called by the protosocket layer when the data first is
|
|
- * sent, and once for every retransmission that is needed.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), \
|
|
- psock_generator_send(psock, generator, arg))
|
|
-
|
|
-/**
|
|
- * Close a protosocket.
|
|
- *
|
|
- * This macro closes a protosocket and can only be called from within the
|
|
- * protothread in which the protosocket lives.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket that is to
|
|
- * be closed.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_CLOSE(psock) uip_close()
|
|
-
|
|
-PT_THREAD(psock_readbuf(struct psock *psock));
|
|
-/**
|
|
- * Read data until the buffer is full.
|
|
- *
|
|
- * This macro will block waiting for data and read the data into the
|
|
- * input buffer specified with the call to PSOCK_INIT(). Data is read
|
|
- * until the buffer is full..
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket from which
|
|
- * data should be read.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_READBUF(psock) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
|
|
-
|
|
-PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
|
|
-/**
|
|
- * Read data up to a specified character.
|
|
- *
|
|
- * This macro will block waiting for data and read the data into the
|
|
- * input buffer specified with the call to PSOCK_INIT(). Data is only
|
|
- * read until the specifieed character appears in the data stream.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket from which
|
|
- * data should be read.
|
|
- *
|
|
- * \param c (char) The character at which to stop reading.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_READTO(psock, c) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
|
|
-
|
|
-/**
|
|
- * The length of the data that was previously read.
|
|
- *
|
|
- * This macro returns the length of the data that was previously read
|
|
- * using PSOCK_READTO() or PSOCK_READ().
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket holding the data.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_DATALEN(psock) psock_datalen(psock)
|
|
-
|
|
-u16_t psock_datalen(struct psock *psock);
|
|
-
|
|
-/**
|
|
- * Exit the protosocket's protothread.
|
|
- *
|
|
- * This macro terminates the protothread of the protosocket and should
|
|
- * almost always be used in conjunction with PSOCK_CLOSE().
|
|
- *
|
|
- * \sa PSOCK_CLOSE_EXIT()
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
|
|
-
|
|
-/**
|
|
- * Close a protosocket and exit the protosocket's protothread.
|
|
- *
|
|
- * This macro closes a protosocket and exits the protosocket's protothread.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_CLOSE_EXIT(psock) \
|
|
- do { \
|
|
- PSOCK_CLOSE(psock); \
|
|
- PSOCK_EXIT(psock); \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Declare the end of a protosocket's protothread.
|
|
- *
|
|
- * This macro is used for declaring that the protosocket's protothread
|
|
- * ends. It must always be used together with a matching PSOCK_BEGIN()
|
|
- * macro.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_END(psock) PT_END(&((psock)->pt))
|
|
-
|
|
-char psock_newdata(struct psock *s);
|
|
-
|
|
-/**
|
|
- * Check if new data has arrived on a protosocket.
|
|
- *
|
|
- * This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
|
|
- * macro to check if data has arrived on a protosocket.
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_NEWDATA(psock) psock_newdata(psock)
|
|
-
|
|
-/**
|
|
- * Wait until a condition is true.
|
|
- *
|
|
- * This macro blocks the protothread until the specified condition is
|
|
- * true. The macro PSOCK_NEWDATA() can be used to check if new data
|
|
- * arrives when the protosocket is waiting.
|
|
- *
|
|
- * Typically, this macro is used as follows:
|
|
- *
|
|
- \code
|
|
- PT_THREAD(thread(struct psock *s, struct timer *t))
|
|
- {
|
|
- PSOCK_BEGIN(s);
|
|
-
|
|
- PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
|
|
-
|
|
- if(PSOCK_NEWDATA(s)) {
|
|
- PSOCK_READTO(s, '\n');
|
|
- } else {
|
|
- handle_timed_out(s);
|
|
- }
|
|
-
|
|
- PSOCK_END(s);
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \param psock (struct psock *) A pointer to the protosocket.
|
|
- * \param condition The condition to wait for.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PSOCK_WAIT_UNTIL(psock, condition) \
|
|
- PT_WAIT_UNTIL(&((psock)->pt), (condition));
|
|
-
|
|
-#define PSOCK_WAIT_THREAD(psock, condition) \
|
|
- PT_WAIT_THREAD(&((psock)->pt), (condition))
|
|
-
|
|
-#endif /* __PSOCK_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/pt.h b/iscsiuio/src/uip/pt.h
|
|
deleted file mode 100644
|
|
index ffb1d15..0000000
|
|
--- a/iscsiuio/src/uip/pt.h
|
|
+++ /dev/null
|
|
@@ -1,322 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \addtogroup pt
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Protothreads implementation.
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __PT_H__
|
|
-#define __PT_H__
|
|
-
|
|
-#include "lc.h"
|
|
-
|
|
-struct pt {
|
|
- unsigned short lc;
|
|
-};
|
|
-
|
|
-#define PT_WAITING 0
|
|
-#define PT_EXITED 1
|
|
-#define PT_ENDED 2
|
|
-#define PT_YIELDED 3
|
|
-
|
|
-/**
|
|
- * \name Initialization
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Initialize a protothread.
|
|
- *
|
|
- * Initializes a protothread. Initialization must be done prior to
|
|
- * starting to execute the protothread.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \sa PT_SPAWN()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_INIT(pt) LC_INIT((pt)->lc)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Declaration and definition
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Declaration of a protothread.
|
|
- *
|
|
- * This macro is used to declare a protothread. All protothreads must
|
|
- * be declared with this macro.
|
|
- *
|
|
- * \param name_args The name and arguments of the C function
|
|
- * implementing the protothread.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_THREAD(name_args) char name_args
|
|
-
|
|
-/**
|
|
- * Declare the start of a protothread inside the C function
|
|
- * implementing the protothread.
|
|
- *
|
|
- * This macro is used to declare the starting point of a
|
|
- * protothread. It should be placed at the start of the function in
|
|
- * which the protothread runs. All C statements above the PT_BEGIN()
|
|
- * invokation will be executed each time the protothread is scheduled.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_BEGIN(pt) { char PT_YIELD_FLAG __attribute__((__unused__)) = 1; LC_RESUME((pt)->lc)
|
|
-
|
|
-/**
|
|
- * Declare the end of a protothread.
|
|
- *
|
|
- * This macro is used for declaring that a protothread ends. It must
|
|
- * always be used together with a matching PT_BEGIN() macro.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
|
|
- PT_INIT(pt); return PT_ENDED; }
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Blocked wait
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Block and wait until condition is true.
|
|
- *
|
|
- * This macro blocks the protothread until the specified condition is
|
|
- * true.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- * \param condition The condition.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_WAIT_UNTIL(pt, condition) \
|
|
- do { \
|
|
- LC_SET((pt)->lc); \
|
|
- if (!(condition)) { \
|
|
- return PT_WAITING; \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Block and wait while condition is true.
|
|
- *
|
|
- * This function blocks and waits while condition is true. See
|
|
- * PT_WAIT_UNTIL().
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- * \param cond The condition.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Hierarchical protothreads
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Block and wait until a child protothread completes.
|
|
- *
|
|
- * This macro schedules a child protothread. The current protothread
|
|
- * will block until the child protothread completes.
|
|
- *
|
|
- * \note The child protothread must be manually initialized with the
|
|
- * PT_INIT() function before this function is used.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- * \param thread The child protothread with arguments
|
|
- *
|
|
- * \sa PT_SPAWN()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
|
|
-
|
|
-/**
|
|
- * Spawn a child protothread and wait until it exits.
|
|
- *
|
|
- * This macro spawns a child protothread and waits until it exits. The
|
|
- * macro can only be used within a protothread.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- * \param child A pointer to the child protothread's control structure.
|
|
- * \param thread The child protothread with arguments
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_SPAWN(pt, child, thread) \
|
|
- do { \
|
|
- PT_INIT((child)); \
|
|
- PT_WAIT_THREAD((pt), (thread)); \
|
|
- } while (0)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Exiting and restarting
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Restart the protothread.
|
|
- *
|
|
- * This macro will block and cause the running protothread to restart
|
|
- * its execution at the place of the PT_BEGIN() call.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_RESTART(pt) \
|
|
- do { \
|
|
- PT_INIT(pt); \
|
|
- return PT_WAITING; \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Exit the protothread.
|
|
- *
|
|
- * This macro causes the protothread to exit. If the protothread was
|
|
- * spawned by another protothread, the parent protothread will become
|
|
- * unblocked and can continue to run.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_EXIT(pt) \
|
|
- do { \
|
|
- PT_INIT(pt); \
|
|
- return PT_EXITED; \
|
|
- } while (0)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Calling a protothread
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Schedule a protothread.
|
|
- *
|
|
- * This function shedules a protothread. The return value of the
|
|
- * function is non-zero if the protothread is running or zero if the
|
|
- * protothread has exited.
|
|
- *
|
|
- * \param f The call to the C function implementing the protothread to
|
|
- * be scheduled
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_SCHEDULE(f) ((f) == PT_WAITING)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \name Yielding from a protothread
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Yield from the current protothread.
|
|
- *
|
|
- * This function will yield the protothread, thereby allowing other
|
|
- * processing to take place in the system.
|
|
- *
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_YIELD(pt) \
|
|
- do { \
|
|
- PT_YIELD_FLAG = 0; \
|
|
- LC_SET((pt)->lc); \
|
|
- if (PT_YIELD_FLAG == 0) { \
|
|
- return PT_YIELDED; \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * \brief Yield from the protothread until a condition occurs.
|
|
- * \param pt A pointer to the protothread control structure.
|
|
- * \param cond The condition.
|
|
- *
|
|
- * This function will yield the protothread, until the
|
|
- * specified condition evaluates to true.
|
|
- *
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define PT_YIELD_UNTIL(pt, cond) \
|
|
- do { \
|
|
- PT_YIELD_FLAG = 0; \
|
|
- LC_SET((pt)->lc); \
|
|
- if ((PT_YIELD_FLAG == 0) || !(cond)) { \
|
|
- return PT_YIELDED; \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-#endif /* __PT_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/timer.c b/iscsiuio/src/uip/timer.c
|
|
deleted file mode 100644
|
|
index da77148..0000000
|
|
--- a/iscsiuio/src/uip/timer.c
|
|
+++ /dev/null
|
|
@@ -1,127 +0,0 @@
|
|
-/**
|
|
- * \addtogroup timer
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Timer library implementation.
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2004, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-
|
|
-#include "clock.h"
|
|
-#include "timer.h"
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/**
|
|
- * Set a timer.
|
|
- *
|
|
- * This function is used to set a timer for a time sometime in the
|
|
- * future. The function timer_expired() will evaluate to true after
|
|
- * the timer has expired.
|
|
- *
|
|
- * \param t A pointer to the timer
|
|
- * \param interval The interval before the timer expires.
|
|
- *
|
|
- */
|
|
-void timer_set(struct timer *t, clock_time_t interval)
|
|
-{
|
|
- t->interval = interval;
|
|
- t->start = clock_time();
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/**
|
|
- * Reset the timer with the same interval.
|
|
- *
|
|
- * This function resets the timer with the same interval that was
|
|
- * given to the timer_set() function. The start point of the interval
|
|
- * is the exact time that the timer last expired. Therefore, this
|
|
- * function will cause the timer to be stable over time, unlike the
|
|
- * timer_rester() function.
|
|
- *
|
|
- * \param t A pointer to the timer.
|
|
- *
|
|
- * \sa timer_restart()
|
|
- */
|
|
-void timer_reset(struct timer *t)
|
|
-{
|
|
- t->start += t->interval;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/**
|
|
- * Restart the timer from the current point in time
|
|
- *
|
|
- * This function restarts a timer with the same interval that was
|
|
- * given to the timer_set() function. The timer will start at the
|
|
- * current time.
|
|
- *
|
|
- * \note A periodic timer will drift if this function is used to reset
|
|
- * it. For preioric timers, use the timer_reset() function instead.
|
|
- *
|
|
- * \param t A pointer to the timer.
|
|
- *
|
|
- * \sa timer_reset()
|
|
- */
|
|
-void timer_restart(struct timer *t)
|
|
-{
|
|
- t->start = clock_time();
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/**
|
|
- * Check if a timer has expired.
|
|
- *
|
|
- * This function tests if a timer has expired and returns true or
|
|
- * false depending on its status.
|
|
- *
|
|
- * \param t A pointer to the timer
|
|
- *
|
|
- * \return Non-zero if the timer has expired, zero otherwise.
|
|
- *
|
|
- */
|
|
-int timer_expired(struct timer *t)
|
|
-{
|
|
- return (clock_time_t) (clock_time() - t->start) >=
|
|
- (clock_time_t) t->interval;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/timer.h b/iscsiuio/src/uip/timer.h
|
|
deleted file mode 100644
|
|
index 12739fd..0000000
|
|
--- a/iscsiuio/src/uip/timer.h
|
|
+++ /dev/null
|
|
@@ -1,84 +0,0 @@
|
|
-/**
|
|
- * \defgroup timer Timer library
|
|
- *
|
|
- * The timer library provides functions for setting, resetting and
|
|
- * restarting timers, and for checking if a timer has expired. An
|
|
- * application must "manually" check if its timers have expired; this
|
|
- * is not done automatically.
|
|
- *
|
|
- * A timer is declared as a \c struct \c timer and all access to the
|
|
- * timer is made by a pointer to the declared timer.
|
|
- *
|
|
- * \note The timer library uses the \ref clock "Clock library" to
|
|
- * measure time. Intervals should be specified in the format used by
|
|
- * the clock library.
|
|
- *
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Timer library header file.
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2004, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- * Author: Adam Dunkels <adam@sics.se>
|
|
- *
|
|
- */
|
|
-#ifndef __TIMER_H__
|
|
-#define __TIMER_H__
|
|
-
|
|
-#include "clock.h"
|
|
-
|
|
-/**
|
|
- * A timer.
|
|
- *
|
|
- * This structure is used for declaring a timer. The timer must be set
|
|
- * with timer_set() before it can be used.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-struct timer {
|
|
- clock_time_t start;
|
|
- clock_time_t interval;
|
|
-};
|
|
-
|
|
-void timer_set(struct timer *t, clock_time_t interval);
|
|
-void timer_reset(struct timer *t);
|
|
-void timer_restart(struct timer *t);
|
|
-int timer_expired(struct timer *t);
|
|
-
|
|
-#endif /* __TIMER_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/uip-neighbor.c b/iscsiuio/src/uip/uip-neighbor.c
|
|
deleted file mode 100644
|
|
index 4c80c32..0000000
|
|
--- a/iscsiuio/src/uip/uip-neighbor.c
|
|
+++ /dev/null
|
|
@@ -1,219 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2006, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Database of link-local neighbors, used by IPv6 code and
|
|
- * to be used by a future ARP code rewrite.
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-#include "logger.h"
|
|
-#include "uip.h"
|
|
-#include "uip-neighbor.h"
|
|
-
|
|
-#include <errno.h>
|
|
-#include <string.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "uip-neigh "
|
|
-
|
|
-#define MAX_TIME 128
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_neighbor_init(struct uip_stack *ustack)
|
|
-{
|
|
- int i;
|
|
-
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
|
|
- memset(&(ustack->neighbor_entries[i].ipaddr), 0,
|
|
- sizeof(ustack->neighbor_entries[i].ipaddr));
|
|
- memset(&(ustack->neighbor_entries[i].mac_addr), 0,
|
|
- sizeof(ustack->neighbor_entries[i].mac_addr));
|
|
- ustack->neighbor_entries[i].time = MAX_TIME;
|
|
- }
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-void uip_neighbor_add(struct uip_stack *ustack,
|
|
- struct in6_addr *addr6, struct uip_eth_addr *addr)
|
|
-{
|
|
- int i, oldest;
|
|
- u8_t oldest_time;
|
|
- char buf[INET6_ADDRSTRLEN];
|
|
-
|
|
- inet_ntop(AF_INET6, addr6, buf, sizeof(buf));
|
|
-
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
-
|
|
- /* Find the first unused entry or the oldest used entry. */
|
|
- oldest_time = 0;
|
|
- oldest = 0;
|
|
- for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
|
|
- if (ustack->neighbor_entries[i].time == MAX_TIME) {
|
|
- oldest = i;
|
|
- break;
|
|
- }
|
|
- if (uip_ip6addr_cmp
|
|
- (ustack->neighbor_entries[i].ipaddr.s6_addr, addr6)) {
|
|
- oldest = i;
|
|
- break;
|
|
- }
|
|
- if (ustack->neighbor_entries[i].time > oldest_time) {
|
|
- oldest = i;
|
|
- oldest_time = ustack->neighbor_entries[i].time;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Use the oldest or first free entry (either pointed to by the
|
|
- "oldest" variable). */
|
|
- ustack->neighbor_entries[oldest].time = 0;
|
|
- uip_ip6addr_copy(ustack->neighbor_entries[oldest].ipaddr.s6_addr,
|
|
- addr6);
|
|
- memcpy(&ustack->neighbor_entries[oldest].mac_addr, addr,
|
|
- sizeof(struct uip_eth_addr));
|
|
-
|
|
- LOG_DEBUG("Adding neighbor %s with "
|
|
- "mac address %02x:%02x:%02x:%02x:%02x:%02x at %d",
|
|
- buf, addr->addr[0], addr->addr[1], addr->addr[2],
|
|
- addr->addr[3], addr->addr[4], addr->addr[5], oldest);
|
|
-
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static struct neighbor_entry *find_entry(struct uip_stack *ustack,
|
|
- struct in6_addr *addr6)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
|
|
- if (uip_ip6addr_cmp
|
|
- (ustack->neighbor_entries[i].ipaddr.s6_addr,
|
|
- addr6->s6_addr)) {
|
|
- return &ustack->neighbor_entries[i];
|
|
- }
|
|
- }
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_neighbor_update(struct uip_stack *ustack, struct in6_addr *addr6)
|
|
-{
|
|
- struct neighbor_entry *e;
|
|
-
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
-
|
|
- e = find_entry(ustack, addr6);
|
|
- if (e != NULL)
|
|
- e->time = 0;
|
|
-
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-int uip_neighbor_lookup(struct uip_stack *ustack,
|
|
- struct in6_addr *addr6, uint8_t *mac_addr)
|
|
-{
|
|
- struct neighbor_entry *e;
|
|
-
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- e = find_entry(ustack, addr6);
|
|
- if (e != NULL) {
|
|
- char addr6_str[INET6_ADDRSTRLEN];
|
|
- uint8_t *entry_mac_addr;
|
|
-
|
|
- addr6_str[0] = '\0';
|
|
- inet_ntop(AF_INET6, addr6->s6_addr, addr6_str,
|
|
- sizeof(addr6_str));
|
|
- entry_mac_addr = (uint8_t *)&e->mac_addr.addr;
|
|
-
|
|
- LOG_DEBUG(PFX
|
|
- "Found %s at %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- addr6_str,
|
|
- entry_mac_addr[0], entry_mac_addr[1],
|
|
- entry_mac_addr[2], entry_mac_addr[3],
|
|
- entry_mac_addr[4], entry_mac_addr[5]);
|
|
-
|
|
- memcpy(mac_addr, entry_mac_addr, sizeof(e->mac_addr));
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
- return -ENOENT;
|
|
-}
|
|
-
|
|
-void uip_neighbor_out(struct uip_stack *ustack)
|
|
-{
|
|
- struct neighbor_entry *e;
|
|
- struct uip_eth_hdr *eth_hdr =
|
|
- (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
- struct uip_ipv6_hdr *ipv6_hdr =
|
|
- (struct uip_ipv6_hdr *)ustack->network_layer;
|
|
-
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
-
|
|
- /* Find the destination IP address in the neighbor table and construct
|
|
- the Ethernet header. If the destination IP addres isn't on the
|
|
- local network, we use the default router's IP address instead.
|
|
-
|
|
- If not ARP table entry is found, we overwrite the original IP
|
|
- packet with an ARP request for the IP address. */
|
|
- e = find_entry(ustack, (struct in6_addr *)ipv6_hdr->destipaddr);
|
|
- if (e == NULL) {
|
|
- struct uip_eth_addr eth_addr_tmp;
|
|
-
|
|
- memcpy(ð_addr_tmp, eth_hdr->src.addr, sizeof(eth_addr_tmp));
|
|
- memcpy(eth_hdr->src.addr, ustack->uip_ethaddr.addr,
|
|
- sizeof(eth_hdr->src.addr));
|
|
- memcpy(eth_hdr->dest.addr, ð_addr_tmp,
|
|
- sizeof(eth_hdr->dest.addr));
|
|
-
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
- return;
|
|
- }
|
|
-
|
|
- memcpy(eth_hdr->dest.addr, &e->mac_addr, sizeof(eth_hdr->dest.addr));
|
|
- memcpy(eth_hdr->src.addr, ustack->uip_ethaddr.addr,
|
|
- sizeof(eth_hdr->src.addr));
|
|
-
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
diff --git a/iscsiuio/src/uip/uip-neighbor.h b/iscsiuio/src/uip/uip-neighbor.h
|
|
deleted file mode 100644
|
|
index d10c57b..0000000
|
|
--- a/iscsiuio/src/uip/uip-neighbor.h
|
|
+++ /dev/null
|
|
@@ -1,105 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2006, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Header file for database of link-local neighbors, used by
|
|
- * IPv6 code and to be used by future ARP code.
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-#ifndef __UIP_NEIGHBOR_H__
|
|
-#define __UIP_NEIGHBOR_H__
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uip_eth.h"
|
|
-
|
|
-/* ICMP types */
|
|
-/* ICMPv6 error Messages */
|
|
-#define ICMPV6_DEST_UNREACH 1
|
|
-#define ICMPV6_PKT_TOOBIG 2
|
|
-#define ICMPV6_TIME_EXCEED 3
|
|
-#define ICMPV6_PARAMPROB 4
|
|
-
|
|
-/* ICMPv6 Informational Messages */
|
|
-#define ICMPV6_ECHO_REQUEST 128
|
|
-#define ICMPV6_ECHO_REPLY 129
|
|
-#define ICMPV6_MGM_QUERY 130
|
|
-#define ICMPV6_MGM_REPORT 131
|
|
-#define ICMPV6_MGM_REDUCTION 132
|
|
-
|
|
-/* Codes for Destination Unreachable */
|
|
-#define ICMPV6_NOROUTE 0
|
|
-#define ICMPV6_ADM_PROHIBITED 1
|
|
-#define ICMPV6_NOT_NEIGHBOUR 2
|
|
-#define ICMPV6_ADDR_UNREACH 3
|
|
-#define ICMPV6_PORT_UNREACH 4
|
|
-
|
|
-/* Codes for Time Exceeded */
|
|
-#define ICMPV6_EXC_HOPLIMIT 0
|
|
-#define ICMPV6_EXC_FRAGTIME 1
|
|
-
|
|
-/* Codes for Parameter Problem */
|
|
-#define ICMPV6_HDR_FIELD 0
|
|
-#define ICMPV6_UNK_NEXTHDR 1
|
|
-#define ICMPV6_UNK_OPTION 2
|
|
-
|
|
-#if 0
|
|
-struct __attribute__ ((__packed__)) icmpv6_hdr {
|
|
- u8_t type;
|
|
- u8_t code;
|
|
- u16_t checksum;
|
|
- union {
|
|
- struct {
|
|
- u16_t id;
|
|
- u16_t sequence;
|
|
- } echo;
|
|
- u32_t gateway;
|
|
- struct {
|
|
- u16_t unused;
|
|
- u16_t mtu;
|
|
- } frag;
|
|
- } un;
|
|
-};
|
|
-#endif
|
|
-
|
|
-void uip_neighbor_init(struct uip_stack *ustack);
|
|
-void uip_neighbor_add(struct uip_stack *ustack,
|
|
- struct in6_addr *addr6, struct uip_eth_addr *addr);
|
|
-void uip_neighbor_update(struct uip_stack *ustack, struct in6_addr *addr6);
|
|
-int uip_neighbor_lookup(struct uip_stack *ustack, struct in6_addr *ipaddr,
|
|
- uint8_t *mac_addr);
|
|
-void uip_neighbor_periodic(void);
|
|
-void uip_neighbor_out(struct uip_stack *ustack);
|
|
-
|
|
-#endif /* __UIP-NEIGHBOR_H__ */
|
|
diff --git a/iscsiuio/src/uip/uip.c b/iscsiuio/src/uip/uip.c
|
|
deleted file mode 100644
|
|
index e0a7221..0000000
|
|
--- a/iscsiuio/src/uip/uip.c
|
|
+++ /dev/null
|
|
@@ -1,2434 +0,0 @@
|
|
-#include <netinet/in.h>
|
|
-#include <netinet/ip6.h>
|
|
-#include <netinet/icmp6.h>
|
|
-#include <sys/types.h>
|
|
-#include <arpa/inet.h>
|
|
-#include "uip.h"
|
|
-#include "dhcpc.h"
|
|
-#include "ipv6_ndpc.h"
|
|
-#include "brcm_iscsi.h"
|
|
-#include "ping.h"
|
|
-
|
|
-/**
|
|
- * \defgroup uip The uIP TCP/IP stack
|
|
- * @{
|
|
- *
|
|
- * uIP is an implementation of the TCP/IP protocol stack intended for
|
|
- * small 8-bit and 16-bit microcontrollers.
|
|
- *
|
|
- * uIP provides the necessary protocols for Internet communication,
|
|
- * with a very small code footprint and RAM requirements - the uIP
|
|
- * code size is on the order of a few kilobytes and RAM usage is on
|
|
- * the order of a few hundred bytes.
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * The uIP TCP/IP stack code.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001-2003, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-/*
|
|
- * uIP is a small implementation of the IP, UDP and TCP protocols (as
|
|
- * well as some basic ICMP stuff). The implementation couples the IP,
|
|
- * UDP, TCP and the application layers very tightly. To keep the size
|
|
- * of the compiled code down, this code frequently uses the goto
|
|
- * statement. While it would be possible to break the uip_process()
|
|
- * function into many smaller functions, this would increase the code
|
|
- * size because of the overhead of parameter passing and the fact that
|
|
- * the optimier would not be as efficient.
|
|
- *
|
|
- * The principle is that we have a small buffer, called the uip_buf,
|
|
- * in which the device driver puts an incoming packet. The TCP/IP
|
|
- * stack parses the headers in the packet, and calls the
|
|
- * application. If the remote host has sent data to the application,
|
|
- * this data is present in the uip_buf and the application read the
|
|
- * data from there. It is up to the application to put this data into
|
|
- * a byte stream if needed. The application will not be fed with data
|
|
- * that is out of sequence.
|
|
- *
|
|
- * If the application whishes to send data to the peer, it should put
|
|
- * its data into the uip_buf. The uip_appdata pointer points to the
|
|
- * first available byte. The TCP/IP stack will calculate the
|
|
- * checksums, and fill in the necessary header fields and finally send
|
|
- * the packet back to the peer.
|
|
-*/
|
|
-
|
|
-#include "logger.h"
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uipopt.h"
|
|
-#include "uip_arch.h"
|
|
-#include "uip_eth.h"
|
|
-#include "uip-neighbor.h"
|
|
-
|
|
-#include <string.h>
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "uip "
|
|
-
|
|
-static const uip_ip4addr_t all_ones_addr4 = { 0xffff, 0xffff };
|
|
-
|
|
-const uip_ip6addr_t all_zeroes_addr6 = {
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
|
-};
|
|
-const uip_ip4addr_t all_zeroes_addr4 = { 0x0000, 0x0000 };
|
|
-
|
|
-const uint8_t mutlicast_ipv6_prefix[16] = {
|
|
- 0xfc, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
-};
|
|
-
|
|
-const uint8_t link_local_addres_prefix[16] = {
|
|
- 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
-};
|
|
-const uint32_t link_local_address_prefix_length = 10;
|
|
-
|
|
-/* Structures and definitions. */
|
|
-#define TCP_FIN 0x01
|
|
-#define TCP_SYN 0x02
|
|
-#define TCP_RST 0x04
|
|
-#define TCP_PSH 0x08
|
|
-#define TCP_ACK 0x10
|
|
-#define TCP_URG 0x20
|
|
-#define TCP_CTL 0x3f
|
|
-
|
|
-#define TCP_OPT_END 0 /* End of TCP options list */
|
|
-#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
|
|
-#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
|
|
-
|
|
-#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
|
|
-
|
|
-#define ICMP_ECHO_REPLY 0
|
|
-#define ICMP_ECHO 8
|
|
-
|
|
-#define ICMP6_ECHO_REPLY 129
|
|
-#define ICMP6_ECHO 128
|
|
-#define ICMP6_NEIGHBOR_SOLICITATION 135
|
|
-#define ICMP6_NEIGHBOR_ADVERTISEMENT 136
|
|
-
|
|
-#define ICMP6_FLAG_S (1 << 6)
|
|
-
|
|
-#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
|
|
-#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
|
|
-
|
|
-/* Macros. */
|
|
-#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
|
|
-#define UDPBUF(ustack) ((struct uip_udpip_hdr *)ustack->network_layer)
|
|
-
|
|
-/******************************************************************************
|
|
- * Utility Functions
|
|
- *****************************************************************************/
|
|
-static int is_ipv6(struct uip_stack *ustack)
|
|
-{
|
|
- u16_t type;
|
|
-
|
|
- type = ETH_BUF(ustack->uip_buf)->type;
|
|
- type = ntohs(type);
|
|
- if (type == UIP_ETHTYPE_8021Q)
|
|
- type = ntohs(VLAN_ETH_BUF(ustack->uip_buf)->type);
|
|
- else
|
|
- type = ntohs(ETH_BUF(ustack->uip_buf)->type);
|
|
-
|
|
- return (type == UIP_ETHTYPE_IPv6);
|
|
-}
|
|
-
|
|
-int is_ipv6_link_local_address(uip_ip6addr_t *addr)
|
|
-{
|
|
- u8_t *test_adddr = (u8_t *) addr;
|
|
- u8_t test_remainder;
|
|
-
|
|
- if (test_adddr[0] != link_local_addres_prefix[0])
|
|
- return 0;
|
|
-
|
|
- test_remainder = (test_adddr[1] & 0xC0) >> 6;
|
|
- if (test_remainder != 2)
|
|
- return 0;
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
-void uip_sethostaddr4(struct uip_stack *ustack, uip_ip4addr_t *addr)
|
|
-{
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- uip_ip4addr_copy(ustack->hostaddr, (addr));
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-void uip_setdraddr4(struct uip_stack *ustack, uip_ip4addr_t *addr)
|
|
-{
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- uip_ip4addr_copy(ustack->default_route_addr, (addr));
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-void uip_setnetmask4(struct uip_stack *ustack, uip_ip4addr_t *addr)
|
|
-{
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- uip_ip4addr_copy(ustack->netmask, (addr));
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-void uip_setethernetmac(struct uip_stack *ustack, uint8_t *mac)
|
|
-{
|
|
- pthread_mutex_lock(&ustack->lock);
|
|
- memcpy(ustack->uip_ethaddr.addr, (mac), 6);
|
|
- pthread_mutex_unlock(&ustack->lock);
|
|
-}
|
|
-
|
|
-void set_uip_stack(struct uip_stack *ustack,
|
|
- uip_ip4addr_t *ip,
|
|
- uip_ip4addr_t *netmask,
|
|
- uip_ip4addr_t *default_route, uint8_t *mac_addr)
|
|
-{
|
|
- if (ip)
|
|
- uip_sethostaddr4(ustack, ip);
|
|
- if (netmask)
|
|
- uip_setnetmask4(ustack, netmask);
|
|
- if (default_route)
|
|
- uip_setdraddr4(ustack, default_route);
|
|
- if (mac_addr)
|
|
- uip_setethernetmac(ustack, mac_addr);
|
|
-}
|
|
-
|
|
-#if !UIP_ARCH_ADD32
|
|
-void uip_add32(u8_t *op32, u16_t op16, u8_t *uip_acc32)
|
|
-{
|
|
- uip_acc32[3] = op32[3] + (op16 & 0xff);
|
|
- uip_acc32[2] = op32[2] + (op16 >> 8);
|
|
- uip_acc32[1] = op32[1];
|
|
- uip_acc32[0] = op32[0];
|
|
-
|
|
- if (uip_acc32[2] < (op16 >> 8)) {
|
|
- ++uip_acc32[1];
|
|
- if (uip_acc32[1] == 0)
|
|
- ++uip_acc32[0];
|
|
- }
|
|
-
|
|
- if (uip_acc32[3] < (op16 & 0xff)) {
|
|
- ++uip_acc32[2];
|
|
- if (uip_acc32[2] == 0) {
|
|
- ++uip_acc32[1];
|
|
- if (uip_acc32[1] == 0)
|
|
- ++uip_acc32[0];
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#endif /* UIP_ARCH_ADD32 */
|
|
-
|
|
-#if !UIP_ARCH_CHKSUM
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u16_t chksum(u16_t sum, const u8_t *data, u16_t len)
|
|
-{
|
|
- u16_t t;
|
|
- const u8_t *dataptr;
|
|
- const u8_t *last_byte;
|
|
-
|
|
- dataptr = data;
|
|
- last_byte = data + len - 1;
|
|
-
|
|
- while (dataptr < last_byte) { /* At least two more bytes */
|
|
- t = (dataptr[0] << 8) + dataptr[1];
|
|
- sum += t;
|
|
- if (sum < t)
|
|
- sum++; /* carry */
|
|
- dataptr += 2;
|
|
- }
|
|
-
|
|
- if (dataptr == last_byte) {
|
|
- t = (dataptr[0] << 8) + 0;
|
|
- sum += t;
|
|
- if (sum < t)
|
|
- sum++; /* carry */
|
|
- }
|
|
-
|
|
- /* Return sum in host byte order. */
|
|
- return sum;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-u16_t uip_chksum(u16_t *data, u16_t len)
|
|
-{
|
|
- return htons(chksum(0, (u8_t *)data, len));
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-#ifndef UIP_ARCH_IPCHKSUM
|
|
-u16_t uip_ipchksum(struct uip_stack *ustack)
|
|
-{
|
|
- u16_t sum;
|
|
- u16_t uip_iph_len;
|
|
-
|
|
- if (is_ipv6(ustack))
|
|
- uip_iph_len = UIP_IPv6_H_LEN;
|
|
- else
|
|
- uip_iph_len = UIP_IPv4_H_LEN;
|
|
-
|
|
- sum = chksum(0, ustack->network_layer, uip_iph_len);
|
|
- return (sum == 0) ? 0xffff : htons(sum);
|
|
-}
|
|
-#endif
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static u16_t upper_layer_chksum_ipv4(struct uip_stack *ustack, u8_t proto)
|
|
-{
|
|
- u16_t upper_layer_len;
|
|
- u16_t sum;
|
|
- struct uip_tcp_ipv4_hdr *tcp_ipv4_hdr = NULL;
|
|
-
|
|
- tcp_ipv4_hdr = (struct uip_tcp_ipv4_hdr *)ustack->network_layer;
|
|
-
|
|
- upper_layer_len = (((u16_t) (tcp_ipv4_hdr->len[0]) << 8) +
|
|
- tcp_ipv4_hdr->len[1]);
|
|
- /* check for underflow from an invalid length field */
|
|
- if (upper_layer_len < UIP_IPv4_H_LEN) {
|
|
- /* return 0 as an invalid checksum */
|
|
- return 0;
|
|
- }
|
|
- upper_layer_len -= UIP_IPv4_H_LEN;
|
|
-
|
|
- /* First sum pseudoheader. */
|
|
- /* IP protocol and length fields. This addition cannot carry. */
|
|
- sum = upper_layer_len + proto;
|
|
-
|
|
- sum =
|
|
- chksum(sum, (u8_t *)&tcp_ipv4_hdr->srcipaddr[0],
|
|
- 2 * sizeof(uip_ip4addr_t));
|
|
- /* Sum TCP header and data. */
|
|
- sum = chksum(sum, ustack->network_layer + UIP_IPv4_H_LEN,
|
|
- upper_layer_len);
|
|
-
|
|
- return (sum == 0) ? 0xffff : htons(sum);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static uint16_t upper_layer_checksum_ipv6(uint8_t *data, uint8_t proto)
|
|
-{
|
|
- uint16_t upper_layer_len;
|
|
- uint16_t sum;
|
|
- struct ip6_hdr *ipv6_hdr;
|
|
- uint8_t *upper_layer;
|
|
- uint32_t val;
|
|
-
|
|
- ipv6_hdr = (struct ip6_hdr *)data;
|
|
-
|
|
- upper_layer_len = ntohs(ipv6_hdr->ip6_plen);
|
|
-
|
|
- /* First sum pseudoheader. */
|
|
- sum = 0;
|
|
- sum = chksum(sum, (const u8_t *)ipv6_hdr->ip6_src.s6_addr,
|
|
- sizeof(ipv6_hdr->ip6_src));
|
|
- sum = chksum(sum, (const u8_t *)ipv6_hdr->ip6_dst.s6_addr,
|
|
- sizeof(ipv6_hdr->ip6_dst));
|
|
-
|
|
- val = htons(upper_layer_len);
|
|
- sum = chksum(sum, (u8_t *)&val, sizeof(val));
|
|
-
|
|
- val = htons(proto);
|
|
- sum = chksum(sum, (u8_t *)&val, sizeof(val));
|
|
-
|
|
- upper_layer = (uint8_t *)(ipv6_hdr + 1);
|
|
- sum = chksum(sum, upper_layer, upper_layer_len);
|
|
-
|
|
- return (sum == 0) ? 0xffff : htons(sum);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-
|
|
-u16_t uip_icmp6chksum(struct uip_stack *ustack)
|
|
-{
|
|
- uint8_t *data = ustack->network_layer;
|
|
-
|
|
- return upper_layer_checksum_ipv6(data, UIP_PROTO_ICMP6);
|
|
-}
|
|
-
|
|
-uint16_t icmpv6_checksum(uint8_t *data)
|
|
-{
|
|
- return upper_layer_checksum_ipv6(data, IPPROTO_ICMPV6);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-u16_t uip_tcpchksum(struct uip_stack *ustack)
|
|
-{
|
|
- return upper_layer_chksum_ipv4(ustack, UIP_PROTO_TCP);
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-#if UIP_UDP_CHECKSUMS
|
|
-static u16_t uip_udpchksum_ipv4(struct uip_stack *ustack)
|
|
-{
|
|
- return upper_layer_chksum_ipv4(ustack, UIP_PROTO_UDP);
|
|
-}
|
|
-
|
|
-static u16_t uip_udpchksum_ipv6(struct uip_stack *ustack)
|
|
-{
|
|
- uint8_t *data = ustack->network_layer;
|
|
-
|
|
- return upper_layer_checksum_ipv6(data, UIP_PROTO_UDP);
|
|
-}
|
|
-
|
|
-u16_t uip_udpchksum(struct uip_stack *ustack)
|
|
-{
|
|
- if (is_ipv6(ustack))
|
|
- return uip_udpchksum_ipv6(ustack);
|
|
- else
|
|
- return uip_udpchksum_ipv4(ustack);
|
|
-}
|
|
-#endif /* UIP_UDP_CHECKSUMS */
|
|
-#endif /* UIP_ARCH_CHKSUM */
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_init(struct uip_stack *ustack, uint8_t ipv6_enabled)
|
|
-{
|
|
- u8_t c;
|
|
-
|
|
- for (c = 0; c < UIP_LISTENPORTS; ++c)
|
|
- ustack->uip_listenports[c] = 0;
|
|
- for (c = 0; c < UIP_CONNS; ++c)
|
|
- ustack->uip_conns[c].tcpstateflags = UIP_CLOSED;
|
|
-#if UIP_ACTIVE_OPEN
|
|
- ustack->lastport = 1024;
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-
|
|
-#if UIP_UDP
|
|
- for (c = 0; c < UIP_UDP_CONNS; ++c)
|
|
- ustack->uip_udp_conns[c].lport = 0;
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
- /* IPv4 initialization. */
|
|
-#if UIP_FIXEDADDR == 0
|
|
- /* uip_hostaddr[0] = uip_hostaddr[1] = 0; */
|
|
-#endif /* UIP_FIXEDADDR */
|
|
-
|
|
- /* zero out the uIP statistics */
|
|
- memset(&ustack->stats, 0, sizeof(ustack->stats));
|
|
-
|
|
- /* prepare the uIP lock */
|
|
- pthread_mutex_init(&ustack->lock, NULL);
|
|
-
|
|
- if (ipv6_enabled)
|
|
- ustack->enable_IPv6 = UIP_SUPPORT_IPv6_ENABLED;
|
|
- else
|
|
- ustack->enable_IPv6 = UIP_SUPPORT_IPv6_DISABLED;
|
|
-
|
|
- ustack->dhcpc = NULL;
|
|
- ustack->ndpc = NULL;
|
|
- ustack->ping_conf = NULL;
|
|
-}
|
|
-void uip_reset(struct uip_stack *ustack)
|
|
-{
|
|
- /* There was an associated DHCP object, this memory needs to be
|
|
- * freed */
|
|
- if (ustack->dhcpc)
|
|
- free(ustack->dhcpc);
|
|
-
|
|
- ndpc_exit(ustack->ndpc);
|
|
-
|
|
- memset(ustack, 0, sizeof(*ustack));
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-#if UIP_ACTIVE_OPEN
|
|
-struct uip_conn *uip_connect(struct uip_stack *ustack, uip_ip4addr_t *ripaddr,
|
|
- u16_t rport)
|
|
-{
|
|
- u8_t c;
|
|
- register struct uip_conn *conn, *cconn;
|
|
-
|
|
- /* Find an unused local port. */
|
|
-again:
|
|
- ++ustack->lastport;
|
|
-
|
|
- if (ustack->lastport >= 32000)
|
|
- ustack->lastport = 4096;
|
|
-
|
|
- /* Check if this port is already in use, and if so try to find
|
|
- another one. */
|
|
- for (c = 0; c < UIP_CONNS; ++c) {
|
|
- conn = &ustack->uip_conns[c];
|
|
- if (conn->tcpstateflags != UIP_CLOSED &&
|
|
- conn->lport == htons(ustack->lastport)) {
|
|
- goto again;
|
|
- }
|
|
- }
|
|
-
|
|
- conn = 0;
|
|
- for (c = 0; c < UIP_CONNS; ++c) {
|
|
- cconn = &ustack->uip_conns[c];
|
|
- if (cconn->tcpstateflags == UIP_CLOSED) {
|
|
- conn = cconn;
|
|
- break;
|
|
- }
|
|
- if (cconn->tcpstateflags == UIP_TIME_WAIT) {
|
|
- if (conn == 0 || cconn->timer > conn->timer)
|
|
- conn = cconn;
|
|
- }
|
|
- }
|
|
-
|
|
- if (conn == 0)
|
|
- return 0;
|
|
-
|
|
- conn->tcpstateflags = UIP_SYN_SENT;
|
|
-
|
|
- conn->snd_nxt[0] = ustack->iss[0];
|
|
- conn->snd_nxt[1] = ustack->iss[1];
|
|
- conn->snd_nxt[2] = ustack->iss[2];
|
|
- conn->snd_nxt[3] = ustack->iss[3];
|
|
-
|
|
- conn->initialmss = conn->mss = UIP_TCP_MSS;
|
|
-
|
|
- conn->len = 1; /* TCP length of the SYN is one. */
|
|
- conn->nrtx = 0;
|
|
- conn->timer = 1; /* Send the SYN next time around. */
|
|
- conn->rto = UIP_RTO;
|
|
- conn->sa = 0;
|
|
- conn->sv = 16; /* Initial value of the RTT variance. */
|
|
- conn->lport = htons(ustack->lastport);
|
|
- conn->rport = rport;
|
|
- uip_ip4addr_copy(&conn->ripaddr, ripaddr);
|
|
-
|
|
- return conn;
|
|
-}
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-/*---------------------------------------------------------------------------*/
|
|
-#if UIP_UDP
|
|
-struct uip_udp_conn *uip_udp_new(struct uip_stack *ustack,
|
|
- uip_ip4addr_t *ripaddr, u16_t rport)
|
|
-{
|
|
- u8_t c;
|
|
- register struct uip_udp_conn *conn;
|
|
-
|
|
- /* Find an unused local port. */
|
|
-again:
|
|
- ++ustack->lastport;
|
|
-
|
|
- if (ustack->lastport >= 32000)
|
|
- ustack->lastport = 4096;
|
|
-
|
|
- for (c = 0; c < UIP_UDP_CONNS; ++c) {
|
|
- if (ustack->uip_udp_conns[c].lport == htons(ustack->lastport))
|
|
- goto again;
|
|
- }
|
|
-
|
|
- conn = 0;
|
|
- for (c = 0; c < UIP_UDP_CONNS; ++c) {
|
|
- if (ustack->uip_udp_conns[c].lport == 0) {
|
|
- conn = &ustack->uip_udp_conns[c];
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (conn == 0)
|
|
- return 0;
|
|
-
|
|
- conn->lport = htons(ustack->lastport);
|
|
- conn->rport = rport;
|
|
- if (ripaddr == NULL)
|
|
- memset(conn->ripaddr, 0, sizeof(uip_ip4addr_t));
|
|
- else
|
|
- uip_ip4addr_copy(&conn->ripaddr, ripaddr);
|
|
- conn->ttl = UIP_TTL;
|
|
-
|
|
- return conn;
|
|
-}
|
|
-#endif /* UIP_UDP */
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_unlisten(struct uip_stack *ustack, u16_t port)
|
|
-{
|
|
- u8_t c;
|
|
-
|
|
- for (c = 0; c < UIP_LISTENPORTS; ++c) {
|
|
- if (ustack->uip_listenports[c] == port) {
|
|
- ustack->uip_listenports[c] = 0;
|
|
- return;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_listen(struct uip_stack *ustack, u16_t port)
|
|
-{
|
|
- u8_t c;
|
|
-
|
|
- for (c = 0; c < UIP_LISTENPORTS; ++c) {
|
|
- if (ustack->uip_listenports[c] == 0) {
|
|
- ustack->uip_listenports[c] = port;
|
|
- return;
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-/**
|
|
- * Is new incoming data available?
|
|
- *
|
|
- * Will reduce to non-zero if there is new data for the application
|
|
- * present at the uip_appdata pointer. The size of the data is
|
|
- * avaliable through the uip_len variable.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_newdata(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_NEWDATA;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Has previously sent data been acknowledged?
|
|
- *
|
|
- * Will reduce to non-zero if the previously sent data has been
|
|
- * acknowledged by the remote host. This means that the application
|
|
- * can send new data.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_acked() (uip_flags & UIP_ACKDATA)
|
|
-
|
|
-/**
|
|
- * Has the connection just been connected?
|
|
- *
|
|
- * Reduces to non-zero if the current connection has been connected to
|
|
- * a remote host. This will happen both if the connection has been
|
|
- * actively opened (with uip_connect()) or passively opened (with
|
|
- * uip_listen()).
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_connected(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_CONNECTED;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Has the connection been closed by the other end?
|
|
- *
|
|
- * Is non-zero if the connection has been closed by the remote
|
|
- * host. The application may then do the necessary clean-ups.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_closed(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_CLOSE;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Has the connection been aborted by the other end?
|
|
- *
|
|
- * Non-zero if the current connection has been aborted (reset) by the
|
|
- * remote host.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_aborted(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_ABORT;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Has the connection timed out?
|
|
- *
|
|
- * Non-zero if the current connection has been aborted due to too many
|
|
- * retransmissions.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_timedout(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_TIMEDOUT;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Do we need to retransmit previously data?
|
|
- *
|
|
- * Reduces to non-zero if the previously sent data has been lost in
|
|
- * the network, and the application should retransmit it. The
|
|
- * application should send the exact same data as it did the last
|
|
- * time, using the uip_send() function.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_rexmit(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_REXMIT;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Is the connection being polled by uIP?
|
|
- *
|
|
- * Is non-zero if the reason the application is invoked is that the
|
|
- * current connection has been idle for a while and should be
|
|
- * polled.
|
|
- *
|
|
- * The polling event can be used for sending data without having to
|
|
- * wait for the remote host to send data.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_poll(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_flags & UIP_POLL;
|
|
-}
|
|
-
|
|
-int uip_initialmss(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_conn->initialmss;
|
|
-}
|
|
-
|
|
-int uip_mss(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_conn->mss;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/* XXX: IP fragment reassembly: not well-tested. */
|
|
-
|
|
-#if UIP_REASSEMBLY && !UIP_CONF_IPV6
|
|
-#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
|
|
-static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
|
|
-static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
|
|
-static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
|
- 0x0f, 0x07, 0x03, 0x01
|
|
-};
|
|
-static u16_t uip_reasslen;
|
|
-static u8_t uip_reassflags;
|
|
-#define UIP_REASS_FLAG_LASTFRAG 0x01
|
|
-static u8_t uip_reasstmr;
|
|
-
|
|
-#define IP_MF 0x20
|
|
-
|
|
-static u8_t uip_reass(void)
|
|
-{
|
|
- u16_t offset, len;
|
|
- u16_t i;
|
|
-
|
|
- /* If ip_reasstmr is zero, no packet is present in the buffer, so we
|
|
- write the IP header of the fragment into the reassembly
|
|
- buffer. The timer is updated with the maximum age. */
|
|
- if (uip_reasstmr == 0) {
|
|
- memcpy(uip_reassbuf, &BUF(ustack)->vhl, uip_iph_len);
|
|
- uip_reasstmr = UIP_REASS_MAXAGE;
|
|
- uip_reassflags = 0;
|
|
- /* Clear the bitmap. */
|
|
- memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
|
|
- }
|
|
-
|
|
- /* Check if the incoming fragment matches the one currently present
|
|
- in the reasembly buffer. If so, we proceed with copying the
|
|
- fragment into the buffer. */
|
|
- if (BUF(ustack)->srcipaddr[0] == FBUF(ustack)->srcipaddr[0] &&
|
|
- BUF(ustack)->srcipaddr[1] == FBUF(ustack)->srcipaddr[1] &&
|
|
- BUF(ustack)->destipaddr[0] == FBUF(ustack)->destipaddr[0] &&
|
|
- BUF(ustack)->destipaddr[1] == FBUF(ustack)->destipaddr[1] &&
|
|
- BUF(ustack)->ipid[0] == FBUF(ustack)->ipid[0] &&
|
|
- BUF(ustack)->ipid[1] == FBUF(ustack)->ipid[1]) {
|
|
-
|
|
- len =
|
|
- (BUF(ustack)->len[0] << 8) + BUF(ustack)->len[1] -
|
|
- (BUF(ustack)->vhl & 0x0f) * 4;
|
|
- offset =
|
|
- (((BUF(ustack)->ipoffset[0] & 0x3f) << 8) +
|
|
- BUF(ustack)->ipoffset[1]) * 8;
|
|
-
|
|
- /* If the offset or the offset + fragment length overflows the
|
|
- reassembly buffer, we discard the entire packet. */
|
|
- if (offset > UIP_REASS_BUFSIZE ||
|
|
- offset + len > UIP_REASS_BUFSIZE) {
|
|
- uip_reasstmr = 0;
|
|
- goto nullreturn;
|
|
- }
|
|
-
|
|
- /* Copy the fragment into the reassembly buffer, at the right
|
|
- offset. */
|
|
- memcpy(&uip_reassbuf[uip_iph_len + offset],
|
|
- (char *)BUF + (int)((BUF(ustack)->vhl & 0x0f) * 4), len);
|
|
-
|
|
- /* Update the bitmap. */
|
|
- if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
|
- /* If the two endpoints are in the same byte, we only
|
|
- update that byte. */
|
|
-
|
|
- uip_reassbitmap[offset / (8 * 8)] |=
|
|
- bitmap_bits[(offset / 8) & 7] &
|
|
- ~bitmap_bits[((offset + len) / 8) & 7];
|
|
- } else {
|
|
- /* If the two endpoints are in different bytes, we
|
|
- update the bytes in the endpoints and fill the
|
|
- stuff inbetween with 0xff. */
|
|
- uip_reassbitmap[offset / (8 * 8)] |=
|
|
- bitmap_bits[(offset / 8) & 7];
|
|
- for (i = 1 + offset / (8 * 8);
|
|
- i < (offset + len) / (8 * 8); ++i) {
|
|
- uip_reassbitmap[i] = 0xff;
|
|
- }
|
|
- uip_reassbitmap[(offset + len) / (8 * 8)] |=
|
|
- ~bitmap_bits[((offset + len) / 8) & 7];
|
|
- }
|
|
-
|
|
- /* If this fragment has the More Fragments flag set to zero, we
|
|
- know that this is the last fragment, so we can calculate the
|
|
- size of the entire packet. We also set the
|
|
- IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
|
|
- the final fragment. */
|
|
-
|
|
- if ((BUF(ustack)->ipoffset[0] & IP_MF) == 0) {
|
|
- uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
|
|
- uip_reasslen = offset + len;
|
|
- }
|
|
-
|
|
- /* Finally, we check if we have a full packet in the buffer.
|
|
- We do this by checking if we have the last fragment and if
|
|
- all bits in the bitmap are set. */
|
|
- if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
|
|
- /* Check all bytes up to and including all but the last
|
|
- byte in the bitmap. */
|
|
- for (i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
|
|
- if (uip_reassbitmap[i] != 0xff)
|
|
- goto nullreturn;
|
|
- }
|
|
- /* Check the last byte in the bitmap. It should contain
|
|
- just the right amount of bits. */
|
|
- if (uip_reassbitmap[uip_reasslen / (8 * 8)] !=
|
|
- (u8_t) ~bitmap_bits[uip_reasslen / 8 & 7])
|
|
- goto nullreturn;
|
|
-
|
|
- /* If we have come this far, we have a full packet in
|
|
- the buffer, so we allocate a pbuf and copy the
|
|
- packet into it. We also reset the timer. */
|
|
- uip_reasstmr = 0;
|
|
- memcpy(BUF, FBUF, uip_reasslen);
|
|
-
|
|
- /* Pretend to be a "normal" (i.e., not fragmented) IP
|
|
- packet from now on. */
|
|
- BUF(ustack)->ipoffset[0] = BUF(ustack)->ipoffset[1] = 0;
|
|
- BUF(ustack)->len[0] = uip_reasslen >> 8;
|
|
- BUF(ustack)->len[1] = uip_reasslen & 0xff;
|
|
- BUF(ustack)->ipchksum = 0;
|
|
- BUF(ustack)->ipchksum = ~(uip_ipchksum());
|
|
-
|
|
- return uip_reasslen;
|
|
- }
|
|
- }
|
|
-
|
|
-nullreturn:
|
|
- return 0;
|
|
-}
|
|
-#endif /* UIP_REASSEMBLY */
|
|
-/*---------------------------------------------------------------------------*/
|
|
-static void uip_add_rcv_nxt(struct uip_stack *ustack, u16_t n)
|
|
-{
|
|
- u8_t uip_acc32[4];
|
|
-
|
|
- uip_add32(ustack->uip_conn->rcv_nxt, n, uip_acc32);
|
|
- ustack->uip_conn->rcv_nxt[0] = uip_acc32[0];
|
|
- ustack->uip_conn->rcv_nxt[1] = uip_acc32[1];
|
|
- ustack->uip_conn->rcv_nxt[2] = uip_acc32[2];
|
|
- ustack->uip_conn->rcv_nxt[3] = uip_acc32[3];
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \defgroup uipdevfunc uIP device driver functions
|
|
- * @{
|
|
- *
|
|
- * These functions are used by a network device driver for interacting
|
|
- * with uIP.
|
|
- */
|
|
-
|
|
-/**
|
|
- * Process an incoming packet.
|
|
- *
|
|
- * This function should be called when the device driver has received
|
|
- * a packet from the network. The packet from the device driver must
|
|
- * be present in the uip_buf buffer, and the length of the packet
|
|
- * should be placed in the uip_len variable.
|
|
- *
|
|
- * When the function returns, there may be an outbound packet placed
|
|
- * in the uip_buf packet buffer. If so, the uip_len variable is set to
|
|
- * the length of the packet. If no packet is to be sent out, the
|
|
- * uip_len variable is set to 0.
|
|
- *
|
|
- * The usual way of calling the function is presented by the source
|
|
- * code below.
|
|
- \code
|
|
- uip_len = devicedriver_poll();
|
|
- if(uip_len > 0) {
|
|
- uip_input();
|
|
- if(uip_len > 0) {
|
|
- devicedriver_send();
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \note If you are writing a uIP device driver that needs ARP
|
|
- * (Address Resolution Protocol), e.g., when running uIP over
|
|
- * Ethernet, you will need to call the uIP ARP code before calling
|
|
- * this function:
|
|
- \code
|
|
- #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
|
|
- uip_len = ethernet_devicedrver_poll();
|
|
- if(uip_len > 0) {
|
|
- if (BUF(ustack)->type == HTONS(UIP_ETHTYPE_IP)) {
|
|
- uip_arp_ipin();
|
|
- uip_input();
|
|
- if (uip_len > 0) {
|
|
- uip_arp_out();
|
|
- ethernet_devicedriver_send();
|
|
- }
|
|
- } else if (BUF(ustack)->type == HTONS(UIP_ETHTYPE_ARP)) {
|
|
- uip_arp_arpin();
|
|
- if (uip_len > 0)
|
|
- ethernet_devicedriver_send();
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_input(struct uip_stack *ustack)
|
|
-{
|
|
- uip_process(ustack, UIP_DATA);
|
|
-}
|
|
-
|
|
-/**
|
|
- * Periodic processing for a connection identified by its number.
|
|
- *
|
|
- * This function does the necessary periodic processing (timers,
|
|
- * polling) for a uIP TCP conneciton, and should be called when the
|
|
- * periodic uIP timer goes off. It should be called for every
|
|
- * connection, regardless of whether they are open of closed.
|
|
- *
|
|
- * When the function returns, it may have an outbound packet waiting
|
|
- * for service in the uIP packet buffer, and if so the uip_len
|
|
- * variable is set to a value larger than zero. The device driver
|
|
- * should be called to send out the packet.
|
|
- *
|
|
- * The ususal way of calling the function is through a for() loop like
|
|
- * this:
|
|
- \code
|
|
- for(i = 0; i < UIP_CONNS; ++i) {
|
|
- uip_periodic(i);
|
|
- if(uip_len > 0) {
|
|
- devicedriver_send();
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \note If you are writing a uIP device driver that needs ARP
|
|
- * (Address Resolution Protocol), e.g., when running uIP over
|
|
- * Ethernet, you will need to call the uip_arp_out() function before
|
|
- * calling the device driver:
|
|
- \code
|
|
- for(i = 0; i < UIP_CONNS; ++i) {
|
|
- uip_periodic(i);
|
|
- if(uip_len > 0) {
|
|
- uip_arp_out();
|
|
- ethernet_devicedriver_send();
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \param conn The number of the connection which is to be periodically polled.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_periodic(struct uip_stack *ustack, int conn)
|
|
-{
|
|
- ustack->uip_conn = &ustack->uip_conns[conn];
|
|
- uip_process(ustack, UIP_TIMER);
|
|
-}
|
|
-
|
|
-#if UIP_UDP
|
|
-/**
|
|
- * Periodic processing for a UDP connection identified by its number.
|
|
- *
|
|
- * This function is essentially the same as uip_periodic(), but for
|
|
- * UDP connections. It is called in a similar fashion as the
|
|
- * uip_periodic() function:
|
|
- \code
|
|
- for(i = 0; i < UIP_UDP_CONNS; i++) {
|
|
- uip_udp_periodic(i);
|
|
- if(uip_len > 0) {
|
|
- devicedriver_send();
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \note As for the uip_periodic() function, special care has to be
|
|
- * taken when using uIP together with ARP and Ethernet:
|
|
- \code
|
|
- for(i = 0; i < UIP_UDP_CONNS; i++) {
|
|
- uip_udp_periodic(i);
|
|
- if(uip_len > 0) {
|
|
- uip_arp_out();
|
|
- ethernet_devicedriver_send();
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \param conn The number of the UDP connection to be processed.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_udp_periodic(struct uip_stack *ustack, int conn)
|
|
-{
|
|
- ustack->uip_udp_conn = &ustack->uip_udp_conns[conn];
|
|
- uip_process(ustack, UIP_UDP_TIMER);
|
|
-}
|
|
-#endif
|
|
-
|
|
-void uip_ndp_periodic(struct uip_stack *ustack)
|
|
-{
|
|
- uip_process(ustack, UIP_NDP_TIMER);
|
|
-}
|
|
-
|
|
-void uip_process(struct uip_stack *ustack, u8_t flag)
|
|
-{
|
|
- u8_t c;
|
|
- u16_t tmp16;
|
|
- register struct uip_conn *uip_connr = ustack->uip_conn;
|
|
-
|
|
- u16_t uip_iph_len = 0;
|
|
- u16_t uip_ip_udph_len = 0;
|
|
- u16_t uip_ip_tcph_len = 0;
|
|
- struct ip6_hdr *ipv6_hdr = NULL;
|
|
- struct uip_tcp_ipv4_hdr *tcp_ipv4_hdr = NULL;
|
|
- struct uip_tcp_hdr *tcp_hdr = NULL;
|
|
- struct uip_icmpv4_hdr *icmpv4_hdr = NULL;
|
|
- struct uip_icmpv6_hdr *icmpv6_hdr __attribute__((__unused__)) = NULL;
|
|
- struct uip_udp_hdr *udp_hdr = NULL;
|
|
-
|
|
- /* Drop invalid packets */
|
|
- if (ustack->uip_buf == NULL) {
|
|
- LOG_ERR(PFX "ustack->uip_buf == NULL.");
|
|
- return;
|
|
- }
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- uint8_t *buf;
|
|
- uip_iph_len = UIP_IPv6_H_LEN;
|
|
- uip_ip_udph_len = UIP_IPv6_UDPH_LEN;
|
|
- uip_ip_tcph_len = UIP_IPv6_TCPH_LEN;
|
|
-
|
|
- ipv6_hdr = (struct ip6_hdr *)ustack->network_layer;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv6_hdr);
|
|
- tcp_hdr = (struct uip_tcp_hdr *)buf;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv6_hdr);
|
|
- udp_hdr = (struct uip_udp_hdr *)buf;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv6_hdr);
|
|
- icmpv6_hdr = (struct uip_icmpv6_hdr *)buf;
|
|
- } else {
|
|
- uint8_t *buf;
|
|
-
|
|
- uip_iph_len = UIP_IPv4_H_LEN;
|
|
- uip_ip_udph_len = UIP_IPv4_UDPH_LEN;
|
|
- uip_ip_tcph_len = UIP_IPv4_TCPH_LEN;
|
|
-
|
|
- tcp_ipv4_hdr = (struct uip_tcp_ipv4_hdr *)ustack->network_layer;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv4_hdr);
|
|
- tcp_hdr = (struct uip_tcp_hdr *)buf;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv4_hdr);
|
|
- icmpv4_hdr = (struct uip_icmpv4_hdr *)buf;
|
|
-
|
|
- buf = ustack->network_layer;
|
|
- buf += sizeof(struct uip_ipv4_hdr);
|
|
- udp_hdr = (struct uip_udp_hdr *)buf;
|
|
- } /* End of ipv6 */
|
|
-
|
|
-#if UIP_UDP
|
|
- if (flag == UIP_UDP_SEND_CONN)
|
|
- goto udp_send;
|
|
-#endif /* UIP_UDP */
|
|
- ustack->uip_sappdata = ustack->uip_appdata = ustack->network_layer +
|
|
- uip_ip_tcph_len;
|
|
-
|
|
- /* Check if we were invoked because of a poll request for a
|
|
- particular connection. */
|
|
- if (flag == UIP_POLL_REQUEST) {
|
|
- if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED
|
|
- && !uip_outstanding(uip_connr)) {
|
|
- ustack->uip_flags = UIP_POLL;
|
|
- UIP_APPCALL(ustack);
|
|
- goto appsend;
|
|
- }
|
|
- goto drop;
|
|
-
|
|
- /* Check if we were invoked because of the perodic timer
|
|
- firing. */
|
|
- } else if (flag == UIP_TIMER) {
|
|
-#if UIP_REASSEMBLY
|
|
- if (uip_reasstmr != 0)
|
|
- --uip_reasstmr;
|
|
-#endif /* UIP_REASSEMBLY */
|
|
- /* Increase the initial sequence number. */
|
|
- if (++ustack->iss[3] == 0) {
|
|
- if (++ustack->iss[2] == 0) {
|
|
- if (++ustack->iss[1] == 0)
|
|
- ++ustack->iss[0];
|
|
- }
|
|
- }
|
|
-
|
|
- /* Reset the length variables. */
|
|
- ustack->uip_len = 0;
|
|
- ustack->uip_slen = 0;
|
|
-
|
|
- /* Check if the connection is in a state in which we simply wait
|
|
- for the connection to time out. If so, we increase the
|
|
- connection's timer and remove the connection if it times
|
|
- out. */
|
|
- if (uip_connr->tcpstateflags == UIP_TIME_WAIT ||
|
|
- uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
|
|
- ++(uip_connr->timer);
|
|
- if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT)
|
|
- uip_connr->tcpstateflags = UIP_CLOSED;
|
|
- } else if (uip_connr->tcpstateflags != UIP_CLOSED) {
|
|
- /* If the connection has outstanding data, we increase
|
|
- the connection's timer and see if it has reached the
|
|
- RTO value in which case we retransmit. */
|
|
- if (uip_outstanding(uip_connr)) {
|
|
- if (uip_connr->timer-- == 0) {
|
|
- if (uip_connr->nrtx == UIP_MAXRTX ||
|
|
- ((uip_connr->tcpstateflags ==
|
|
- UIP_SYN_SENT
|
|
- || uip_connr->tcpstateflags ==
|
|
- UIP_SYN_RCVD)
|
|
- && uip_connr->nrtx ==
|
|
- UIP_MAXSYNRTX)) {
|
|
- uip_connr->tcpstateflags =
|
|
- UIP_CLOSED;
|
|
-
|
|
- /* We call UIP_APPCALL() with
|
|
- uip_flags set to UIP_TIMEDOUT
|
|
- to inform the application
|
|
- that the connection has timed
|
|
- out. */
|
|
- ustack->uip_flags =
|
|
- UIP_TIMEDOUT;
|
|
- UIP_APPCALL(ustack);
|
|
-
|
|
- /* We also send a reset packet
|
|
- to the remote host. */
|
|
- tcp_hdr->flags =
|
|
- TCP_RST | TCP_ACK;
|
|
- goto tcp_send_nodata;
|
|
- }
|
|
-
|
|
- /* Exponential backoff. */
|
|
- uip_connr->timer =
|
|
- UIP_RTO << (uip_connr->nrtx >
|
|
- 4 ? 4 : uip_connr->
|
|
- nrtx);
|
|
- ++(uip_connr->nrtx);
|
|
-
|
|
- /* Ok, so we need to retransmit.
|
|
- We do this differently depending on
|
|
- which state we are in.
|
|
- In ESTABLISHED, we call upon the
|
|
- application so that it may prepare
|
|
- the data for the retransmit.
|
|
- In SYN_RCVD, we resend the SYNACK
|
|
- that we sent earlier and in LAST_ACK
|
|
- we have to retransmit our FINACK. */
|
|
- ++ustack->stats.tcp.rexmit;
|
|
- switch (uip_connr->
|
|
- tcpstateflags & UIP_TS_MASK) {
|
|
- case UIP_SYN_RCVD:
|
|
- /* In the SYN_RCVD state, we
|
|
- should retransmit our SYNACK
|
|
- */
|
|
- goto tcp_send_synack;
|
|
-#if UIP_ACTIVE_OPEN
|
|
- case UIP_SYN_SENT:
|
|
- /* In the SYN_SENT state,
|
|
- we retransmit out SYN. */
|
|
- tcp_hdr->flags = 0;
|
|
- goto tcp_send_syn;
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-
|
|
- case UIP_ESTABLISHED:
|
|
- /* In the ESTABLISHED state,
|
|
- we call upon the application
|
|
- to do the actual retransmit
|
|
- after which we jump into
|
|
- the code for sending out the
|
|
- packet (the apprexmit
|
|
- label). */
|
|
- ustack->uip_flags = UIP_REXMIT;
|
|
- UIP_APPCALL(ustack);
|
|
- goto apprexmit;
|
|
-
|
|
- case UIP_FIN_WAIT_1:
|
|
- case UIP_CLOSING:
|
|
- case UIP_LAST_ACK:
|
|
- /* In all these states we should
|
|
- retransmit a FINACK. */
|
|
- goto tcp_send_finack;
|
|
-
|
|
- }
|
|
- }
|
|
- } else if ((uip_connr->tcpstateflags & UIP_TS_MASK) ==
|
|
- UIP_ESTABLISHED) {
|
|
- /* If there was no need for a retransmission,
|
|
- we poll the application for new data. */
|
|
- ustack->uip_flags = UIP_POLL;
|
|
- UIP_APPCALL(ustack);
|
|
- goto appsend;
|
|
- }
|
|
- }
|
|
- goto drop;
|
|
- } /* End of UIP_TIMER */
|
|
-#if UIP_UDP
|
|
- if (flag == UIP_UDP_TIMER) {
|
|
- /* This is for IPv4 DHCP only! */
|
|
- if (ustack->uip_udp_conn->lport != 0) {
|
|
- ustack->uip_conn = NULL;
|
|
- ustack->uip_sappdata = ustack->uip_appdata =
|
|
- ustack->network_layer + uip_ip_udph_len;
|
|
- ustack->uip_len = ustack->uip_slen = 0;
|
|
- ustack->uip_flags = UIP_POLL;
|
|
- UIP_UDP_APPCALL(ustack);
|
|
- goto udp_send;
|
|
- } else {
|
|
- goto drop;
|
|
- }
|
|
- }
|
|
-#endif
|
|
- if (flag == UIP_NDP_TIMER) {
|
|
- /* This is for IPv6 NDP Only! */
|
|
- if (1) { /* If NDP engine active */
|
|
- ustack->uip_len = ustack->uip_slen = 0;
|
|
- ustack->uip_flags = UIP_POLL;
|
|
- goto ndp_send;
|
|
- }
|
|
- }
|
|
-
|
|
- /* This is where the input processing starts. */
|
|
- ++ustack->stats.ip.recv;
|
|
-
|
|
- /* Start of IP input header processing code. */
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- u8_t version = ((ipv6_hdr->ip6_vfc) & 0xf0) >> 4;
|
|
-
|
|
- /* Check validity of the IP header. */
|
|
- if (version != 0x6) { /* IP version and header length. */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.vhlerr;
|
|
- LOG_DEBUG(PFX "ipv6: invalid version(0x%x).", version);
|
|
- goto drop;
|
|
- }
|
|
- } else {
|
|
- /* Check validity of the IP header. */
|
|
- if (tcp_ipv4_hdr->vhl != 0x45) {
|
|
- /* IP version and header length. */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.vhlerr;
|
|
- LOG_DEBUG(PFX
|
|
- "ipv4: invalid version or header length: "
|
|
- "0x%x.",
|
|
- tcp_ipv4_hdr->vhl);
|
|
- goto drop;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Check the size of the packet. If the size reported to us in
|
|
- uip_len is smaller the size reported in the IP header, we assume
|
|
- that the packet has been corrupted in transit. If the size of
|
|
- uip_len is larger than the size reported in the IP packet header,
|
|
- the packet has been padded and we set uip_len to the correct
|
|
- value.. */
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- u16_t len = ntohs(ipv6_hdr->ip6_plen);
|
|
- if (len > ustack->uip_len) {
|
|
- LOG_DEBUG(PFX
|
|
- "ip: packet shorter than reported in IP header"
|
|
- ":IPv6_BUF(ustack)->len: %d ustack->uip_len: "
|
|
- "%d", len, ustack->uip_len);
|
|
- goto drop;
|
|
- }
|
|
- } else {
|
|
- if ((tcp_ipv4_hdr->len[0] << 8) +
|
|
- tcp_ipv4_hdr->len[1] <= ustack->uip_len) {
|
|
- ustack->uip_len = (tcp_ipv4_hdr->len[0] << 8) +
|
|
- tcp_ipv4_hdr->len[1];
|
|
- } else {
|
|
- LOG_DEBUG(PFX
|
|
- "ip: packet shorter than reported in IP header"
|
|
- ":tcp_ipv4_hdr->len: %d ustack->uip_len:%d.",
|
|
- (tcp_ipv4_hdr->len[0] << 8) +
|
|
- tcp_ipv4_hdr->len[1], ustack->uip_len);
|
|
- goto drop;
|
|
- }
|
|
- }
|
|
-
|
|
- if (!is_ipv6(ustack)) {
|
|
- /* Check the fragment flag. */
|
|
- if ((tcp_ipv4_hdr->ipoffset[0] & 0x3f) != 0 ||
|
|
- tcp_ipv4_hdr->ipoffset[1] != 0) {
|
|
-#if UIP_REASSEMBLY
|
|
- uip_len = uip_reass();
|
|
- if (uip_len == 0)
|
|
- goto drop;
|
|
-#else /* UIP_REASSEMBLY */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.fragerr;
|
|
- LOG_WARN(PFX "ip: fragment dropped.");
|
|
- goto drop;
|
|
-#endif /* UIP_REASSEMBLY */
|
|
- }
|
|
- }
|
|
-
|
|
- if (!is_ipv6(ustack)) {
|
|
- /* ipv4 */
|
|
- if (uip_ip4addr_cmp(ustack->hostaddr, all_zeroes_addr4)) {
|
|
- /* If we are configured to use ping IP address
|
|
- configuration and hasn't been assigned an IP
|
|
- address yet, we accept all ICMP packets. */
|
|
-#if UIP_PINGADDRCONF && !UIP_CONF_IPV6
|
|
- if (tcp_ipv4_hdr->proto == UIP_PROTO_ICMP) {
|
|
- LOG_WARN(PFX
|
|
- "ip: possible ping config packet "
|
|
- "received.");
|
|
- goto icmp_input;
|
|
- } else {
|
|
- LOG_WARN(PFX
|
|
- "ip: packet dropped since no "
|
|
- "address assigned.");
|
|
- goto drop;
|
|
- }
|
|
-#endif /* UIP_PINGADDRCONF */
|
|
- } else {
|
|
- int broadcast_addr = 0xFFFFFFFF;
|
|
- /* If IP broadcast support is configured, we check for
|
|
- a broadcast UDP packet, which may be destined to us
|
|
- */
|
|
- if ((tcp_ipv4_hdr->proto == UIP_PROTO_UDP) &&
|
|
- (uip_ip4addr_cmp
|
|
- (tcp_ipv4_hdr->destipaddr, &broadcast_addr))
|
|
- /*&&
|
|
- uip_ipchksum() == 0xffff */
|
|
- ) {
|
|
- goto udp_input;
|
|
- }
|
|
-
|
|
- /* Check if the packet is destined for our IP address
|
|
- */
|
|
- if (!uip_ip4addr_cmp(tcp_ipv4_hdr->destipaddr,
|
|
- ustack->hostaddr)) {
|
|
- ++ustack->stats.ip.drop;
|
|
- goto drop;
|
|
- }
|
|
- }
|
|
- if (uip_ipchksum(ustack) != 0xffff) {
|
|
- /* Compute and check the IP header checksum. */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.chkerr;
|
|
- LOG_ERR(PFX "ip: bad checksum.");
|
|
- goto drop;
|
|
- }
|
|
- } /* End of ipv4 */
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- if (ipv6_hdr->ip6_nxt == UIP_PROTO_TCP) {
|
|
- /* Check for TCP packet. If so, proceed with TCP input
|
|
- processing. */
|
|
- goto ndp_newdata;
|
|
- }
|
|
-#if UIP_UDP
|
|
- if (ipv6_hdr->ip6_nxt == UIP_PROTO_UDP)
|
|
- goto ndp_newdata;
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
- /* This is IPv6 ICMPv6 processing code. */
|
|
- if (ipv6_hdr->ip6_nxt != UIP_PROTO_ICMP6) {
|
|
- /* We only allow ICMPv6 packets from here. */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.protoerr;
|
|
- goto drop;
|
|
- }
|
|
-
|
|
- ++ustack->stats.icmp.recv;
|
|
-
|
|
-ndp_newdata:
|
|
- /* This call is to handle the IPv6 Network Discovery Protocol */
|
|
- ustack->uip_flags = UIP_NEWDATA;
|
|
- ustack->uip_slen = 0;
|
|
-ndp_send:
|
|
- UIP_NDP_CALL(ustack);
|
|
- if (ustack->uip_slen != 0) {
|
|
- ustack->uip_len = ustack->uip_slen;
|
|
- goto send;
|
|
- } else {
|
|
- goto drop;
|
|
- }
|
|
- } else {
|
|
- /* IPv4 Processing */
|
|
- if (tcp_ipv4_hdr->proto == UIP_PROTO_TCP) {
|
|
- /* Check for TCP packet. If so, proceed with TCP input
|
|
- processing. */
|
|
- goto tcp_input;
|
|
- }
|
|
-#if UIP_UDP
|
|
- if (tcp_ipv4_hdr->proto == UIP_PROTO_UDP)
|
|
- goto udp_input;
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
- /* ICMPv4 processing code follows. */
|
|
- if (tcp_ipv4_hdr->proto != UIP_PROTO_ICMP) {
|
|
- /* We only allow ICMP packets from here. */
|
|
- ++ustack->stats.ip.drop;
|
|
- ++ustack->stats.ip.protoerr;
|
|
- LOG_DEBUG(PFX "ip: neither tcp nor icmp.");
|
|
- goto drop;
|
|
- }
|
|
-#if UIP_PINGADDRCONF
|
|
-icmp_input:
|
|
-#endif /* UIP_PINGADDRCONF */
|
|
- ++ustack->stats.icmp.recv;
|
|
-
|
|
- if (icmpv4_hdr->type == ICMP_ECHO_REPLY) {
|
|
- if (process_icmp_packet(icmpv4_hdr, ustack) == 0)
|
|
- goto drop;
|
|
- }
|
|
-
|
|
- /* ICMP echo (i.e., ping) processing. This is simple, we only
|
|
- change the ICMP type from ECHO to ECHO_REPLY and adjust the
|
|
- ICMP checksum before we return the packet. */
|
|
- if (icmpv4_hdr->type != ICMP_ECHO) {
|
|
- ++ustack->stats.icmp.drop;
|
|
- ++ustack->stats.icmp.typeerr;
|
|
- LOG_DEBUG(PFX "icmp: not icmp echo.");
|
|
- goto drop;
|
|
- }
|
|
-
|
|
- /* If we are configured to use ping IP address assignment, we
|
|
- use the destination IP address of this ping packet and assign
|
|
- it to ourself. */
|
|
-#if UIP_PINGADDRCONF
|
|
- if ((ustack->hostaddr[0] | ustack->hostaddr[1]) == 0) {
|
|
- ustack->hostaddr[0] = tcp_ipv4_hdr->destipaddr[0];
|
|
- ustack->hostaddr[1] = tcp_ipv4_hdr->destipaddr[1];
|
|
- }
|
|
-#endif /* UIP_PINGADDRCONF */
|
|
-
|
|
- icmpv4_hdr->type = ICMP_ECHO_REPLY;
|
|
-
|
|
- if (icmpv4_hdr->icmpchksum >= htons(0xffff -
|
|
- (ICMP_ECHO << 8))) {
|
|
- icmpv4_hdr->icmpchksum += htons(ICMP_ECHO << 8) + 1;
|
|
- } else {
|
|
- icmpv4_hdr->icmpchksum += htons(ICMP_ECHO << 8);
|
|
- }
|
|
-
|
|
- /* Swap IP addresses. */
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
|
|
- tcp_ipv4_hdr->srcipaddr);
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
|
|
-
|
|
- ++ustack->stats.icmp.sent;
|
|
- goto send;
|
|
-
|
|
- /* End of IPv4 input header processing code. */
|
|
- }
|
|
-
|
|
-#if UIP_UDP
|
|
- /* UDP input processing. */
|
|
-udp_input:
|
|
- /* UDP processing is really just a hack. We don't do anything to the
|
|
- UDP/IP headers, but let the UDP application do all the hard
|
|
- work. If the application sets uip_slen, it has a packet to
|
|
- send. */
|
|
-#if UIP_UDP_CHECKSUMS
|
|
- ustack->uip_len = ustack->uip_len - uip_ip_udph_len;
|
|
- ustack->uip_appdata = ustack->network_layer + uip_ip_udph_len;
|
|
- if (UDPBUF(ustack)->udpchksum != 0 && uip_udpchksum(ustack) != 0xffff) {
|
|
- ++ustack->stats.udp.drop;
|
|
- ++ustack->stats.udp.chkerr;
|
|
- LOG_DEBUG(PFX "udp: bad checksum.");
|
|
- goto drop;
|
|
- }
|
|
-#else /* UIP_UDP_CHECKSUMS */
|
|
- uip_len = uip_len - uip_ip_udph_len;
|
|
-#endif /* UIP_UDP_CHECKSUMS */
|
|
-
|
|
- if (is_ipv6(ustack))
|
|
- goto udp_found;
|
|
-
|
|
- /* Demultiplex this UDP packet between the UDP "connections". */
|
|
- for (ustack->uip_udp_conn = &ustack->uip_udp_conns[0];
|
|
- ustack->uip_udp_conn < &ustack->uip_udp_conns[UIP_UDP_CONNS];
|
|
- ++ustack->uip_udp_conn) {
|
|
- /* If the local UDP port is non-zero, the connection is
|
|
- considered to be used. If so, the local port number is
|
|
- checked against the destination port number in the
|
|
- received packet. If the two port
|
|
- numbers match, the remote port number is checked if the
|
|
- connection is bound to a remote port. Finally, if the
|
|
- connection is bound to a remote IP address, the source IP
|
|
- address of the packet is checked. */
|
|
-
|
|
- if (ustack->uip_udp_conn->lport != 0 &&
|
|
- UDPBUF(ustack)->destport == ustack->uip_udp_conn->lport &&
|
|
- (ustack->uip_udp_conn->rport == 0 ||
|
|
- UDPBUF(ustack)->srcport == ustack->uip_udp_conn->rport) &&
|
|
- (uip_ip4addr_cmp(ustack->uip_udp_conn->ripaddr,
|
|
- all_zeroes_addr4) ||
|
|
- uip_ip4addr_cmp(ustack->uip_udp_conn->ripaddr,
|
|
- all_ones_addr4) ||
|
|
- uip_ip4addr_cmp(tcp_ipv4_hdr->srcipaddr,
|
|
- ustack->uip_udp_conn->ripaddr))) {
|
|
- goto udp_found;
|
|
- }
|
|
- }
|
|
- LOG_DEBUG(PFX
|
|
- "udp: no matching connection found: dest port: %d src port: "
|
|
- "%d", udp_hdr->destport, udp_hdr->srcport);
|
|
- goto drop;
|
|
-
|
|
-udp_found:
|
|
- ustack->uip_conn = NULL;
|
|
- ustack->uip_flags = UIP_NEWDATA;
|
|
- ustack->uip_sappdata = ustack->uip_appdata = ustack->network_layer +
|
|
- uip_ip_udph_len;
|
|
- ustack->uip_slen = 0;
|
|
- if (is_ipv6(ustack))
|
|
- UIP_NDP_CALL(ustack);
|
|
- else
|
|
- UIP_UDP_APPCALL(ustack);
|
|
-udp_send:
|
|
- if (ustack->uip_slen == 0)
|
|
- goto drop;
|
|
-
|
|
- ustack->uip_len = ustack->uip_slen + uip_ip_udph_len;
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- goto ip_send_nolen;
|
|
- } else {
|
|
- tcp_ipv4_hdr->len[0] = (ustack->uip_len >> 8);
|
|
- tcp_ipv4_hdr->len[1] = (ustack->uip_len & 0xff);
|
|
- tcp_ipv4_hdr->ttl = ustack->uip_udp_conn->ttl;
|
|
- tcp_ipv4_hdr->proto = UIP_PROTO_UDP;
|
|
- }
|
|
-
|
|
- udp_hdr->udplen = htons(ustack->uip_slen + UIP_UDPH_LEN);
|
|
- udp_hdr->udpchksum = 0;
|
|
-
|
|
- udp_hdr->srcport = ustack->uip_udp_conn->lport;
|
|
- udp_hdr->destport = ustack->uip_udp_conn->rport;
|
|
-
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
|
|
- ustack->uip_udp_conn->ripaddr);
|
|
-
|
|
- ustack->uip_appdata = ustack->network_layer + uip_ip_tcph_len;
|
|
-
|
|
- if (ustack->uip_buf == NULL) {
|
|
- LOG_WARN(PFX "uip_buf == NULL on udp send");
|
|
- goto drop;
|
|
- }
|
|
-#if UIP_UDP_CHECKSUMS
|
|
- /* Calculate UDP checksum. */
|
|
- udp_hdr->udpchksum = ~(uip_udpchksum(ustack));
|
|
- if (udp_hdr->udpchksum == 0)
|
|
- udp_hdr->udpchksum = 0xffff;
|
|
-#endif /* UIP_UDP_CHECKSUMS */
|
|
-
|
|
- goto ip_send_nolen;
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
- /* TCP input processing. */
|
|
-tcp_input:
|
|
- ++ustack->stats.tcp.recv;
|
|
-
|
|
- /* Start of TCP input header processing code. */
|
|
-
|
|
- if (uip_tcpchksum(ustack) != 0xffff) { /* Compute and check the TCP
|
|
- checksum. */
|
|
- ++ustack->stats.tcp.drop;
|
|
- ++ustack->stats.tcp.chkerr;
|
|
- LOG_WARN(PFX "tcp: bad checksum.");
|
|
- goto drop;
|
|
- }
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- /* Demultiplex this segment. */
|
|
- /* First check any active connections. */
|
|
- for (uip_connr = &ustack->uip_conns[0];
|
|
- uip_connr <= &ustack->uip_conns[UIP_CONNS - 1];
|
|
- ++uip_connr) {
|
|
- if (uip_connr->tcpstateflags != UIP_CLOSED &&
|
|
- tcp_hdr->destport == uip_connr->lport &&
|
|
- tcp_hdr->srcport == uip_connr->rport &&
|
|
- uip_ip6addr_cmp(IPv6_BUF(ustack)->srcipaddr,
|
|
- uip_connr->ripaddr)) {
|
|
- goto found;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- /* Demultiplex this segment. */
|
|
- /* First check any active connections. */
|
|
- for (uip_connr = &ustack->uip_conns[0];
|
|
- uip_connr <= &ustack->uip_conns[UIP_CONNS - 1];
|
|
- ++uip_connr) {
|
|
- if (uip_connr->tcpstateflags != UIP_CLOSED &&
|
|
- tcp_hdr->destport == uip_connr->lport &&
|
|
- tcp_hdr->srcport == uip_connr->rport &&
|
|
- uip_ip4addr_cmp(tcp_ipv4_hdr->srcipaddr,
|
|
- uip_connr->ripaddr)) {
|
|
- goto found;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* If we didn't find and active connection that expected the packet,
|
|
- either this packet is an old duplicate, or this is a SYN packet
|
|
- destined for a connection in LISTEN. If the SYN flag isn't set,
|
|
- it is an old packet and we send a RST. */
|
|
- if ((tcp_hdr->flags & TCP_CTL) != TCP_SYN)
|
|
- goto reset;
|
|
-
|
|
- tmp16 = tcp_hdr->destport;
|
|
- /* Next, check listening connections. */
|
|
- for (c = 0; c < UIP_LISTENPORTS; ++c) {
|
|
- if (tmp16 == ustack->uip_listenports[c])
|
|
- goto found_listen;
|
|
- }
|
|
-
|
|
- /* No matching connection found, so we send a RST packet. */
|
|
- ++ustack->stats.tcp.synrst;
|
|
-reset:
|
|
-
|
|
- /* We do not send resets in response to resets. */
|
|
- if (tcp_hdr->flags & TCP_RST)
|
|
- goto drop;
|
|
-
|
|
- ++ustack->stats.tcp.rst;
|
|
-
|
|
- tcp_hdr->flags = TCP_RST | TCP_ACK;
|
|
- ustack->uip_len = uip_ip_tcph_len;
|
|
- tcp_hdr->tcpoffset = 5 << 4;
|
|
-
|
|
- /* Flip the seqno and ackno fields in the TCP header. */
|
|
- c = tcp_hdr->seqno[3];
|
|
- tcp_hdr->seqno[3] = tcp_hdr->ackno[3];
|
|
- tcp_hdr->ackno[3] = c;
|
|
-
|
|
- c = tcp_hdr->seqno[2];
|
|
- tcp_hdr->seqno[2] = tcp_hdr->ackno[2];
|
|
- tcp_hdr->ackno[2] = c;
|
|
-
|
|
- c = tcp_hdr->seqno[1];
|
|
- tcp_hdr->seqno[1] = tcp_hdr->ackno[1];
|
|
- tcp_hdr->ackno[1] = c;
|
|
-
|
|
- c = tcp_hdr->seqno[0];
|
|
- tcp_hdr->seqno[0] = tcp_hdr->ackno[0];
|
|
- tcp_hdr->ackno[0] = c;
|
|
-
|
|
- /* We also have to increase the sequence number we are
|
|
- acknowledging. If the least significant byte overflowed, we need
|
|
- to propagate the carry to the other bytes as well. */
|
|
- if (++tcp_hdr->ackno[3] == 0) {
|
|
- if (++tcp_hdr->ackno[2] == 0) {
|
|
- if (++tcp_hdr->ackno[1] == 0)
|
|
- ++tcp_hdr->ackno[0];
|
|
- }
|
|
- }
|
|
-
|
|
- /* Swap port numbers. */
|
|
- tmp16 = tcp_hdr->srcport;
|
|
- tcp_hdr->srcport = tcp_hdr->destport;
|
|
- tcp_hdr->destport = tmp16;
|
|
-
|
|
- /* Swap IP addresses. */
|
|
- if (is_ipv6(ustack)) {
|
|
- uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
|
|
- IPv6_BUF(ustack)->srcipaddr);
|
|
- uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
|
|
- ustack->hostaddr6);
|
|
- } else {
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr,
|
|
- tcp_ipv4_hdr->srcipaddr);
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
|
|
- }
|
|
-
|
|
- /* And send out the RST packet! */
|
|
- goto tcp_send_noconn;
|
|
-
|
|
- /* This label will be jumped to if we matched the incoming packet
|
|
- with a connection in LISTEN. In that case, we should create a new
|
|
- connection and send a SYNACK in return. */
|
|
-found_listen:
|
|
- /* First we check if there are any connections avaliable. Unused
|
|
- connections are kept in the same table as used connections, but
|
|
- unused ones have the tcpstate set to CLOSED. Also, connections in
|
|
- TIME_WAIT are kept track of and we'll use the oldest one if no
|
|
- CLOSED connections are found. Thanks to Eddie C. Dost for a very
|
|
- nice algorithm for the TIME_WAIT search. */
|
|
- uip_connr = 0;
|
|
- for (c = 0; c < UIP_CONNS; ++c) {
|
|
- if (ustack->uip_conns[c].tcpstateflags == UIP_CLOSED) {
|
|
- uip_connr = &ustack->uip_conns[c];
|
|
- break;
|
|
- }
|
|
- if (ustack->uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
|
|
- if (uip_connr == 0 ||
|
|
- ustack->uip_conns[c].timer > uip_connr->timer) {
|
|
- uip_connr = &ustack->uip_conns[c];
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (uip_connr == 0) {
|
|
- /* All connections are used already, we drop packet and hope
|
|
- that the remote end will retransmit the packet at a time when
|
|
- we have more spare connections. */
|
|
- ++ustack->stats.tcp.syndrop;
|
|
- LOG_WARN(PFX "tcp: found no unused connections.");
|
|
- goto drop;
|
|
- }
|
|
- ustack->uip_conn = uip_connr;
|
|
-
|
|
- /* Fill in the necessary fields for the new connection. */
|
|
- uip_connr->rto = uip_connr->timer = UIP_RTO;
|
|
- uip_connr->sa = 0;
|
|
- uip_connr->sv = 4;
|
|
- uip_connr->nrtx = 0;
|
|
- uip_connr->lport = tcp_hdr->destport;
|
|
- uip_connr->rport = tcp_hdr->srcport;
|
|
- if (is_ipv6(ustack)) {
|
|
- uip_ip6addr_copy(uip_connr->ripaddr,
|
|
- IPv6_BUF(ustack)->srcipaddr);
|
|
- } else {
|
|
- uip_ip4addr_copy(uip_connr->ripaddr, tcp_ipv4_hdr->srcipaddr);
|
|
- }
|
|
- uip_connr->tcpstateflags = UIP_SYN_RCVD;
|
|
-
|
|
- uip_connr->snd_nxt[0] = ustack->iss[0];
|
|
- uip_connr->snd_nxt[1] = ustack->iss[1];
|
|
- uip_connr->snd_nxt[2] = ustack->iss[2];
|
|
- uip_connr->snd_nxt[3] = ustack->iss[3];
|
|
- uip_connr->len = 1;
|
|
-
|
|
- /* rcv_nxt should be the seqno from the incoming packet + 1. */
|
|
- uip_connr->rcv_nxt[3] = tcp_hdr->seqno[3];
|
|
- uip_connr->rcv_nxt[2] = tcp_hdr->seqno[2];
|
|
- uip_connr->rcv_nxt[1] = tcp_hdr->seqno[1];
|
|
- uip_connr->rcv_nxt[0] = tcp_hdr->seqno[0];
|
|
- uip_add_rcv_nxt(ustack, 1);
|
|
-
|
|
- /* Parse the TCP MSS option, if present. */
|
|
- if ((tcp_hdr->tcpoffset & 0xf0) > 0x50) {
|
|
- for (c = 0; c < ((tcp_hdr->tcpoffset >> 4) - 5) << 2;) {
|
|
- ustack->opt =
|
|
- ustack->uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + c];
|
|
- if (ustack->opt == TCP_OPT_END) {
|
|
- /* End of options. */
|
|
- break;
|
|
- } else if (ustack->opt == TCP_OPT_NOOP) {
|
|
- ++c;
|
|
- /* NOP option. */
|
|
- } else if (ustack->opt == TCP_OPT_MSS &&
|
|
- ustack->uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 1 + c] ==
|
|
- TCP_OPT_MSS_LEN) {
|
|
- /* An MSS option with the right option length.*/
|
|
- tmp16 =
|
|
- ((u16_t) ustack->
|
|
- uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 2 +
|
|
- c] << 8) | (u16_t) ustack->
|
|
- uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 3 +
|
|
- c];
|
|
- uip_connr->initialmss = uip_connr->mss =
|
|
- tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
|
|
-
|
|
- /* And we are done processing options. */
|
|
- break;
|
|
- } else {
|
|
- /* All other options have a length field, so
|
|
- that we easily can skip past them. */
|
|
- if (ustack->uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 1 + c] == 0) {
|
|
- /* If the length field is zero, the
|
|
- options are malformed
|
|
- and we don't process them further. */
|
|
- break;
|
|
- }
|
|
- if ((ustack->uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 1 + c]) > (256 - c)) {
|
|
- /* u8 overflow, actually there should
|
|
- * never be more than 40 bytes of options */
|
|
- break;
|
|
- }
|
|
- c += ustack->uip_buf[uip_ip_tcph_len + UIP_LLH_LEN + 1 + c];
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Our response will be a SYNACK. */
|
|
-#if UIP_ACTIVE_OPEN
|
|
-tcp_send_synack:
|
|
- tcp_hdr->flags = TCP_ACK;
|
|
-
|
|
-tcp_send_syn:
|
|
- tcp_hdr->flags |= TCP_SYN;
|
|
-#else /* UIP_ACTIVE_OPEN */
|
|
-tcp_send_synack:
|
|
- tcp_hdr->flags = TCP_SYN | TCP_ACK;
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-
|
|
- /* We send out the TCP Maximum Segment Size option with our
|
|
- SYNACK. */
|
|
- tcp_hdr->optdata[0] = TCP_OPT_MSS;
|
|
- tcp_hdr->optdata[1] = TCP_OPT_MSS_LEN;
|
|
- tcp_hdr->optdata[2] = (UIP_TCP_MSS) / 256;
|
|
- tcp_hdr->optdata[3] = (UIP_TCP_MSS) & 255;
|
|
- ustack->uip_len = uip_ip_tcph_len + TCP_OPT_MSS_LEN;
|
|
- tcp_hdr->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
|
|
- goto tcp_send;
|
|
-
|
|
- /* This label will be jumped to if we found an active connection. */
|
|
-found:
|
|
- ustack->uip_conn = uip_connr;
|
|
- ustack->uip_flags = 0;
|
|
- /* We do a very naive form of TCP reset processing; we just accept
|
|
- any RST and kill our connection. We should in fact check if the
|
|
- sequence number of this reset is wihtin our advertised window
|
|
- before we accept the reset. */
|
|
- if (tcp_hdr->flags & TCP_RST) {
|
|
- uip_connr->tcpstateflags = UIP_CLOSED;
|
|
- LOG_WARN(PFX "tcp: got reset, aborting connection.");
|
|
- ustack->uip_flags = UIP_ABORT;
|
|
- UIP_APPCALL(ustack);
|
|
- goto drop;
|
|
- }
|
|
- /* Calculated the length of the data, if the application has sent
|
|
- any data to us. */
|
|
- c = (tcp_hdr->tcpoffset >> 4) << 2;
|
|
- /* uip_len will contain the length of the actual TCP data. This is
|
|
- calculated by subtracing the length of the TCP header (in
|
|
- c) and the length of the IP header (20 bytes). */
|
|
- ustack->uip_len = ustack->uip_len - c - uip_iph_len;
|
|
-
|
|
- /* First, check if the sequence number of the incoming packet is
|
|
- what we're expecting next. If not, we send out an ACK with the
|
|
- correct numbers in. */
|
|
- if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
|
|
- ((tcp_hdr->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
|
|
- if ((ustack->uip_len > 0
|
|
- || ((tcp_hdr->flags & (TCP_SYN | TCP_FIN)) != 0))
|
|
- && (tcp_hdr->seqno[0] != uip_connr->rcv_nxt[0]
|
|
- || tcp_hdr->seqno[1] != uip_connr->rcv_nxt[1]
|
|
- || tcp_hdr->seqno[2] != uip_connr->rcv_nxt[2]
|
|
- || tcp_hdr->seqno[3] != uip_connr->rcv_nxt[3])) {
|
|
- goto tcp_send_ack;
|
|
- }
|
|
- }
|
|
-
|
|
- {
|
|
- u8_t uip_acc32[4];
|
|
-
|
|
- /* Next, check if the incoming segment acks any outstanding
|
|
- data. If so, we update the sequence number, reset the len of
|
|
- the outstanding data, calc RTT estimations, and reset the
|
|
- retransmission timer. */
|
|
- if ((tcp_hdr->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
|
|
- uip_add32(uip_connr->snd_nxt, uip_connr->len,
|
|
- uip_acc32);
|
|
-
|
|
- if (tcp_hdr->ackno[0] == uip_acc32[0] &&
|
|
- tcp_hdr->ackno[1] == uip_acc32[1] &&
|
|
- tcp_hdr->ackno[2] == uip_acc32[2] &&
|
|
- tcp_hdr->ackno[3] == uip_acc32[3]) {
|
|
- /* Update sequence number. */
|
|
- uip_connr->snd_nxt[0] = uip_acc32[0];
|
|
- uip_connr->snd_nxt[1] = uip_acc32[1];
|
|
- uip_connr->snd_nxt[2] = uip_acc32[2];
|
|
- uip_connr->snd_nxt[3] = uip_acc32[3];
|
|
-
|
|
- /* Do RTT estimation, unless we have done
|
|
- retransmissions. */
|
|
- if (uip_connr->nrtx == 0) {
|
|
- signed char m;
|
|
- m = uip_connr->rto - uip_connr->timer;
|
|
- /* This is taken directly from VJs
|
|
- original code in his paper */
|
|
- m = m - (uip_connr->sa >> 3);
|
|
- uip_connr->sa += m;
|
|
- if (m < 0)
|
|
- m = -m;
|
|
- m = m - (uip_connr->sv >> 2);
|
|
- uip_connr->sv += m;
|
|
- uip_connr->rto =
|
|
- (uip_connr->sa >> 3) +
|
|
- uip_connr->sv;
|
|
-
|
|
- }
|
|
- /* Set the acknowledged flag. */
|
|
- ustack->uip_flags = UIP_ACKDATA;
|
|
- /* Reset the retransmission timer. */
|
|
- uip_connr->timer = uip_connr->rto;
|
|
-
|
|
- /* Reset length of outstanding data. */
|
|
- uip_connr->len = 0;
|
|
- }
|
|
-
|
|
- }
|
|
-
|
|
- }
|
|
-
|
|
- /* Do different things depending on in what state the connection is. */
|
|
- switch (uip_connr->tcpstateflags & UIP_TS_MASK) {
|
|
- /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
|
|
- implemented, since we force the application to close when the
|
|
- peer sends a FIN (hence the application goes directly from
|
|
- ESTABLISHED to LAST_ACK). */
|
|
- case UIP_SYN_RCVD:
|
|
- /* In SYN_RCVD we have sent out a SYNACK in response to a SYN,
|
|
- and we are waiting for an ACK that acknowledges the data we
|
|
- sent out the last time. Therefore, we want to have the
|
|
- UIP_ACKDATA flag set.
|
|
- If so, we enter the ESTABLISHED state. */
|
|
- if (ustack->uip_flags & UIP_ACKDATA) {
|
|
- uip_connr->tcpstateflags = UIP_ESTABLISHED;
|
|
- ustack->uip_flags = UIP_CONNECTED;
|
|
- uip_connr->len = 0;
|
|
- if (ustack->uip_len > 0) {
|
|
- ustack->uip_flags |= UIP_NEWDATA;
|
|
- uip_add_rcv_nxt(ustack, ustack->uip_len);
|
|
- }
|
|
- ustack->uip_slen = 0;
|
|
- UIP_APPCALL(ustack);
|
|
- goto appsend;
|
|
- }
|
|
- goto drop;
|
|
-#if UIP_ACTIVE_OPEN
|
|
- case UIP_SYN_SENT:
|
|
- /* In SYN_SENT, we wait for a SYNACK that is sent in response to
|
|
- our SYN. The rcv_nxt is set to sequence number in the SYNACK
|
|
- plus one, and we send an ACK. We move into the ESTABLISHED
|
|
- state. */
|
|
- if ((ustack->uip_flags & UIP_ACKDATA) &&
|
|
- (tcp_hdr->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
|
|
-
|
|
- /* Parse the TCP MSS option, if present. */
|
|
- if ((tcp_hdr->tcpoffset & 0xf0) > 0x50) {
|
|
- for (c = 0;
|
|
- c <
|
|
- ((tcp_hdr->tcpoffset >> 4) - 5) << 2;) {
|
|
- ustack->opt =
|
|
- ustack->uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + c];
|
|
- if (ustack->opt == TCP_OPT_END) {
|
|
- /* End of options. */
|
|
- break;
|
|
- } else if (ustack->opt ==
|
|
- TCP_OPT_NOOP) {
|
|
- ++c;
|
|
- /* NOP option. */
|
|
- } else if (ustack->opt == TCP_OPT_MSS &&
|
|
- ustack->
|
|
- uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 1 +
|
|
- c] ==
|
|
- TCP_OPT_MSS_LEN) {
|
|
- /* An MSS option with the right
|
|
- option length. */
|
|
- tmp16 =
|
|
- (ustack->
|
|
- uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 2 +
|
|
- c] << 8) | ustack->
|
|
- uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 3 +
|
|
- c];
|
|
- uip_connr->initialmss =
|
|
- uip_connr->mss =
|
|
- tmp16 >
|
|
- UIP_TCP_MSS ? UIP_TCP_MSS :
|
|
- tmp16;
|
|
-
|
|
- /* And we are done processing
|
|
- options. */
|
|
- break;
|
|
- } else {
|
|
- /* All other options have a
|
|
- length field, so that we
|
|
- easily can skip past them */
|
|
- if (ustack->
|
|
- uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 1 +
|
|
- c] == 0) {
|
|
- /* If the length field
|
|
- is zero, the options
|
|
- are malformed and we
|
|
- don't process them
|
|
- further. */
|
|
- break;
|
|
- }
|
|
- if ((ustack->uip_buf[uip_ip_tcph_len
|
|
- + UIP_LLH_LEN + 1 +
|
|
- c]) > (256 - c)) {
|
|
- /* u8 overflow, actually there should
|
|
- * never be more than 40 bytes of
|
|
- * options */
|
|
- break;
|
|
- }
|
|
- c += ustack->
|
|
- uip_buf[uip_ip_tcph_len +
|
|
- UIP_LLH_LEN + 1 +
|
|
- c];
|
|
- }
|
|
- }
|
|
- }
|
|
- uip_connr->tcpstateflags = UIP_ESTABLISHED;
|
|
- uip_connr->rcv_nxt[0] = tcp_hdr->seqno[0];
|
|
- uip_connr->rcv_nxt[1] = tcp_hdr->seqno[1];
|
|
- uip_connr->rcv_nxt[2] = tcp_hdr->seqno[2];
|
|
- uip_connr->rcv_nxt[3] = tcp_hdr->seqno[3];
|
|
- uip_add_rcv_nxt(ustack, 1);
|
|
- ustack->uip_flags = UIP_CONNECTED | UIP_NEWDATA;
|
|
- uip_connr->len = 0;
|
|
- ustack->uip_len = 0;
|
|
- ustack->uip_slen = 0;
|
|
- UIP_APPCALL(ustack);
|
|
- goto appsend;
|
|
- }
|
|
- /* Inform the application that the connection failed */
|
|
- ustack->uip_flags = UIP_ABORT;
|
|
- UIP_APPCALL(ustack);
|
|
- /* The connection is closed after we send the RST */
|
|
- ustack->uip_conn->tcpstateflags = UIP_CLOSED;
|
|
- goto reset;
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-
|
|
- case UIP_ESTABLISHED:
|
|
- /* In the ESTABLISHED state, we call upon the application to
|
|
- feed data into the uip_buf. If the UIP_ACKDATA flag is set,
|
|
- the application should put new data into the buffer,
|
|
- otherwise we are retransmitting an old segment, and the
|
|
- application should put that data into the buffer.
|
|
-
|
|
- If the incoming packet is a FIN, we should close the
|
|
- connection on this side as well, and we send out a FIN and
|
|
- enter the LAST_ACK state. We require that there is no
|
|
- outstanding data; otherwise the sequence numbers will be
|
|
- screwed up. */
|
|
-
|
|
- if (tcp_hdr->flags & TCP_FIN
|
|
- && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
|
|
- if (uip_outstanding(uip_connr))
|
|
- goto drop;
|
|
- uip_add_rcv_nxt(ustack, 1 + ustack->uip_len);
|
|
- ustack->uip_flags |= UIP_CLOSE;
|
|
- if (ustack->uip_len > 0)
|
|
- ustack->uip_flags |= UIP_NEWDATA;
|
|
- UIP_APPCALL(ustack);
|
|
- uip_connr->len = 1;
|
|
- uip_connr->tcpstateflags = UIP_LAST_ACK;
|
|
- uip_connr->nrtx = 0;
|
|
-tcp_send_finack:
|
|
- tcp_hdr->flags = TCP_FIN | TCP_ACK;
|
|
- goto tcp_send_nodata;
|
|
- }
|
|
-
|
|
- /* Check the URG flag. If this is set, the segment carries
|
|
- urgent data that we must pass to the application. */
|
|
- if ((tcp_hdr->flags & TCP_URG) != 0) {
|
|
-#if UIP_URGDATA > 0
|
|
- uip_urglen = (tcp_hdr->urgp[0] << 8) | tcp_hdr->urgp[1];
|
|
- if (uip_urglen > uip_len) {
|
|
- /* There is more urgent data in the next segment
|
|
- to come. */
|
|
- uip_urglen = uip_len;
|
|
- }
|
|
- uip_add_rcv_nxt(uip_urglen);
|
|
- uip_len -= uip_urglen;
|
|
- uip_urgdata = uip_appdata;
|
|
- uip_appdata += uip_urglen;
|
|
- } else {
|
|
- uip_urglen = 0;
|
|
-#else /* UIP_URGDATA > 0 */
|
|
- tmp16 = (tcp_hdr->urgp[0] << 8) | tcp_hdr->urgp[1];
|
|
- if (tmp16 <= ustack->uip_len) {
|
|
- ustack->uip_appdata = ((char *)ustack->uip_appdata) + tmp16;
|
|
- ustack->uip_len -= tmp16;
|
|
- } else {
|
|
- /* invalid urgent pointer length greater than frame */
|
|
- /* we're discarding urgent data anyway, throw it all out */
|
|
- ustack->uip_appdata = ((char *)ustack->uip_appdata) + ustack->uip_len;
|
|
- ustack->uip_len = 0;
|
|
- }
|
|
-#endif /* UIP_URGDATA > 0 */
|
|
- }
|
|
-
|
|
- /* If uip_len > 0 we have TCP data in the packet, and we flag
|
|
- this by setting the UIP_NEWDATA flag and update the sequence
|
|
- number we acknowledge. If the application has stopped the
|
|
- dataflow using uip_stop(), we must not accept any data
|
|
- packets from the remote host. */
|
|
- if (ustack->uip_len > 0
|
|
- && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
|
|
- ustack->uip_flags |= UIP_NEWDATA;
|
|
- uip_add_rcv_nxt(ustack, ustack->uip_len);
|
|
- }
|
|
-
|
|
- /* Check if the available buffer space advertised by the other
|
|
- end is smaller than the initial MSS for this connection.
|
|
- If so, we set the current MSS to the window size to ensure
|
|
- that the application does not send more data than the other
|
|
- end can handle.
|
|
-
|
|
- If the remote host advertises a zero window, we set the MSS
|
|
- to the initial MSS so that the application will send an
|
|
- entire MSS of data. This data will not be acknowledged by
|
|
- the receiver, and the application will retransmit it.
|
|
- This is called the "persistent timer" and uses the
|
|
- retransmission mechanim.
|
|
- */
|
|
- tmp16 =
|
|
- ((u16_t) tcp_hdr->wnd[0] << 8) + (u16_t) tcp_hdr->wnd[1];
|
|
- if (tmp16 > uip_connr->initialmss || tmp16 == 0)
|
|
- tmp16 = uip_connr->initialmss;
|
|
- uip_connr->mss = tmp16;
|
|
-
|
|
- /* If this packet constitutes an ACK for outstanding data
|
|
- (flagged by the UIP_ACKDATA flag, we should call the
|
|
- application since it might want to send more data.
|
|
- If the incoming packet had data from the peer
|
|
- (as flagged by the UIP_NEWDATA flag), the application
|
|
- must also be notified.
|
|
-
|
|
- When the application is called, the global variable uip_len
|
|
- contains the length of the incoming data. The application can
|
|
- access the incoming data through the global pointer
|
|
- uip_appdata, which usually points uip_ip_tcph_len +
|
|
- UIP_LLH_LEN bytes into the uip_buf array.
|
|
-
|
|
- If the application wishes to send any data, this data should
|
|
- be put into the uip_appdata and the length of the data should
|
|
- be put into uip_len. If the application don't have any data
|
|
- to send, uip_len must be set to 0. */
|
|
- if (ustack->uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
|
|
- ustack->uip_slen = 0;
|
|
- UIP_APPCALL(ustack);
|
|
-
|
|
-appsend:
|
|
-
|
|
- if (ustack->uip_flags & UIP_ABORT) {
|
|
- ustack->uip_slen = 0;
|
|
- uip_connr->tcpstateflags = UIP_CLOSED;
|
|
- tcp_hdr->flags = TCP_RST | TCP_ACK;
|
|
- goto tcp_send_nodata;
|
|
- }
|
|
-
|
|
- if (ustack->uip_flags & UIP_CLOSE) {
|
|
- ustack->uip_slen = 0;
|
|
- uip_connr->len = 1;
|
|
- uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
|
|
- uip_connr->nrtx = 0;
|
|
- tcp_hdr->flags = TCP_FIN | TCP_ACK;
|
|
- goto tcp_send_nodata;
|
|
- }
|
|
-
|
|
- /* If uip_slen > 0, the application has data to be sent
|
|
- */
|
|
- if (ustack->uip_slen > 0) {
|
|
-
|
|
- /* If the connection has acknowledged data, the
|
|
- contents of the ->len variable should be
|
|
- discarded. */
|
|
- if ((ustack->uip_flags & UIP_ACKDATA) != 0)
|
|
- uip_connr->len = 0;
|
|
-
|
|
- /* If the ->len variable is non-zero the
|
|
- connection has already data in transit and
|
|
- cannot send anymore right now. */
|
|
- if (uip_connr->len == 0) {
|
|
-
|
|
- /* The application cannot send more than
|
|
- what is allowed by the mss (the
|
|
- minumum of the MSS and the available
|
|
- window). */
|
|
- if (ustack->uip_slen > uip_connr->mss) {
|
|
- ustack->uip_slen =
|
|
- uip_connr->mss;
|
|
- }
|
|
-
|
|
- /* Remember how much data we send out
|
|
- now so that we know when everything
|
|
- has been acknowledged. */
|
|
- uip_connr->len = ustack->uip_slen;
|
|
- } else {
|
|
-
|
|
- /* If the application already had
|
|
- unacknowledged data, we make sure
|
|
- that the application does not send
|
|
- (i.e., retransmit) out more than it
|
|
- previously sent out. */
|
|
- ustack->uip_slen = uip_connr->len;
|
|
- }
|
|
- }
|
|
- uip_connr->nrtx = 0;
|
|
-apprexmit:
|
|
- ustack->uip_appdata = ustack->uip_sappdata;
|
|
-
|
|
- /* If the application has data to be sent, or if the
|
|
- incoming packet had new data in it, we must send
|
|
- out a packet. */
|
|
- if (ustack->uip_slen > 0 && uip_connr->len > 0) {
|
|
- /* Add the length of the IP and TCP headers. */
|
|
- ustack->uip_len =
|
|
- uip_connr->len + uip_ip_tcph_len;
|
|
- /* We always set the ACK flag in response
|
|
- packets. */
|
|
- tcp_hdr->flags = TCP_ACK | TCP_PSH;
|
|
- /* Send the packet. */
|
|
- goto tcp_send_noopts;
|
|
- }
|
|
- /* If there is no data to send, just send out a pure ACK
|
|
- if there is newdata. */
|
|
- if (ustack->uip_flags & UIP_NEWDATA) {
|
|
- ustack->uip_len = uip_ip_tcph_len;
|
|
- tcp_hdr->flags = TCP_ACK;
|
|
- goto tcp_send_noopts;
|
|
- }
|
|
- }
|
|
- goto drop;
|
|
- case UIP_LAST_ACK:
|
|
- /* We can close this connection if the peer has acknowledged our
|
|
- FIN. This is indicated by the UIP_ACKDATA flag. */
|
|
- if (ustack->uip_flags & UIP_ACKDATA) {
|
|
- uip_connr->tcpstateflags = UIP_CLOSED;
|
|
- ustack->uip_flags = UIP_CLOSE;
|
|
- UIP_APPCALL(ustack);
|
|
- }
|
|
- break;
|
|
-
|
|
- case UIP_FIN_WAIT_1:
|
|
- /* The application has closed the connection, but the remote
|
|
- host hasn't closed its end yet. Thus we do nothing but wait
|
|
- for a FIN from the other side. */
|
|
- if (ustack->uip_len > 0)
|
|
- uip_add_rcv_nxt(ustack, ustack->uip_len);
|
|
- if (tcp_hdr->flags & TCP_FIN) {
|
|
- if (ustack->uip_flags & UIP_ACKDATA) {
|
|
- uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
|
- uip_connr->timer = 0;
|
|
- uip_connr->len = 0;
|
|
- } else {
|
|
- uip_connr->tcpstateflags = UIP_CLOSING;
|
|
- }
|
|
- uip_add_rcv_nxt(ustack, 1);
|
|
- ustack->uip_flags = UIP_CLOSE;
|
|
- UIP_APPCALL(ustack);
|
|
- goto tcp_send_ack;
|
|
- } else if (ustack->uip_flags & UIP_ACKDATA) {
|
|
- uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
|
|
- uip_connr->len = 0;
|
|
- goto drop;
|
|
- }
|
|
- if (ustack->uip_len > 0)
|
|
- goto tcp_send_ack;
|
|
- goto drop;
|
|
-
|
|
- case UIP_FIN_WAIT_2:
|
|
- if (ustack->uip_len > 0)
|
|
- uip_add_rcv_nxt(ustack, ustack->uip_len);
|
|
- if (tcp_hdr->flags & TCP_FIN) {
|
|
- uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
|
- uip_connr->timer = 0;
|
|
- uip_add_rcv_nxt(ustack, 1);
|
|
- ustack->uip_flags = UIP_CLOSE;
|
|
- UIP_APPCALL(ustack);
|
|
- goto tcp_send_ack;
|
|
- }
|
|
- if (ustack->uip_len > 0)
|
|
- goto tcp_send_ack;
|
|
- goto drop;
|
|
-
|
|
- case UIP_TIME_WAIT:
|
|
- goto tcp_send_ack;
|
|
-
|
|
- case UIP_CLOSING:
|
|
- if (ustack->uip_flags & UIP_ACKDATA) {
|
|
- uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
|
- uip_connr->timer = 0;
|
|
- }
|
|
- }
|
|
- goto drop;
|
|
-
|
|
- /* We jump here when we are ready to send the packet, and just want
|
|
- to set the appropriate TCP sequence numbers in the TCP header. */
|
|
-tcp_send_ack:
|
|
- tcp_hdr->flags = TCP_ACK;
|
|
-tcp_send_nodata:
|
|
- ustack->uip_len = uip_ip_tcph_len;
|
|
-tcp_send_noopts:
|
|
- tcp_hdr->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
|
|
-tcp_send:
|
|
- /* We're done with the input processing. We are now ready to send a
|
|
- reply. Our job is to fill in all the fields of the TCP and IP
|
|
- headers before calculating the checksum and finally send the
|
|
- packet. */
|
|
- tcp_hdr->ackno[0] = uip_connr->rcv_nxt[0];
|
|
- tcp_hdr->ackno[1] = uip_connr->rcv_nxt[1];
|
|
- tcp_hdr->ackno[2] = uip_connr->rcv_nxt[2];
|
|
- tcp_hdr->ackno[3] = uip_connr->rcv_nxt[3];
|
|
-
|
|
- tcp_hdr->seqno[0] = uip_connr->snd_nxt[0];
|
|
- tcp_hdr->seqno[1] = uip_connr->snd_nxt[1];
|
|
- tcp_hdr->seqno[2] = uip_connr->snd_nxt[2];
|
|
- tcp_hdr->seqno[3] = uip_connr->snd_nxt[3];
|
|
-
|
|
- if (is_ipv6(ustack)) {
|
|
- IPv6_BUF(ustack)->proto = UIP_PROTO_TCP;
|
|
- uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
|
|
- ustack->hostaddr6);
|
|
- uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
|
|
- uip_connr->ripaddr6);
|
|
- } else {
|
|
- tcp_ipv4_hdr->proto = UIP_PROTO_TCP;
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
|
|
- uip_ip4addr_copy(tcp_ipv4_hdr->destipaddr, uip_connr->ripaddr);
|
|
- }
|
|
-
|
|
- tcp_hdr->srcport = uip_connr->lport;
|
|
- tcp_hdr->destport = uip_connr->rport;
|
|
-
|
|
- if (uip_connr->tcpstateflags & UIP_STOPPED) {
|
|
- /* If the connection has issued uip_stop(), we advertise a zero
|
|
- window so that the remote host will stop sending data. */
|
|
- tcp_hdr->wnd[0] = tcp_hdr->wnd[1] = 0;
|
|
- } else {
|
|
- tcp_hdr->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
|
|
- tcp_hdr->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
|
|
- }
|
|
-
|
|
-tcp_send_noconn:
|
|
- if (is_ipv6(ustack)) {
|
|
- IPv6_BUF(ustack)->ttl = UIP_TTL;
|
|
-
|
|
- /* For IPv6, the IP length field does not include the IPv6 IP
|
|
- header length. */
|
|
- IPv6_BUF(ustack)->len[0] =
|
|
- ((ustack->uip_len - uip_iph_len) >> 8);
|
|
- IPv6_BUF(ustack)->len[1] =
|
|
- ((ustack->uip_len - uip_iph_len) & 0xff);
|
|
- } else {
|
|
- tcp_ipv4_hdr->ttl = UIP_TTL;
|
|
- tcp_ipv4_hdr->len[0] = (ustack->uip_len >> 8);
|
|
- tcp_ipv4_hdr->len[1] = (ustack->uip_len & 0xff);
|
|
- }
|
|
-
|
|
- tcp_hdr->urgp[0] = tcp_hdr->urgp[1] = 0;
|
|
-
|
|
- /* Calculate TCP checksum. */
|
|
- tcp_hdr->tcpchksum = 0;
|
|
- tcp_hdr->tcpchksum = ~(uip_tcpchksum(ustack));
|
|
-
|
|
-ip_send_nolen:
|
|
-
|
|
- if (!is_ipv6(ustack)) {
|
|
- tcp_ipv4_hdr->vhl = 0x45;
|
|
- tcp_ipv4_hdr->tos = 0;
|
|
- tcp_ipv4_hdr->ipoffset[0] = tcp_ipv4_hdr->ipoffset[1] = 0;
|
|
- ++ustack->ipid;
|
|
- tcp_ipv4_hdr->ipid[0] = ustack->ipid >> 8;
|
|
- tcp_ipv4_hdr->ipid[1] = ustack->ipid & 0xff;
|
|
- /* Calculate IP checksum. */
|
|
- tcp_ipv4_hdr->ipchksum = 0;
|
|
- tcp_ipv4_hdr->ipchksum = ~(uip_ipchksum(ustack));
|
|
- }
|
|
-
|
|
- ++ustack->stats.tcp.sent;
|
|
-send:
|
|
- if (is_ipv6(ustack)) {
|
|
- LOG_DEBUG(PFX "Sending packet with length %d (%d)",
|
|
- ustack->uip_len, ipv6_hdr ? ipv6_hdr->ip6_plen : 0);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "Sending packet with length %d (%d)",
|
|
- ustack->uip_len,
|
|
- (tcp_ipv4_hdr->len[0] << 8) | tcp_ipv4_hdr->len[1]);
|
|
- }
|
|
- ++ustack->stats.ip.sent;
|
|
- /* Return and let the caller do the actual transmission. */
|
|
- ustack->uip_flags = 0;
|
|
- return;
|
|
-drop:
|
|
- ustack->uip_len = 0;
|
|
- ustack->uip_flags = 0;
|
|
- return;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-void uip_send(struct uip_stack *ustack, const void *data, int len)
|
|
-{
|
|
- if (len > 0) {
|
|
- ustack->uip_slen = len;
|
|
- if (data != ustack->uip_buf)
|
|
- memcpy(ustack->uip_buf, (data), ustack->uip_slen);
|
|
- }
|
|
-}
|
|
-
|
|
-void uip_appsend(struct uip_stack *ustack, const void *data, int len)
|
|
-{
|
|
- if (len > 0) {
|
|
- ustack->uip_slen = len;
|
|
- if (data != ustack->uip_sappdata)
|
|
- memcpy(ustack->uip_sappdata, (data), ustack->uip_slen);
|
|
- }
|
|
-}
|
|
-
|
|
-u16_t uip_datalen(struct uip_stack *ustack)
|
|
-{
|
|
- return ustack->uip_len;
|
|
-}
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/uip.h b/iscsiuio/src/uip/uip.h
|
|
deleted file mode 100644
|
|
index 9d9428a..0000000
|
|
--- a/iscsiuio/src/uip/uip.h
|
|
+++ /dev/null
|
|
@@ -1,1574 +0,0 @@
|
|
-
|
|
-/**
|
|
- * \addtogroup uip
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Header file for the uIP TCP/IP stack.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- *
|
|
- * The uIP TCP/IP stack header file contains definitions for a number
|
|
- * of C macros that are used by uIP programs as well as internal uIP
|
|
- * structures, TCP/IP header structures and function declarations.
|
|
- *
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001-2003, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __UIP_H__
|
|
-#define __UIP_H__
|
|
-
|
|
-#include <netinet/in.h>
|
|
-#include <pthread.h>
|
|
-
|
|
-#include "uipopt.h"
|
|
-
|
|
-#include "debug.h"
|
|
-
|
|
-#include "uip_eth.h"
|
|
-
|
|
-/* Forware declaration */
|
|
-struct uip_stack;
|
|
-
|
|
-/**
|
|
- * Repressentation of an IP address.
|
|
- *
|
|
- */
|
|
-typedef u16_t uip_ip4addr_t[2];
|
|
-typedef u16_t uip_ip6addr_t[8];
|
|
-
|
|
-extern const uip_ip6addr_t all_zeroes_addr6;
|
|
-extern const uip_ip4addr_t all_zeroes_addr4;
|
|
-
|
|
-#define ETH_BUF(buf) ((struct uip_eth_hdr *)buf)
|
|
-#define VLAN_ETH_BUF(buf) ((struct uip_vlan_eth_hdr *)buf)
|
|
-#define IPv4_BUF(buf) ((struct uip_tcp_ipv4_hdr *)buf)
|
|
-#define IPv6_BUF(buf) ((struct uip_tcp_ipv6_hdr *)buf)
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/* First, the functions that should be called from the
|
|
- * system. Initialization, the periodic timer and incoming packets are
|
|
- * handled by the following three functions.
|
|
- */
|
|
-
|
|
-/**
|
|
- * Set the IP address of this host.
|
|
- *
|
|
- * The IP address is represented as a 4-byte array where the first
|
|
- * octet of the IP address is put in the first member of the 4-byte
|
|
- * array.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
-
|
|
- uip_ipaddr_t addr;
|
|
-
|
|
- uip_ipaddr(&addr, 192,168,1,2);
|
|
- uip_sethostaddr(&addr);
|
|
-
|
|
- \endcode
|
|
- * \param addr A pointer to an IP address of type uip_ipaddr_t;
|
|
- *
|
|
- * \sa uip_ipaddr()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_sethostaddr4(struct uip_stack *ustack, uip_ip4addr_t *addr);
|
|
-
|
|
-/**
|
|
- * Set the default router's IP address.
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable containing the IP
|
|
- * address of the default router.
|
|
- *
|
|
- * \sa uip_ipaddr()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_setdraddr4(struct uip_stack *ustack, uip_ip4addr_t *addr);
|
|
-
|
|
-/**
|
|
- * Set the netmask.
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable containing the IP
|
|
- * address of the netmask.
|
|
- *
|
|
- * \sa uip_ipaddr()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_setnetmask4(struct uip_stack *ustack, uip_ip4addr_t *addr);
|
|
-
|
|
-/**
|
|
- * Set the ethernet MAC address.
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable containing the IP
|
|
- * address of the netmask.
|
|
- *
|
|
- * \sa uip_ipaddr()
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_setethernetmac(struct uip_stack *ustack, uint8_t *mac);
|
|
-
|
|
-/**
|
|
- * Get the default router's IP address.
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable that will be
|
|
- * filled in with the IP address of the default router.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr)
|
|
-
|
|
-/**
|
|
- * Get the netmask.
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable that will be
|
|
- * filled in with the value of the netmask.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask)
|
|
-
|
|
-void set_uip_stack(struct uip_stack *ustack,
|
|
- uip_ip4addr_t *ip,
|
|
- uip_ip4addr_t *netmask,
|
|
- uip_ip4addr_t *default_route, uint8_t *mac_addr);
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \defgroup uipinit uIP initialization functions
|
|
- * @{
|
|
- *
|
|
- * The uIP initialization functions are used for booting uIP.
|
|
- */
|
|
-
|
|
-/**
|
|
- * uIP initialization function.
|
|
- *
|
|
- * This function should be called at boot up to initilize the uIP
|
|
- * TCP/IP stack.
|
|
- */
|
|
-void uip_init(struct uip_stack *ustack, uint8_t enable_ipv6);
|
|
-
|
|
-/**
|
|
- * uIP reset function.
|
|
- *
|
|
- * This function should be called at to reset the uIP TCP/IP stack.
|
|
- */
|
|
-void uip_reset(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * uIP initialization function.
|
|
- *
|
|
- * This function may be used at boot time to set the initial ip_id.
|
|
- */
|
|
-void uip_setipid(u16_t id);
|
|
-
|
|
-/**
|
|
- *
|
|
- *
|
|
- */
|
|
-#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED)
|
|
-
|
|
-#if UIP_UDP
|
|
-void uip_udp_periodic(struct uip_stack *ustack, int conn);
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
-void uip_ndp_periodic(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * The uIP packet buffer.
|
|
- *
|
|
- * The uip_buf array is used to hold incoming and outgoing
|
|
- * packets. The device driver should place incoming data into this
|
|
- * buffer. When sending data, the device driver should read the link
|
|
- * level headers and the TCP/IP headers from this buffer. The size of
|
|
- * the link level headers is configured by the UIP_LLH_LEN define.
|
|
- *
|
|
- * \note The application data need not be placed in this buffer, so
|
|
- * the device driver must read it from the place pointed to by the
|
|
- * uip_appdata pointer as illustrated by the following example:
|
|
- \code
|
|
- void
|
|
- devicedriver_send(void)
|
|
- {
|
|
- hwsend(&uip_buf[0], UIP_LLH_LEN);
|
|
- if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
|
|
- hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
|
|
- } else {
|
|
- hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
|
|
- hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
|
|
- }
|
|
- }
|
|
- \endcode
|
|
- */
|
|
-/*extern u8_t uip_buf[UIP_BUFSIZE+2]; */
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/* Functions that are used by the uIP application program. Opening and
|
|
- * closing connections, sending and receiving data, etc. is all
|
|
- * handled by the functions below.
|
|
-*/
|
|
-/**
|
|
- * \defgroup uipappfunc uIP application functions
|
|
- * @{
|
|
- *
|
|
- * Functions used by an application running of top of uIP.
|
|
- */
|
|
-
|
|
-/**
|
|
- * Start listening to the specified port.
|
|
- *
|
|
- * \note Since this function expects the port number in network byte
|
|
- * order, a conversion using HTONS() or htons() is necessary.
|
|
- *
|
|
- \code
|
|
- uip_listen(HTONS(80));
|
|
- \endcode
|
|
- *
|
|
- * \param port A 16-bit port number in network byte order.
|
|
- */
|
|
-void uip_listen(struct uip_stack *ustack, u16_t port);
|
|
-
|
|
-/**
|
|
- * Stop listening to the specified port.
|
|
- *
|
|
- * \note Since this function expects the port number in network byte
|
|
- * order, a conversion using HTONS() or htons() is necessary.
|
|
- *
|
|
- \code
|
|
- uip_unlisten(HTONS(80));
|
|
- \endcode
|
|
- *
|
|
- * \param port A 16-bit port number in network byte order.
|
|
- */
|
|
-void uip_unlisten(struct uip_stack *ustack, u16_t port);
|
|
-
|
|
-/**
|
|
- * Connect to a remote host using TCP.
|
|
- *
|
|
- * This function is used to start a new connection to the specified
|
|
- * port on the specied host. It allocates a new connection identifier,
|
|
- * sets the connection to the SYN_SENT state and sets the
|
|
- * retransmission timer to 0. This will cause a TCP SYN segment to be
|
|
- * sent out the next time this connection is periodically processed,
|
|
- * which usually is done within 0.5 seconds after the call to
|
|
- * uip_connect().
|
|
- *
|
|
- * \note This function is avaliable only if support for active open
|
|
- * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
|
|
- *
|
|
- * \note Since this function requires the port number to be in network
|
|
- * byte order, a conversion using HTONS() or htons() is necessary.
|
|
- *
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 192,168,1,2);
|
|
- uip_connect(&ipaddr, HTONS(80));
|
|
- \endcode
|
|
- *
|
|
- * \param ripaddr The IP address of the remote hot.
|
|
- *
|
|
- * \param port A 16-bit port number in network byte order.
|
|
- *
|
|
- * \return A pointer to the uIP connection identifier for the new connection,
|
|
- * or NULL if no connection could be allocated.
|
|
- *
|
|
- */
|
|
-struct uip_conn *uip_connect(struct uip_stack *ustack,
|
|
- uip_ip4addr_t *ripaddr, u16_t port);
|
|
-
|
|
-/**
|
|
- * \internal
|
|
- *
|
|
- * Check if a connection has outstanding (i.e., unacknowledged) data.
|
|
- *
|
|
- * \param conn A pointer to the uip_conn structure for the connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_outstanding(conn) ((conn)->len)
|
|
-
|
|
-/**
|
|
- * Send data on the current connection.
|
|
- *
|
|
- * This function is used to send out a single segment of TCP
|
|
- * data. Only applications that have been invoked by uIP for event
|
|
- * processing can send data.
|
|
- *
|
|
- * The amount of data that actually is sent out after a call to this
|
|
- * funcion is determined by the maximum amount of data TCP allows. uIP
|
|
- * will automatically crop the data so that only the appropriate
|
|
- * amount of data is sent. The function uip_mss() can be used to query
|
|
- * uIP for the amount of data that actually will be sent.
|
|
- *
|
|
- * \note This function does not guarantee that the sent data will
|
|
- * arrive at the destination. If the data is lost in the network, the
|
|
- * application will be invoked with the uip_rexmit() event being
|
|
- * set. The application will then have to resend the data using this
|
|
- * function.
|
|
- *
|
|
- * \param data A pointer to the data which is to be sent.
|
|
- *
|
|
- * \param len The maximum amount of data bytes to be sent.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-void uip_send(struct uip_stack *ustack, const void *data, int len);
|
|
-void uip_appsend(struct uip_stack *ustack, const void *data, int len);
|
|
-
|
|
-/**
|
|
- * The length of any incoming data that is currently avaliable (if avaliable)
|
|
- * in the uip_appdata buffer.
|
|
- *
|
|
- * The test function uip_data() must first be used to check if there
|
|
- * is any data available at all.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-/*void uip_datalen(void);*/
|
|
-u16_t uip_datalen(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * The length of any out-of-band data (urgent data) that has arrived
|
|
- * on the connection.
|
|
- *
|
|
- * \note The configuration parameter UIP_URGDATA must be set for this
|
|
- * function to be enabled.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_urgdatalen() uip_urglen
|
|
-
|
|
-/**
|
|
- * Close the current connection.
|
|
- *
|
|
- * This function will close the current connection in a nice way.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_close() (uip_flags = UIP_CLOSE)
|
|
-
|
|
-/**
|
|
- * Abort the current connection.
|
|
- *
|
|
- * This function will abort (reset) the current connection, and is
|
|
- * usually used when an error has occured that prevents using the
|
|
- * uip_close() function.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_abort() (uip_flags = UIP_ABORT)
|
|
-
|
|
-/**
|
|
- * Tell the sending host to stop sending data.
|
|
- *
|
|
- * This function will close our receiver's window so that we stop
|
|
- * receiving data for the current connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
|
|
-
|
|
-/**
|
|
- * Find out if the current connection has been previously stopped with
|
|
- * uip_stop().
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
|
|
-
|
|
-/**
|
|
- * Restart the current connection, if is has previously been stopped
|
|
- * with uip_stop().
|
|
- *
|
|
- * This function will open the receiver's window again so that we
|
|
- * start receiving data for the current connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
|
|
- uip_conn->tcpstateflags &= ~UIP_STOPPED; \
|
|
- } while (0)
|
|
-
|
|
-/* uIP tests that can be made to determine in what state the current
|
|
- connection is, and what the application function should do. */
|
|
-
|
|
-/**
|
|
- * Is the current connection a UDP connection?
|
|
- *
|
|
- * This function checks whether the current connection is a UDP connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- *
|
|
- */
|
|
-#define uip_udpconnection() (uip_conn == NULL)
|
|
-
|
|
-/**
|
|
- * Function declarations for hte uip_flags
|
|
- */
|
|
-/**
|
|
- * Is new incoming data available?
|
|
- *
|
|
- * Will reduce to non-zero if there is new data for the application
|
|
- * present at the uip_appdata pointer. The size of the data is
|
|
- * avaliable through the uip_len variable.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_newdata(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Has previously sent data been acknowledged?
|
|
- *
|
|
- * Will reduce to non-zero if the previously sent data has been
|
|
- * acknowledged by the remote host. This means that the application
|
|
- * can send new data.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_acked(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Has the connection just been connected?
|
|
- *
|
|
- * Reduces to non-zero if the current connection has been connected to
|
|
- * a remote host. This will happen both if the connection has been
|
|
- * actively opened (with uip_connect()) or passively opened (with
|
|
- * uip_listen()).
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_connected(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Has the connection been closed by the other end?
|
|
- *
|
|
- * Is non-zero if the connection has been closed by the remote
|
|
- * host. The application may then do the necessary clean-ups.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_closed(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Has the connection been aborted by the other end?
|
|
- *
|
|
- * Non-zero if the current connection has been aborted (reset) by the
|
|
- * remote host.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_aborted(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Has the connection timed out?
|
|
- *
|
|
- * Non-zero if the current connection has been aborted due to too many
|
|
- * retransmissions.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_timedout(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Do we need to retransmit previously data?
|
|
- *
|
|
- * Reduces to non-zero if the previously sent data has been lost in
|
|
- * the network, and the application should retransmit it. The
|
|
- * application should send the exact same data as it did the last
|
|
- * time, using the uip_send() function.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_rexmit(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Is the connection being polled by uIP?
|
|
- *
|
|
- * Is non-zero if the reason the application is invoked is that the
|
|
- * current connection has been idle for a while and should be
|
|
- * polled.
|
|
- *
|
|
- * The polling event can be used for sending data without having to
|
|
- * wait for the remote host to send data.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_poll(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Get the initial maxium segment size (MSS) of the current
|
|
- * connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_initialmss(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Get the current maxium segment size that can be sent on the current
|
|
- * connection.
|
|
- *
|
|
- * The current maxiumum segment size that can be sent on the
|
|
- * connection is computed from the receiver's window and the MSS of
|
|
- * the connection (which also is available by calling
|
|
- * uip_initialmss()).
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-int uip_mss(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Set up a new UDP connection.
|
|
- *
|
|
- * This function sets up a new UDP connection. The function will
|
|
- * automatically allocate an unused local port for the new
|
|
- * connection. However, another port can be chosen by using the
|
|
- * uip_udp_bind() call, after the uip_udp_new() function has been
|
|
- * called.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t addr;
|
|
- struct uip_udp_conn *c;
|
|
-
|
|
- uip_ipaddr(&addr, 192,168,2,1);
|
|
- c = uip_udp_new(&addr, HTONS(12345));
|
|
- if(c != NULL) {
|
|
- uip_udp_bind(c, HTONS(12344));
|
|
- }
|
|
- \endcode
|
|
- * \param ripaddr The IP address of the remote host.
|
|
- *
|
|
- * \param rport The remote port number in network byte order.
|
|
- *
|
|
- * \return The uip_udp_conn structure for the new connection or NULL
|
|
- * if no connection could be allocated.
|
|
- */
|
|
-struct uip_udp_conn *uip_udp_new(struct uip_stack *ustack,
|
|
- uip_ip4addr_t *ripaddr, u16_t rport);
|
|
-
|
|
-/**
|
|
- * Removed a UDP connection.
|
|
- *
|
|
- * \param conn A pointer to the uip_udp_conn structure for the connection.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_udp_remove(conn) ((conn)->lport = 0)
|
|
-
|
|
-/**
|
|
- * Bind a UDP connection to a local port.
|
|
- *
|
|
- * \param conn A pointer to the uip_udp_conn structure for the
|
|
- * connection.
|
|
- *
|
|
- * \param port The local port number, in network byte order.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_udp_bind(conn, port) ((conn)->lport = port)
|
|
-
|
|
-/**
|
|
- * Send a UDP datagram of length len on the current connection.
|
|
- *
|
|
- * This function can only be called in response to a UDP event (poll
|
|
- * or newdata). The data must be present in the uip_buf buffer, at the
|
|
- * place pointed to by the uip_appdata pointer.
|
|
- *
|
|
- * \param len The length of the data in the uip_buf buffer.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_udp_send(len) uip_appsend((char *)uip_appdata, len)
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/* uIP convenience and converting functions. */
|
|
-
|
|
-/**
|
|
- * \defgroup uipconvfunc uIP conversion functions
|
|
- * @{
|
|
- *
|
|
- * These functions can be used for converting between different data
|
|
- * formats used by uIP.
|
|
- */
|
|
-
|
|
-/**
|
|
- * Construct an IP address from four bytes.
|
|
- *
|
|
- * This function constructs an IP address of the type that uIP handles
|
|
- * internally from four bytes. The function is handy for specifying IP
|
|
- * addresses to use with e.g. the uip_connect() function.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
- struct uip_conn *c;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 192,168,1,2);
|
|
- c = uip_connect(&ipaddr, HTONS(80));
|
|
- \endcode
|
|
- *
|
|
- * \param addr A pointer to a uip_ipaddr_t variable that will be
|
|
- * filled in with the IP address.
|
|
- *
|
|
- * \param addr0 The first octet of the IP address.
|
|
- * \param addr1 The second octet of the IP address.
|
|
- * \param addr2 The third octet of the IP address.
|
|
- * \param addr3 The forth octet of the IP address.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ipaddr(addr, addr0, addr1, addr2, addr3) do { \
|
|
- ((u16_t *)(addr))[0] = const_htons(((addr0) << 8) | (addr1)); \
|
|
- ((u16_t *)(addr))[1] = const_htons(((addr2) << 8) | (addr3)); \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Construct an IPv6 address from eight 16-bit words.
|
|
- *
|
|
- * This function constructs an IPv6 address.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, \
|
|
- addr7) \
|
|
- do { \
|
|
- ((u16_t *)(addr))[0] = HTONS((addr0)); \
|
|
- ((u16_t *)(addr))[1] = HTONS((addr1)); \
|
|
- ((u16_t *)(addr))[2] = HTONS((addr2)); \
|
|
- ((u16_t *)(addr))[3] = HTONS((addr3)); \
|
|
- ((u16_t *)(addr))[4] = HTONS((addr4)); \
|
|
- ((u16_t *)(addr))[5] = HTONS((addr5)); \
|
|
- ((u16_t *)(addr))[6] = HTONS((addr6)); \
|
|
- ((u16_t *)(addr))[7] = HTONS((addr7)); \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Copy an IP address to another IP address.
|
|
- *
|
|
- * Copies an IP address from one place to another.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr1, ipaddr2;
|
|
-
|
|
- uip_ipaddr(&ipaddr1, 192,16,1,2);
|
|
- uip_ipaddr_copy(&ipaddr2, &ipaddr1);
|
|
- \endcode
|
|
- *
|
|
- * \param dest The destination for the copy.
|
|
- * \param src The source from where to copy.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ip4addr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip4addr_t))
|
|
-#define uip_ip6addr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t))
|
|
-
|
|
-/**
|
|
- * Compare two IP addresses
|
|
- *
|
|
- * Compares two IP addresses.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr1, ipaddr2;
|
|
-
|
|
- uip_ipaddr(&ipaddr1, 192,16,1,2);
|
|
- if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) {
|
|
- printf("They are the same");
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \param addr1 The first IP address.
|
|
- * \param addr2 The second IP address.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ip4addr_cmp(addr1, addr2) (memcmp(addr1, addr2, \
|
|
- sizeof(uip_ip4addr_t)) == 0)
|
|
-#define uip_ip6addr_cmp(addr1, addr2) (memcmp(addr1, addr2, \
|
|
- sizeof(uip_ip6addr_t)) == 0)
|
|
-
|
|
-/**
|
|
- * Compare two IP addresses with netmasks
|
|
- *
|
|
- * Compares two IP addresses with netmasks. The masks are used to mask
|
|
- * out the bits that are to be compared.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr1, ipaddr2, mask;
|
|
-
|
|
- uip_ipaddr(&mask, 255,255,255,0);
|
|
- uip_ipaddr(&ipaddr1, 192,16,1,2);
|
|
- uip_ipaddr(&ipaddr2, 192,16,1,3);
|
|
- if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) {
|
|
- printf("They are the same");
|
|
- }
|
|
- \endcode
|
|
- *
|
|
- * \param addr1 The first IP address.
|
|
- * \param addr2 The second IP address.
|
|
- * \param mask The netmask.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ip4addr_maskcmp(addr1, addr2, mask) \
|
|
- (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \
|
|
- (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \
|
|
- ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \
|
|
- (((u16_t *)addr2)[1] & ((u16_t *)mask)[1])))
|
|
-
|
|
-/**
|
|
- * Mask out the network part of an IP address.
|
|
- *
|
|
- * Masks out the network part of an IP address, given the address and
|
|
- * the netmask.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr1, ipaddr2, netmask;
|
|
-
|
|
- uip_ipaddr(&ipaddr1, 192,16,1,2);
|
|
- uip_ipaddr(&netmask, 255,255,255,0);
|
|
- uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
|
|
- \endcode
|
|
- *
|
|
- * In the example above, the variable "ipaddr2" will contain the IP
|
|
- * address 192.168.1.0.
|
|
- *
|
|
- * \param dest Where the result is to be placed.
|
|
- * \param src The IP address.
|
|
- * \param mask The netmask.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ip4addr_mask(dest, src, mask) do { \
|
|
- ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \
|
|
- ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \
|
|
- } while (0)
|
|
-
|
|
-/**
|
|
- * Pick the first octet of an IP address.
|
|
- *
|
|
- * Picks out the first octet of an IP address.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
- u8_t octet;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 1,2,3,4);
|
|
- octet = uip_ipaddr1(&ipaddr);
|
|
- \endcode
|
|
- *
|
|
- * In the example above, the variable "octet" will contain the value 1.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8)
|
|
-
|
|
-/**
|
|
- * Pick the second octet of an IP address.
|
|
- *
|
|
- * Picks out the second octet of an IP address.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
- u8_t octet;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 1,2,3,4);
|
|
- octet = uip_ipaddr2(&ipaddr);
|
|
- \endcode
|
|
- *
|
|
- * In the example above, the variable "octet" will contain the value 2.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff)
|
|
-
|
|
-/**
|
|
- * Pick the third octet of an IP address.
|
|
- *
|
|
- * Picks out the third octet of an IP address.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
- u8_t octet;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 1,2,3,4);
|
|
- octet = uip_ipaddr3(&ipaddr);
|
|
- \endcode
|
|
- *
|
|
- * In the example above, the variable "octet" will contain the value 3.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8)
|
|
-
|
|
-/**
|
|
- * Pick the fourth octet of an IP address.
|
|
- *
|
|
- * Picks out the fourth octet of an IP address.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- uip_ipaddr_t ipaddr;
|
|
- u8_t octet;
|
|
-
|
|
- uip_ipaddr(&ipaddr, 1,2,3,4);
|
|
- octet = uip_ipaddr4(&ipaddr);
|
|
- \endcode
|
|
- *
|
|
- * In the example above, the variable "octet" will contain the value 4.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff)
|
|
-
|
|
-/**
|
|
- * Convert 16-bit quantity from host byte order to network byte order.
|
|
- *
|
|
- * This macro is primarily used for converting constants from host
|
|
- * byte order to network byte order. For converting variables to
|
|
- * network byte order, use the htons() function instead.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#if 0
|
|
-#ifndef HTONS
|
|
-# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
|
|
-# define HTONS(n) (n)
|
|
-# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
|
|
-# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8))
|
|
-# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
|
|
-#else
|
|
-#error "HTONS already defined!"
|
|
-#endif /* HTONS */
|
|
-#endif
|
|
-
|
|
-#if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
|
|
-# error "Should not be here"
|
|
-# define const_htons(n) (n)
|
|
-# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
|
|
-# define const_htons(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8))
|
|
-# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
|
|
-
|
|
-/* BWL */
|
|
-#if 0
|
|
-/**
|
|
- * Convert 16-bit quantity from host byte order to network byte order.
|
|
- *
|
|
- * This function is primarily used for converting variables from host
|
|
- * byte order to network byte order. For converting constants to
|
|
- * network byte order, use the HTONS() macro instead.
|
|
- */
|
|
-#ifndef htons
|
|
-u16_t htons(u16_t val);
|
|
-#endif /* htons */
|
|
-#ifndef ntohs
|
|
-#define ntohs htons
|
|
-#endif
|
|
-#endif
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * Pointer to the application data in the packet buffer.
|
|
- *
|
|
- * This pointer points to the application data when the application is
|
|
- * called. If the application wishes to send data, the application may
|
|
- * use this space to write the data into before calling uip_send().
|
|
- */
|
|
-/* extern void *uip_appdata; */
|
|
-
|
|
-#if UIP_URGDATA > 0
|
|
-/* u8_t *uip_urgdata:
|
|
- *
|
|
- * This pointer points to any urgent data that has been received. Only
|
|
- * present if compiled with support for urgent data (UIP_URGDATA).
|
|
- */
|
|
-extern void *uip_urgdata;
|
|
-#endif /* UIP_URGDATA > 0 */
|
|
-
|
|
-/**
|
|
- * \defgroup uipdrivervars Variables used in uIP device drivers
|
|
- * @{
|
|
- *
|
|
- * uIP has a few global variables that are used in device drivers for
|
|
- * uIP.
|
|
- */
|
|
-
|
|
-/**
|
|
- * The length of the packet in the uip_buf buffer.
|
|
- *
|
|
- * The global variable uip_len holds the length of the packet in the
|
|
- * uip_buf buffer.
|
|
- *
|
|
- * When the network device driver calls the uIP input function,
|
|
- * uip_len should be set to the length of the packet in the uip_buf
|
|
- * buffer.
|
|
- *
|
|
- * When sending packets, the device driver should use the contents of
|
|
- * the uip_len variable to determine the length of the outgoing
|
|
- * packet.
|
|
- *
|
|
- */
|
|
-/* extern u16_t uip_len; */
|
|
-
|
|
-/** @} */
|
|
-
|
|
-#if UIP_URGDATA > 0
|
|
-extern u16_t uip_urglen, uip_surglen;
|
|
-#endif /* UIP_URGDATA > 0 */
|
|
-
|
|
-/**
|
|
- * Representation of a uIP TCP connection.
|
|
- *
|
|
- * The uip_conn structure is used for identifying a connection. All
|
|
- * but one field in the structure are to be considered read-only by an
|
|
- * application. The only exception is the appstate field whos purpose
|
|
- * is to let the application store application-specific state (e.g.,
|
|
- * file pointers) for the connection. The type of this field is
|
|
- * configured in the "uipopt.h" header file.
|
|
- */
|
|
-struct __attribute__ ((__packed__)) uip_conn {
|
|
- uip_ip4addr_t ripaddr;
|
|
- uip_ip6addr_t ripaddr6;
|
|
- /**< The IP address of the remote host. */
|
|
-
|
|
- u16_t lport; /**< The local TCP port, in network byte order. */
|
|
- u16_t rport; /**< The local remote TCP port, in network byte
|
|
- order. */
|
|
-
|
|
- u8_t rcv_nxt[4];
|
|
- /**< The sequence number that we expect to
|
|
- receive next. */
|
|
- u8_t snd_nxt[4];
|
|
- /**< The sequence number that was last sent by
|
|
- us. */
|
|
- u16_t len; /**< Length of the data that was previously sent. */
|
|
- u16_t mss; /**< Current maximum segment size for the
|
|
- connection. */
|
|
- u16_t initialmss;
|
|
- /**< Initial maximum segment size for the
|
|
- connection. */
|
|
- u8_t sa; /**< Retransmission time-out calculation state
|
|
- variable. */
|
|
- u8_t sv; /**< Retransmission time-out calculation state
|
|
- variable. */
|
|
- u8_t rto; /**< Retransmission time-out. */
|
|
- u8_t tcpstateflags;
|
|
- /**< TCP state and flags. */
|
|
- u8_t timer; /**< The retransmission timer. */
|
|
- u8_t nrtx; /**< The number of retransmissions for the last
|
|
- segment sent. */
|
|
-};
|
|
-
|
|
-/**
|
|
- * \addtogroup uiparch
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * 4-byte array used for the 32-bit sequence number calculations.
|
|
- */
|
|
-extern u8_t uip_acc32[4];
|
|
-
|
|
-/** @} */
|
|
-
|
|
-#if UIP_UDP
|
|
-/**
|
|
- * Representation of a uIP UDP connection.
|
|
- */
|
|
-struct uip_udp_conn {
|
|
- uip_ip4addr_t ripaddr;
|
|
- /**< The IP address of the remote peer. */
|
|
- u16_t lport; /**< The local port number in network byte order. */
|
|
- u16_t rport; /**< The remote port number in network byte order. */
|
|
- u8_t ttl; /**< Default time-to-live. */
|
|
-
|
|
- /** The application state. */
|
|
-/* uip_udp_appstate_t appstate; */
|
|
-};
|
|
-
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
-/**
|
|
- * The structure holding the TCP/IP statistics that are gathered if
|
|
- * UIP_STATISTICS is set to 1.
|
|
- *
|
|
- */
|
|
-struct uip_stats {
|
|
- struct {
|
|
- uip_stats_t drop;
|
|
- /**< Number of dropped packets at the IP
|
|
- layer. */
|
|
- uip_stats_t recv;
|
|
- /**< Number of received packets at the IP
|
|
- layer. */
|
|
- uip_stats_t sent;
|
|
- /**< Number of sent packets at the IP
|
|
- layer. */
|
|
- uip_stats_t vhlerr;
|
|
- /**< Number of packets dropped due to wrong
|
|
- IP version or header length. */
|
|
- uip_stats_t hblenerr;
|
|
- /**< Number of packets dropped due to wrong
|
|
- IP length, high byte. */
|
|
- uip_stats_t lblenerr;
|
|
- /**< Number of packets dropped due to wrong
|
|
- IP length, low byte. */
|
|
- uip_stats_t fragerr;
|
|
- /**< Number of packets dropped since they
|
|
- were IP fragments. */
|
|
- uip_stats_t chkerr;
|
|
- /**< Number of packets dropped due to IP
|
|
- checksum errors. */
|
|
- uip_stats_t protoerr;
|
|
- /**< Number of packets dropped since they
|
|
- were neither ICMP, UDP nor TCP. */
|
|
- } ip; /**< IP statistics. */
|
|
- struct {
|
|
- uip_stats_t drop;
|
|
- /**< Number of dropped ICMP packets. */
|
|
- uip_stats_t recv;
|
|
- /**< Number of received ICMP packets. */
|
|
- uip_stats_t sent;
|
|
- /**< Number of sent ICMP packets. */
|
|
- uip_stats_t typeerr;
|
|
- /**< Number of ICMP packets with a wrong
|
|
- type. */
|
|
- } icmp; /**< ICMP statistics. */
|
|
- struct {
|
|
- uip_stats_t drop;
|
|
- /**< Number of dropped TCP segments. */
|
|
- uip_stats_t recv;
|
|
- /**< Number of recived TCP segments. */
|
|
- uip_stats_t sent;
|
|
- /**< Number of sent TCP segments. */
|
|
- uip_stats_t chkerr;
|
|
- /**< Number of TCP segments with a bad
|
|
- checksum. */
|
|
- uip_stats_t ackerr;
|
|
- /**< Number of TCP segments with a bad ACK
|
|
- number. */
|
|
- uip_stats_t rst;
|
|
- /**< Number of recevied TCP RST (reset) segments. */
|
|
- uip_stats_t rexmit;
|
|
- /**< Number of retransmitted TCP segments. */
|
|
- uip_stats_t syndrop;
|
|
- /**< Number of dropped SYNs due to too few
|
|
- connections was avaliable. */
|
|
- uip_stats_t synrst;
|
|
- /**< Number of SYNs for closed ports,
|
|
- triggering a RST. */
|
|
- } tcp; /**< TCP statistics. */
|
|
-#if UIP_UDP
|
|
- struct {
|
|
- uip_stats_t drop;
|
|
- /**< Number of dropped UDP segments. */
|
|
- uip_stats_t recv;
|
|
- /**< Number of recived UDP segments. */
|
|
- uip_stats_t sent;
|
|
- /**< Number of sent UDP segments. */
|
|
- uip_stats_t chkerr;
|
|
- /**< Number of UDP segments with a bad
|
|
- checksum. */
|
|
- } udp; /**< UDP statistics. */
|
|
-#endif /* UIP_UDP */
|
|
-};
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/* All the stuff below this point is internal to uIP and should not be
|
|
- * used directly by an application or by a device driver.
|
|
- */
|
|
-/*---------------------------------------------------------------------------*/
|
|
-/* u8_t uip_flags:
|
|
- *
|
|
- * When the application is called, uip_flags will contain the flags
|
|
- * that are defined in this file. Please read below for more
|
|
- * infomation.
|
|
- */
|
|
-/* extern u8_t uip_flags; */
|
|
-
|
|
-/* The following flags may be set in the global variable uip_flags
|
|
- before calling the application callback. The UIP_ACKDATA,
|
|
- UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time,
|
|
- whereas the others are mutualy exclusive. Note that these flags
|
|
- should *NOT* be accessed directly, but only through the uIP
|
|
- functions/macros. */
|
|
-
|
|
-#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
|
|
- acked and the application should send
|
|
- out new data instead of retransmitting
|
|
- the last data. */
|
|
-#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
|
|
- us new data. */
|
|
-#define UIP_REXMIT 4 /* Tells the application to retransmit the
|
|
- data that was last sent. */
|
|
-#define UIP_POLL 8 /* Used for polling the application, to
|
|
- check if the application has data that
|
|
- it wants to send. */
|
|
-#define UIP_CLOSE 16 /* The remote host has closed the
|
|
- connection, thus the connection has
|
|
- gone away. Or the application signals
|
|
- that it wants to close the
|
|
- connection. */
|
|
-#define UIP_ABORT 32 /* The remote host has aborted the
|
|
- connection, thus the connection has
|
|
- gone away. Or the application signals
|
|
- that it wants to abort the
|
|
- connection. */
|
|
-#define UIP_CONNECTED 64 /* We have got a connection from a remote
|
|
- host and have set up a new connection
|
|
- for it, or an active connection has
|
|
- been successfully established. */
|
|
-
|
|
-#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
|
|
- too many retransmissions. */
|
|
-
|
|
-void uip_input(struct uip_stack *ustack);
|
|
-void uip_periodic(struct uip_stack *ustack, int conn);
|
|
-
|
|
-/* uip_process(flag):
|
|
- *
|
|
- * The actual uIP function which does all the work.
|
|
- */
|
|
-void uip_process(struct uip_stack *ustack, u8_t flag);
|
|
-
|
|
-/* The following flags are passed as an argument to the uip_process()
|
|
- function. They are used to distinguish between the two cases where
|
|
- uip_process() is called. It can be called either because we have
|
|
- incoming data that should be processed, or because the periodic
|
|
- timer has fired. These values are never used directly, but only in
|
|
- the macrose defined in this file. */
|
|
-
|
|
-#define UIP_DATA 1 /* Tells uIP that there is incoming
|
|
- data in the uip_buf buffer. The
|
|
- length of the data is stored in the
|
|
- global variable uip_len. */
|
|
-#define UIP_TIMER 2 /* Tells uIP that the periodic timer
|
|
- has fired. */
|
|
-#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
|
|
- be polled. */
|
|
-#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
|
|
- should be constructed in the
|
|
- uip_buf buffer. */
|
|
-#if UIP_UDP
|
|
-#define UIP_UDP_TIMER 5
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
-#define UIP_NDP_TIMER 6
|
|
-
|
|
-/* The TCP states used in the uip_conn->tcpstateflags. */
|
|
-#define UIP_CLOSED 0
|
|
-#define UIP_SYN_RCVD 1
|
|
-#define UIP_SYN_SENT 2
|
|
-#define UIP_ESTABLISHED 3
|
|
-#define UIP_FIN_WAIT_1 4
|
|
-#define UIP_FIN_WAIT_2 5
|
|
-#define UIP_CLOSING 6
|
|
-#define UIP_TIME_WAIT 7
|
|
-#define UIP_LAST_ACK 8
|
|
-#define UIP_TS_MASK 15
|
|
-
|
|
-#define UIP_STOPPED 16
|
|
-
|
|
-struct __attribute__ ((__packed__)) uip_tcp_hdr {
|
|
- /* TCP header. */
|
|
- u16_t srcport, destport;
|
|
- u8_t seqno[4], ackno[4], tcpoffset, flags, wnd[2];
|
|
- u16_t tcpchksum;
|
|
- u8_t urgp[2];
|
|
- u8_t optdata[4];
|
|
-};
|
|
-
|
|
-struct __attribute__ ((__packed__)) uip_ipv4_hdr {
|
|
- /* IPv4 header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-};
|
|
-
|
|
-struct __attribute__ ((__packed__)) uip_ipv6_hdr {
|
|
- /* IPv6 header. */
|
|
- u8_t vtc, tcflow;
|
|
- u16_t flow;
|
|
- u16_t len;
|
|
- u8_t proto, ttl;
|
|
- uip_ip6addr_t srcipaddr, destipaddr;
|
|
-};
|
|
-
|
|
-/* The TCP and IPv4 headers. */
|
|
-struct __attribute__ ((__packed__)) uip_tcp_ipv4_hdr {
|
|
- /* IPv4 header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-
|
|
- /* TCP header. */
|
|
- u16_t srcport, destport;
|
|
- u8_t seqno[4], ackno[4], tcpoffset, flags, wnd[2];
|
|
- u16_t tcpchksum;
|
|
- u8_t urgp[2];
|
|
- u8_t optdata[4];
|
|
-};
|
|
-
|
|
-/* The TCP and IP headers. */
|
|
-struct __attribute__ ((__packed__)) uip_tcp_ipv6_hdr {
|
|
- /* IPv6 header. */
|
|
- u8_t vtc, tcflow;
|
|
- u16_t flow;
|
|
- u8_t len[2];
|
|
- u8_t proto, ttl;
|
|
- uip_ip6addr_t srcipaddr, destipaddr;
|
|
-
|
|
- /* TCP header. */
|
|
- u16_t srcport, destport;
|
|
- u8_t seqno[4], ackno[4], tcpoffset, flags, wnd[2];
|
|
- u16_t tcpchksum;
|
|
- u8_t urgp[2];
|
|
- u8_t optdata[4];
|
|
-};
|
|
-
|
|
-/* The ICMPv4 */
|
|
-struct __attribute__ ((__packed__)) uip_icmpv4_hdr {
|
|
- /* ICMP (echo) header. */
|
|
- u8_t type, icode;
|
|
- u16_t icmpchksum;
|
|
- u16_t id, seqno;
|
|
-};
|
|
-
|
|
-typedef struct uip_icmpv4_hdr uip_icmp_echo_hdr_t;
|
|
-
|
|
-/* The ICMPv6 */
|
|
-struct __attribute__ ((__packed__)) uip_icmpv6_hdr {
|
|
- /* ICMP (echo) header. */
|
|
- u8_t type, icode;
|
|
- u16_t icmpchksum;
|
|
- u8_t flags, reserved1, reserved2, reserved3;
|
|
- u8_t icmp6data[16];
|
|
- u8_t options[1];
|
|
-};
|
|
-
|
|
-/* The ICMP and IP headers. */
|
|
-struct __attribute__ ((__packed__)) uip_icmpip_hdr {
|
|
-#if UIP_CONF_IPV6
|
|
- /* IPv6 header. */
|
|
- u8_t vtc, tcf;
|
|
- u16_t flow;
|
|
- u8_t len[2];
|
|
- u8_t proto, ttl;
|
|
- uip_ip6addr_t srcipaddr, destipaddr;
|
|
-#else /* UIP_CONF_IPV6 */
|
|
- /* IPv4 header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-#endif /* UIP_CONF_IPV6 */
|
|
-
|
|
- /* ICMP (echo) header. */
|
|
- u8_t type, icode;
|
|
- u16_t icmpchksum;
|
|
-#if !UIP_CONF_IPV6
|
|
- u16_t id, seqno;
|
|
-#else /* !UIP_CONF_IPV6 */
|
|
- u8_t flags, reserved1, reserved2, reserved3;
|
|
- u8_t icmp6data[16];
|
|
- u8_t options[1];
|
|
-#endif /* !UIP_CONF_IPV6 */
|
|
-};
|
|
-
|
|
-/* The UDP */
|
|
-struct __attribute__ ((__packed__)) uip_udp_hdr {
|
|
- /* UDP header. */
|
|
- u16_t srcport, destport;
|
|
- u16_t udplen;
|
|
- u16_t udpchksum;
|
|
-};
|
|
-
|
|
-/* The UDP and IP headers. */
|
|
-struct __attribute__ ((__packed__)) uip_udpip_hdr {
|
|
-#if UIP_CONF_IPV6
|
|
- /* IPv6 header. */
|
|
- u8_t vtc, tcf;
|
|
- u16_t flow;
|
|
- u8_t len[2];
|
|
- u8_t proto, ttl;
|
|
- uip_ip6addr_t srcipaddr, destipaddr;
|
|
-#else /* UIP_CONF_IPV6 */
|
|
- /* IP header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-#endif /* UIP_CONF_IPV6 */
|
|
-
|
|
- /* UDP header. */
|
|
- u16_t srcport, destport;
|
|
- u16_t udplen;
|
|
- u16_t udpchksum;
|
|
-};
|
|
-
|
|
-/**
|
|
- * The buffer size available for user data in the \ref uip_buf buffer.
|
|
- *
|
|
- * This macro holds the available size for user data in the \ref
|
|
- * uip_buf buffer. The macro is intended to be used for checking
|
|
- * bounds of available user data.
|
|
- *
|
|
- * Example:
|
|
- \code
|
|
- snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i);
|
|
- \endcode
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
|
|
-
|
|
-#define UIP_PROTO_ICMP 1
|
|
-#define UIP_PROTO_TCP 6
|
|
-#define UIP_PROTO_UDP 17
|
|
-#define UIP_PROTO_ICMP6 58
|
|
-
|
|
-/* Header sizes. */
|
|
-#define UIP_IPv6_H_LEN 40 /* Size of IPv6 header */
|
|
-#define UIP_IPv4_H_LEN 20 /* Size of IPv4 header */
|
|
-
|
|
-#define UIP_UDPH_LEN 8 /* Size of UDP header */
|
|
-#define UIP_TCPH_LEN 20 /* Size of TCP header */
|
|
-
|
|
-#define UIP_IPv4_UDPH_LEN (UIP_UDPH_LEN + UIP_IPv4_H_LEN) /* Size of IPv4
|
|
- + UDP
|
|
- header */
|
|
-#define UIP_IPv4_TCPH_LEN (UIP_TCPH_LEN + UIP_IPv4_H_LEN) /* Size of IPv4
|
|
- + TCP
|
|
- header */
|
|
-#define UIP_TCP_IPv4_HLEN UIP_IPv4_TCPH_LEN
|
|
-
|
|
-#define UIP_IPv6_UDPH_LEN (UIP_UDPH_LEN + UIP_IPv6_H_LEN) /* Size of IPv6
|
|
- + UDP
|
|
- header */
|
|
-#define UIP_IPv6_TCPH_LEN (UIP_TCPH_LEN + UIP_IPv6_H_LEN) /* Size of IPv6
|
|
- + TCP
|
|
- header */
|
|
-#define UIP_TCP_IPv6_HLEN UIP_IPv6_TCPH_LEN
|
|
-
|
|
-/**
|
|
- * Calculate the Internet checksum over a buffer.
|
|
- *
|
|
- * The Internet checksum is the one's complement of the one's
|
|
- * complement sum of all 16-bit words in the buffer.
|
|
- *
|
|
- * See RFC1071.
|
|
- *
|
|
- * \param buf A pointer to the buffer over which the checksum is to be
|
|
- * computed.
|
|
- *
|
|
- * \param len The length of the buffer over which the checksum is to
|
|
- * be computed.
|
|
- *
|
|
- * \return The Internet checksum of the buffer.
|
|
- */
|
|
-u16_t uip_chksum(u16_t *buf, u16_t len);
|
|
-
|
|
-/**
|
|
- * Calculate the IP header checksum of the packet header in uip_buf.
|
|
- *
|
|
- * The IP header checksum is the Internet checksum of the 20 bytes of
|
|
- * the IP header.
|
|
- *
|
|
- * \return The IP header checksum of the IP header in the uip_buf
|
|
- * buffer.
|
|
- */
|
|
-u16_t uip_ipchksum(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
|
|
- *
|
|
- * The TCP checksum is the Internet checksum of data contents of the
|
|
- * TCP segment, and a pseudo-header as defined in RFC793.
|
|
- *
|
|
- * \return The TCP checksum of the TCP segment in uip_buf and pointed
|
|
- * to by uip_appdata.
|
|
- */
|
|
-u16_t uip_tcpchksum(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
|
|
- *
|
|
- * The UDP checksum is the Internet checksum of data contents of the
|
|
- * UDP segment, and a pseudo-header as defined in RFC768.
|
|
- *
|
|
- * \return The UDP checksum of the UDP segment in uip_buf and pointed
|
|
- * to by uip_appdata.
|
|
- */
|
|
-u16_t uip_udpchksum(struct uip_stack *ustack);
|
|
-
|
|
-/* IPv6 checksum */
|
|
-uint16_t icmpv6_checksum(uint8_t *data);
|
|
-
|
|
-struct neighbor_entry {
|
|
- struct in6_addr ipaddr;
|
|
- struct uip_eth_addr mac_addr;
|
|
- u8_t time;
|
|
-};
|
|
-
|
|
-struct uip_stack {
|
|
- struct uip_eth_addr uip_ethaddr;
|
|
-
|
|
- u8_t *uip_buf;
|
|
-
|
|
- uint8_t *data_link_layer; /* Pointer to the data link layer */
|
|
- uint8_t *network_layer; /* Pointer to the network layer */
|
|
- void *uip_appdata; /* The uip_appdata pointer points to
|
|
- application data. */
|
|
- void *uip_sappdata; /* The uip_appdata pointer points to
|
|
- the application data which is to
|
|
- be sent. */
|
|
-#if UIP_URGDATA > 0
|
|
- void *uip_urgdata; /* The uip_urgdata pointer points to
|
|
- urgent data (out-of-band data), if
|
|
- present. */
|
|
- u16_t uip_urglen, uip_surglen;
|
|
-#endif /* UIP_URGDATA > 0 */
|
|
-
|
|
- u16_t uip_len, uip_slen; /* The uip_len is either 8 or 16 bits,
|
|
- depending on the maximum packet
|
|
- size. */
|
|
- u8_t uip_flags; /* The uip_flags variable is used for
|
|
- communication between the TCP/IP stack
|
|
- and the application program. */
|
|
- struct uip_conn *uip_conn; /* uip_conn always points to the current
|
|
- connection. */
|
|
-
|
|
- struct uip_conn uip_conns[UIP_CONNS];
|
|
- /* The uip_conns array holds all TCP
|
|
- connections. */
|
|
- u16_t uip_listenports[UIP_LISTENPORTS];
|
|
- /* The uip_listenports list all currently
|
|
- listning ports. */
|
|
-#if UIP_UDP
|
|
- struct uip_udp_conn *uip_udp_conn;
|
|
- struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
|
-#endif /* UIP_UDP */
|
|
-
|
|
- u16_t ipid; /* This ipid variable is an increasing
|
|
- number that is used for the IP ID
|
|
- field. */
|
|
-
|
|
- u8_t iss[4]; /* The iss variable is used for the TCP
|
|
- initial sequence number. */
|
|
-
|
|
-#if UIP_ACTIVE_OPEN
|
|
- u16_t lastport; /* Keeps track of the last port used for
|
|
- a new connection. */
|
|
-#endif /* UIP_ACTIVE_OPEN */
|
|
-
|
|
-#define IP_CONFIG_OFF 0x00
|
|
-#define IPV4_CONFIG_OFF 0x01
|
|
-#define IPV4_CONFIG_STATIC 0x02
|
|
-#define IPV4_CONFIG_DHCP 0x04
|
|
-#define IPV6_CONFIG_OFF 0x10
|
|
-#define IPV6_CONFIG_STATIC 0x20
|
|
-#define IPV6_CONFIG_DHCP 0x40
|
|
- u8_t ip_config;
|
|
-
|
|
- uip_ip4addr_t hostaddr, netmask, default_route_addr;
|
|
- uip_ip6addr_t hostaddr6, netmask6, default_route_addr6,
|
|
- linklocal6;
|
|
- int prefix_len;
|
|
- u8_t ipv6_autocfg;
|
|
-#define IPV6_AUTOCFG_DHCPV6 (1<<0)
|
|
-#define IPV6_AUTOCFG_ND (1<<1)
|
|
-#define IPV6_AUTOCFG_NOTSPEC (1<<6)
|
|
-#define IPV6_AUTOCFG_NOTUSED (1<<7)
|
|
- u8_t linklocal_autocfg;
|
|
-#define IPV6_LL_AUTOCFG_ON (1<<0)
|
|
-#define IPV6_LL_AUTOCFG_OFF (1<<1)
|
|
-#define IPV6_LL_AUTOCFG_NOTSPEC (1<<6)
|
|
-#define IPV6_LL_AUTOCFG_NOTUSED (1<<7)
|
|
- u8_t router_autocfg;
|
|
-#define IPV6_RTR_AUTOCFG_ON (1<<0)
|
|
-#define IPV6_RTR_AUTOCFG_OFF (1<<1)
|
|
-#define IPV6_RTR_AUTOCFG_NOTSPEC (1<<6)
|
|
-#define IPV6_RTR_AUTOCFG_NOTUSED (1<<7)
|
|
-
|
|
-#define UIP_NEIGHBOR_ENTRIES 8
|
|
- struct neighbor_entry neighbor_entries[UIP_NEIGHBOR_ENTRIES];
|
|
-
|
|
- struct uip_stats stats;
|
|
-
|
|
- u8_t opt;
|
|
-
|
|
- pthread_mutex_t lock;
|
|
-
|
|
- /* IPv6 support */
|
|
-#define UIP_SUPPORT_IPv6_ENABLED 0x01
|
|
-#define UIP_SUPPORT_IPv6_DISABLED 0x02
|
|
- u8_t enable_IPv6;
|
|
-
|
|
- /* DHCPC client attached */
|
|
- void *dhcpc;
|
|
-
|
|
- /* NDP client */
|
|
- void *ndpc;
|
|
-
|
|
- void *ping_conf;
|
|
-};
|
|
-
|
|
-/*******************************************************************************
|
|
- * IPv6 Support
|
|
- ******************************************************************************/
|
|
-int set_ipv6_link_local_address(struct uip_stack *ustack);
|
|
-int is_ipv6_link_local_address(uip_ip6addr_t *addr);
|
|
-
|
|
-void dump_uip_packet(struct uip_stack *ustack);
|
|
-u16_t uip_icmp6chksum(struct uip_stack *ustack);
|
|
-
|
|
-#endif /* __UIP_H__ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/uip_arch.h b/iscsiuio/src/uip/uip_arch.h
|
|
deleted file mode 100644
|
|
index 3ddacec..0000000
|
|
--- a/iscsiuio/src/uip/uip_arch.h
|
|
+++ /dev/null
|
|
@@ -1,137 +0,0 @@
|
|
-/**
|
|
- * \addtogroup uip
|
|
- * {@
|
|
- */
|
|
-
|
|
-/**
|
|
- * \defgroup uiparch Architecture specific uIP functions
|
|
- * @{
|
|
- *
|
|
- * The functions in the architecture specific module implement the IP
|
|
- * check sum and 32-bit additions.
|
|
- *
|
|
- * The IP checksum calculation is the most computationally expensive
|
|
- * operation in the TCP/IP stack and it therefore pays off to
|
|
- * implement this in efficient assembler. The purpose of the uip-arch
|
|
- * module is to let the checksum functions to be implemented in
|
|
- * architecture specific assembler.
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Declarations of architecture specific functions.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __UIP_ARCH_H__
|
|
-#define __UIP_ARCH_H__
|
|
-
|
|
-#include "uip.h"
|
|
-
|
|
-/**
|
|
- * Carry out a 32-bit addition.
|
|
- *
|
|
- * Because not all architectures for which uIP is intended has native
|
|
- * 32-bit arithmetic, uIP uses an external C function for doing the
|
|
- * required 32-bit additions in the TCP protocol processing. This
|
|
- * function should add the two arguments and place the result in the
|
|
- * global variable uip_acc32.
|
|
- *
|
|
- * \note The 32-bit integer pointed to by the op32 parameter and the
|
|
- * result in the uip_acc32 variable are in network byte order (big
|
|
- * endian).
|
|
- *
|
|
- * \param op32 A pointer to a 4-byte array representing a 32-bit
|
|
- * integer in network byte order (big endian).
|
|
- *
|
|
- * \param op16 A 16-bit integer in host byte order.
|
|
- */
|
|
-void uip_add32(u8_t *op32, u16_t op16, u8_t *uip_add32);
|
|
-
|
|
-/**
|
|
- * Calculate the Internet checksum over a buffer.
|
|
- *
|
|
- * The Internet checksum is the one's complement of the one's
|
|
- * complement sum of all 16-bit words in the buffer.
|
|
- *
|
|
- * See RFC1071.
|
|
- *
|
|
- * \note This function is not called in the current version of uIP,
|
|
- * but future versions might make use of it.
|
|
- *
|
|
- * \param buf A pointer to the buffer over which the checksum is to be
|
|
- * computed.
|
|
- *
|
|
- * \param len The length of the buffer over which the checksum is to
|
|
- * be computed.
|
|
- *
|
|
- * \return The Internet checksum of the buffer.
|
|
- */
|
|
-u16_t uip_chksum(u16_t *buf, u16_t len);
|
|
-
|
|
-/**
|
|
- * Calculate the IP header checksum of the packet header in uip_buf.
|
|
- *
|
|
- * The IP header checksum is the Internet checksum of the 20 bytes of
|
|
- * the IP header.
|
|
- *
|
|
- * \return The IP header checksum of the IP header in the uip_buf
|
|
- * buffer.
|
|
- */
|
|
-u16_t uip_ipchksum(struct uip_stack *ustack);
|
|
-
|
|
-/**
|
|
- * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
|
|
- *
|
|
- * The TCP checksum is the Internet checksum of data contents of the
|
|
- * TCP segment, and a pseudo-header as defined in RFC793.
|
|
- *
|
|
- * \note The uip_appdata pointer that points to the packet data may
|
|
- * point anywhere in memory, so it is not possible to simply calculate
|
|
- * the Internet checksum of the contents of the uip_buf buffer.
|
|
- *
|
|
- * \return The TCP checksum of the TCP segment in uip_buf and pointed
|
|
- * to by uip_appdata.
|
|
- */
|
|
-u16_t uip_tcpchksum(struct uip_stack *ustack);
|
|
-
|
|
-u16_t uip_udpchksum(struct uip_stack *ustack);
|
|
-
|
|
-/** @} */
|
|
-/** @} */
|
|
-
|
|
-#endif /* __UIP_ARCH_H__ */
|
|
diff --git a/iscsiuio/src/uip/uip_arp.c b/iscsiuio/src/uip/uip_arp.c
|
|
deleted file mode 100644
|
|
index 1b3761f..0000000
|
|
--- a/iscsiuio/src/uip/uip_arp.c
|
|
+++ /dev/null
|
|
@@ -1,479 +0,0 @@
|
|
-#include <errno.h>
|
|
-#include <netinet/in.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-#include "logger.h"
|
|
-#include "packet.h"
|
|
-
|
|
-/**
|
|
- * \addtogroup uip
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \defgroup uiparp uIP Address Resolution Protocol
|
|
- * @{
|
|
- *
|
|
- * The Address Resolution Protocol ARP is used for mapping between IP
|
|
- * addresses and link level addresses such as the Ethernet MAC
|
|
- * addresses. ARP uses broadcast queries to ask for the link level
|
|
- * address of a known IP address and the host which is configured with
|
|
- * the IP address for which the query was meant, will respond with its
|
|
- * link level address.
|
|
- *
|
|
- * \note This ARP implementation only supports Ethernet.
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Implementation of the ARP Address Resolution Protocol.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- *
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001-2003, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#include "uip_arp.h"
|
|
-#include "uip_eth.h"
|
|
-
|
|
-#include <pthread.h>
|
|
-#include <string.h>
|
|
-
|
|
-static const struct uip_eth_addr broadcast_ethaddr = {
|
|
- {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
|
|
-static const u16_t broadcast_ipaddr[2] = { 0xffff, 0xffff };
|
|
-
|
|
-pthread_mutex_t arp_table_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
-static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
|
|
-
|
|
-static u8_t arptime;
|
|
-
|
|
-/**
|
|
- * Initialize the ARP module.
|
|
- *
|
|
- */
|
|
-/*----------------------------------------------------------------------------*/
|
|
-void uip_arp_init(void)
|
|
-{
|
|
- u8_t i;
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i)
|
|
- memset(&arp_table[i], 0, sizeof(arp_table[i]));
|
|
-
|
|
- pthread_mutex_init(&arp_table_mutex, NULL);
|
|
-}
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-/**
|
|
- * Periodic ARP processing function.
|
|
- *
|
|
- * This function performs periodic timer processing in the ARP module
|
|
- * and should be called at regular intervals. The recommended interval
|
|
- * is 10 seconds between the calls.
|
|
- *
|
|
- */
|
|
-/*----------------------------------------------------------------------------*/
|
|
-void uip_arp_timer(void)
|
|
-{
|
|
- u8_t i;
|
|
- struct arp_entry *tabptr;
|
|
-
|
|
- ++arptime;
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
- tabptr = &arp_table[i];
|
|
- if ((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
|
|
- (u8_t)(arptime - tabptr->time) >= UIP_ARP_MAXAGE)
|
|
- memset(tabptr->ipaddr, 0, 4);
|
|
- }
|
|
-
|
|
-}
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-static void uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
|
|
-{
|
|
- u8_t i;
|
|
- struct arp_entry *tabptr;
|
|
-
|
|
- pthread_mutex_lock(&arp_table_mutex);
|
|
- /* Walk through the ARP mapping table and try to find an entry to
|
|
- update. If none is found, the IP -> MAC address mapping is
|
|
- inserted in the ARP table. */
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
-
|
|
- tabptr = &arp_table[i];
|
|
- /* Only check those entries that are actually in use. */
|
|
- if (tabptr->ipaddr[0] != 0 && tabptr->ipaddr[1] != 0) {
|
|
-
|
|
- /* Check if the source IP address of the incoming packet
|
|
- matches the IP address in this ARP table entry. */
|
|
- if (ipaddr[0] == tabptr->ipaddr[0] &&
|
|
- ipaddr[1] == tabptr->ipaddr[1]) {
|
|
-
|
|
- tabptr->time = arptime;
|
|
-
|
|
- pthread_mutex_unlock(&arp_table_mutex);
|
|
- return;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* If we get here, no existing ARP table entry was found, so we
|
|
- create one. */
|
|
-
|
|
- /* First, we try to find an unused entry in the ARP table. */
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
- tabptr = &arp_table[i];
|
|
- if (tabptr->ipaddr[0] == 0 && tabptr->ipaddr[1] == 0)
|
|
- break;
|
|
- }
|
|
-
|
|
- /* If no unused entry is found, we try to find the oldest entry and
|
|
- throw it away. */
|
|
- if (i == UIP_ARPTAB_SIZE) {
|
|
- u8_t c;
|
|
- u8_t tmpage = 0;
|
|
- c = 0;
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
- tabptr = &arp_table[i];
|
|
- if ((u8_t)(arptime - tabptr->time) > tmpage) {
|
|
- tmpage = (u8_t)(arptime - tabptr->time);
|
|
- c = i;
|
|
- }
|
|
- }
|
|
- i = c;
|
|
- tabptr = &arp_table[i];
|
|
- }
|
|
-
|
|
- /* Now, i is the ARP table entry which we will fill with the new
|
|
- information. */
|
|
- memcpy(tabptr->ipaddr, ipaddr, 4);
|
|
- memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
|
- tabptr->time = arptime;
|
|
-
|
|
- pthread_mutex_unlock(&arp_table_mutex);
|
|
-}
|
|
-
|
|
-/**
|
|
- * ARP processing for incoming ARP packets.
|
|
- *
|
|
- * This function should be called by the device driver when an ARP
|
|
- * packet has been received. The function will act differently
|
|
- * depending on the ARP packet type: if it is a reply for a request
|
|
- * that we previously sent out, the ARP cache will be filled in with
|
|
- * the values from the ARP reply. If the incoming ARP packet is an ARP
|
|
- * request for our IP address, an ARP reply packet is created and put
|
|
- * into the uip_buf[] buffer.
|
|
- *
|
|
- * When the function returns, the value of the global variable uip_len
|
|
- * indicates whether the device driver should send out a packet or
|
|
- * not. If uip_len is zero, no packet should be sent. If uip_len is
|
|
- * non-zero, it contains the length of the outbound packet that is
|
|
- * present in the uip_buf[] buffer.
|
|
- *
|
|
- * This function expects an ARP packet with a prepended Ethernet
|
|
- * header in the uip_buf[] buffer, and the length of the packet in the
|
|
- * global variable uip_len.
|
|
- */
|
|
-void uip_arp_ipin(struct uip_stack *ustack, packet_t *pkt)
|
|
-{
|
|
- struct ip_hdr *ip;
|
|
- struct uip_eth_hdr *eth;
|
|
-
|
|
- eth = (struct uip_eth_hdr *)pkt->data_link_layer;
|
|
- ip = (struct ip_hdr *)pkt->network_layer;
|
|
-
|
|
- if (uip_ip4addr_cmp(ip->destipaddr, ustack->hostaddr)) {
|
|
- /* First, we register the one who made the request in our ARP
|
|
- table, since it is likely that we will do more communication
|
|
- with this host in the future. */
|
|
- uip_arp_update(ip->srcipaddr, ð->src);
|
|
- }
|
|
-}
|
|
-
|
|
-void
|
|
-uip_arp_arpin(nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, packet_t *pkt)
|
|
-{
|
|
- struct arp_hdr *arp;
|
|
- struct uip_eth_hdr *eth;
|
|
-
|
|
- if (pkt->buf_size < sizeof(struct arp_hdr)) {
|
|
- pkt->buf_size = 0;
|
|
- return;
|
|
- }
|
|
- pkt->buf_size = 0;
|
|
-
|
|
- eth = (struct uip_eth_hdr *)pkt->data_link_layer;
|
|
- arp = (struct arp_hdr *)pkt->network_layer;
|
|
-
|
|
- switch (arp->opcode) {
|
|
- case const_htons(ARP_REQUEST):
|
|
- /* ARP request. If it asked for our address, we send out a
|
|
- reply. */
|
|
- if (uip_ip4addr_cmp(arp->dipaddr, ustack->hostaddr)) {
|
|
- /* First, we register the one who made the request in
|
|
- our ARP table, since it is likely that we will do
|
|
- more communication with this host in the future. */
|
|
- uip_arp_update(arp->sipaddr, &arp->shwaddr);
|
|
-
|
|
- /* The reply opcode is 2. */
|
|
- arp->opcode = htons(2);
|
|
-
|
|
- memcpy(arp->dhwaddr.addr, arp->shwaddr.addr, 6);
|
|
- memcpy(arp->shwaddr.addr, ustack->uip_ethaddr.addr, 6);
|
|
- memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6);
|
|
- memcpy(eth->dest.addr, arp->dhwaddr.addr, 6);
|
|
-
|
|
- arp->dipaddr[0] = arp->sipaddr[0];
|
|
- arp->dipaddr[1] = arp->sipaddr[1];
|
|
- arp->sipaddr[0] = ustack->hostaddr[0];
|
|
- arp->sipaddr[1] = ustack->hostaddr[1];
|
|
-
|
|
- if (nic_iface->vlan_id == 0) {
|
|
- eth->type = htons(UIP_ETHTYPE_ARP);
|
|
- pkt->buf_size = sizeof(*arp) + sizeof(*eth);
|
|
- } else {
|
|
- eth->type = htons(UIP_ETHTYPE_8021Q);
|
|
- pkt->buf_size = sizeof(*arp) +
|
|
- sizeof(struct uip_vlan_eth_hdr);
|
|
- }
|
|
- }
|
|
- break;
|
|
- case const_htons(ARP_REPLY):
|
|
- uip_arp_update(arp->sipaddr, &arp->shwaddr);
|
|
- break;
|
|
- default:
|
|
- LOG_WARN("Unknown ARP opcode: %d", ntohs(arp->opcode));
|
|
- break;
|
|
- }
|
|
-
|
|
- return;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Prepend Ethernet header to an outbound IP packet and see if we need
|
|
- * to send out an ARP request.
|
|
- *
|
|
- * This function should be called before sending out an IP packet. The
|
|
- * function checks the destination IP address of the IP packet to see
|
|
- * what Ethernet MAC address that should be used as a destination MAC
|
|
- * address on the Ethernet.
|
|
- *
|
|
- * If the destination IP address is in the local network (determined
|
|
- * by logical ANDing of netmask and our IP address), the function
|
|
- * checks the ARP cache to see if an entry for the destination IP
|
|
- * address is found. If so, an Ethernet header is prepended and the
|
|
- * function returns. If no ARP cache entry is found for the
|
|
- * destination IP address, the packet in the uip_buf[] is replaced by
|
|
- * an ARP request packet for the IP address. The IP packet is dropped
|
|
- * and it is assumed that they higher level protocols (e.g., TCP)
|
|
- * eventually will retransmit the dropped packet.
|
|
- *
|
|
- * If the destination IP address is not on the local network, the IP
|
|
- * address of the default router is used instead.
|
|
- *
|
|
- * When the function returns, a packet is present in the uip_buf[]
|
|
- * buffer, and the length of the packet is in the global variable
|
|
- * uip_len.
|
|
- */
|
|
-
|
|
-dest_ipv4_addr_t
|
|
-uip_determine_dest_ipv4_addr(struct uip_stack *ustack, u16_t *ipaddr)
|
|
-{
|
|
- struct uip_eth_hdr *eth;
|
|
- struct ip_hdr *ip_buf;
|
|
-
|
|
- eth = (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
- ip_buf = (struct ip_hdr *)ustack->network_layer;
|
|
-
|
|
- /* Find the destination IP address in the ARP table and construct
|
|
- the Ethernet header. If the destination IP addres isn't on the
|
|
- local network, we use the default router's IP address instead.
|
|
-
|
|
- If not ARP table entry is found, we overwrite the original IP
|
|
- packet with an ARP request for the IP address. */
|
|
-
|
|
- /* First check if destination is a local broadcast. */
|
|
- if (uip_ip4addr_cmp(ip_buf->destipaddr, broadcast_ipaddr)) {
|
|
- memcpy(ð->dest, broadcast_ethaddr.addr, 6);
|
|
-
|
|
- return LOCAL_BROADCAST;
|
|
- } else {
|
|
- /* Check if the destination address is on the local network. */
|
|
- if (!uip_ip4addr_maskcmp(ip_buf->destipaddr,
|
|
- ustack->hostaddr, ustack->netmask)) {
|
|
- /* Destination address was not on the local network,
|
|
- so we need to use the default router's IP address
|
|
- instead of the destination address when determining
|
|
- the MAC address. */
|
|
- uip_ip4addr_copy(ipaddr, ustack->default_route_addr);
|
|
- } else {
|
|
- /* Else, we use the destination IP address. */
|
|
- uip_ip4addr_copy(ipaddr, ip_buf->destipaddr);
|
|
- }
|
|
-
|
|
- return NONLOCAL_BROADCAST;
|
|
- }
|
|
-}
|
|
-
|
|
-arp_out_t is_in_arp_table(u16_t *ipaddr, struct arp_entry **tabptr)
|
|
-{
|
|
- u8_t i;
|
|
-
|
|
- pthread_mutex_lock(&arp_table_mutex);
|
|
-
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
- if (uip_ip4addr_cmp(ipaddr, arp_table[i].ipaddr)) {
|
|
- *tabptr = &arp_table[i];
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&arp_table_mutex);
|
|
-
|
|
- if (i == UIP_ARPTAB_SIZE)
|
|
- return NOT_IN_ARP_TABLE;
|
|
- else
|
|
- return IS_IN_ARP_TABLE;
|
|
-}
|
|
-
|
|
-void uip_build_arp_request(struct uip_stack *ustack, u16_t *ipaddr)
|
|
-{
|
|
- struct arp_hdr *arp;
|
|
- struct uip_eth_hdr *eth;
|
|
-
|
|
- arp = (struct arp_hdr *)ustack->network_layer;
|
|
- eth = (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
-
|
|
- /* The destination address was not in our ARP table, so we
|
|
- overwrite the IP packet with an ARP request. */
|
|
-
|
|
- memset(eth->dest.addr, 0xff, 6);
|
|
- memset(arp->dhwaddr.addr, 0x00, 6);
|
|
- memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6);
|
|
- memcpy(arp->shwaddr.addr, ustack->uip_ethaddr.addr, 6);
|
|
-
|
|
- uip_ip4addr_copy(arp->dipaddr, ipaddr);
|
|
- uip_ip4addr_copy(arp->sipaddr, ustack->hostaddr);
|
|
- arp->opcode = const_htons(ARP_REQUEST); /* ARP request. */
|
|
- arp->hwtype = const_htons(ARP_HWTYPE_ETH);
|
|
- arp->protocol = const_htons(UIP_ETHTYPE_IPv4);
|
|
- arp->hwlen = 6;
|
|
- arp->protolen = 4;
|
|
- eth->type = const_htons(UIP_ETHTYPE_ARP);
|
|
-
|
|
- ustack->uip_appdata = &ustack->uip_buf[UIP_TCP_IPv4_HLEN + UIP_LLH_LEN];
|
|
-
|
|
- ustack->uip_len = sizeof(*arp) + sizeof(*eth);
|
|
-}
|
|
-
|
|
-void
|
|
-uip_build_eth_header(struct uip_stack *ustack,
|
|
- u16_t *ipaddr,
|
|
- struct arp_entry *tabptr,
|
|
- struct packet *pkt, u16_t vlan_id)
|
|
-{
|
|
- struct uip_ipv4_hdr *ip_buf;
|
|
- struct uip_eth_hdr *eth;
|
|
- struct uip_vlan_eth_hdr *eth_vlan;
|
|
-
|
|
- ip_buf = (struct uip_ipv4_hdr *)ustack->network_layer;
|
|
- eth = (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
- eth_vlan = (struct uip_vlan_eth_hdr *)ustack->data_link_layer;
|
|
-
|
|
- /* First check if destination is a local broadcast. */
|
|
- if (uip_ip4addr_cmp(ip_buf->destipaddr, broadcast_ipaddr)) {
|
|
- memcpy(eth->dest.addr, broadcast_ethaddr.addr, 6);
|
|
- } else {
|
|
- /* Build an ethernet header. */
|
|
- memcpy(eth->dest.addr, tabptr->ethaddr.addr, 6);
|
|
- }
|
|
- memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6);
|
|
-
|
|
- if (vlan_id == 0) {
|
|
- eth->type = htons(UIP_ETHTYPE_IPv4);
|
|
-
|
|
- ustack->uip_len += sizeof(struct uip_eth_hdr);
|
|
- pkt->buf_size += sizeof(struct uip_eth_hdr);
|
|
- } else {
|
|
- eth_vlan->tpid = htons(UIP_ETHTYPE_8021Q);
|
|
- eth_vlan->vid = htons(vlan_id);
|
|
- eth_vlan->type = htons(UIP_ETHTYPE_IPv4);
|
|
-
|
|
- ustack->uip_len += sizeof(struct uip_vlan_eth_hdr);
|
|
- pkt->buf_size += sizeof(struct uip_vlan_eth_hdr);
|
|
- }
|
|
-}
|
|
-
|
|
-static struct arp_entry *uip_get_arp_entry(int index)
|
|
-{
|
|
- return &arp_table[index];
|
|
-}
|
|
-
|
|
-int uip_lookup_arp_entry(uint32_t ip_addr, uint8_t *mac_addr)
|
|
-{
|
|
- int i;
|
|
- int rc = -EINVAL;
|
|
-
|
|
- pthread_mutex_lock(&arp_table_mutex);
|
|
-
|
|
- for (i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
|
- struct arp_entry *entry = uip_get_arp_entry(i);
|
|
-
|
|
- if (((entry->ipaddr[1] << 16) == (ip_addr & 0xffff0000)) &&
|
|
- ((entry->ipaddr[0]) == (ip_addr & 0x0000ffff))) {
|
|
- struct in_addr addr;
|
|
- char *addr_str;
|
|
-
|
|
- addr.s_addr = ip_addr;
|
|
- addr_str = inet_ntoa(addr);
|
|
-
|
|
- memcpy(mac_addr, entry->ethaddr.addr, 6);
|
|
-
|
|
- LOG_INFO("Found %s at %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- addr_str,
|
|
- mac_addr[0], mac_addr[1], mac_addr[2],
|
|
- mac_addr[3], mac_addr[4], mac_addr[5]);
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&arp_table_mutex);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-
|
|
-/** @} */
|
|
-/** @} */
|
|
diff --git a/iscsiuio/src/uip/uip_arp.h b/iscsiuio/src/uip/uip_arp.h
|
|
deleted file mode 100644
|
|
index 339d57d..0000000
|
|
--- a/iscsiuio/src/uip/uip_arp.h
|
|
+++ /dev/null
|
|
@@ -1,197 +0,0 @@
|
|
-/**
|
|
- * \addtogroup uip
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \addtogroup uiparp
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Macros and definitions for the ARP module.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001-2003, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __UIP_ARP_H__
|
|
-#define __UIP_ARP_H__
|
|
-
|
|
-#include "packet.h"
|
|
-#include "uip.h"
|
|
-#include "uip_eth.h"
|
|
-
|
|
-#define ARP_REQUEST 1
|
|
-#define ARP_REPLY 2
|
|
-
|
|
-#define ARP_HWTYPE_ETH 1
|
|
-
|
|
-struct __attribute__ ((__packed__)) arp_hdr {
|
|
- u16_t hwtype;
|
|
- u16_t protocol;
|
|
- u8_t hwlen;
|
|
- u8_t protolen;
|
|
- u16_t opcode;
|
|
- struct uip_eth_addr shwaddr;
|
|
- u16_t sipaddr[2];
|
|
- struct uip_eth_addr dhwaddr;
|
|
- u16_t dipaddr[2];
|
|
-};
|
|
-
|
|
-struct __attribute__ ((__packed__)) ip_hdr {
|
|
- /* IP header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-};
|
|
-
|
|
-struct __attribute__ ((__packed__)) ethip_hdr {
|
|
- struct uip_eth_hdr ethhdr;
|
|
- /* IP header. */
|
|
- u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto;
|
|
- u16_t ipchksum;
|
|
- u16_t srcipaddr[2], destipaddr[2];
|
|
-};
|
|
-
|
|
-struct arp_entry {
|
|
- u16_t ipaddr[2];
|
|
- struct uip_eth_addr ethaddr;
|
|
- u8_t time;
|
|
-};
|
|
-
|
|
-/* The uip_arp_init() function must be called before any of the other
|
|
- ARP functions. */
|
|
-void uip_arp_init(void);
|
|
-
|
|
-/* The uip_arp_ipin() function should be called whenever an IP packet
|
|
- arrives from the Ethernet. This function refreshes the ARP table or
|
|
- inserts a new mapping if none exists. The function assumes that an
|
|
- IP packet with an Ethernet header is present in the uip_buf buffer
|
|
- and that the length of the packet is in the uip_len variable. */
|
|
-/*void uip_arp_ipin(void);*/
|
|
-/* #define uip_arp_ipin() */
|
|
-void uip_arp_ipin(struct uip_stack *ustack, struct packet *pkt);
|
|
-
|
|
-/* The uip_arp_arpin() should be called when an ARP packet is received
|
|
- by the Ethernet driver. This function also assumes that the
|
|
- Ethernet frame is present in the uip_buf buffer. When the
|
|
- uip_arp_arpin() function returns, the contents of the uip_buf
|
|
- buffer should be sent out on the Ethernet if the uip_len variable
|
|
- is > 0. */
|
|
-void uip_arp_arpin(nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, struct packet *pkt);
|
|
-
|
|
-typedef enum {
|
|
- ARP_SENT = 1,
|
|
- ETH_HEADER_APPEDEND = 2,
|
|
-} arp_out_t;
|
|
-
|
|
-typedef enum {
|
|
- LOCAL_BROADCAST = 1,
|
|
- NONLOCAL_BROADCAST = 2,
|
|
-} dest_ipv4_addr_t;
|
|
-
|
|
-typedef enum {
|
|
- IS_IN_ARP_TABLE = 1,
|
|
- NOT_IN_ARP_TABLE = 2,
|
|
-} arp_table_query_t;
|
|
-
|
|
-dest_ipv4_addr_t
|
|
-uip_determine_dest_ipv4_addr(struct uip_stack *ustack, u16_t *ipaddr);
|
|
-arp_out_t is_in_arp_table(u16_t *ipaddr, struct arp_entry **tabptr);
|
|
-
|
|
-void uip_build_arp_request(struct uip_stack *ustack, u16_t *ipaddr);
|
|
-
|
|
-void
|
|
-uip_build_eth_header(struct uip_stack *ustack,
|
|
- u16_t *ipaddr,
|
|
- struct arp_entry *tabptr,
|
|
- struct packet *pkt, u16_t vlan_id);
|
|
-
|
|
-/* The uip_arp_out() function should be called when an IP packet
|
|
- should be sent out on the Ethernet. This function creates an
|
|
- Ethernet header before the IP header in the uip_buf buffer. The
|
|
- Ethernet header will have the correct Ethernet MAC destination
|
|
- address filled in if an ARP table entry for the destination IP
|
|
- address (or the IP address of the default router) is present. If no
|
|
- such table entry is found, the IP packet is overwritten with an ARP
|
|
- request and we rely on TCP to retransmit the packet that was
|
|
- overwritten. In any case, the uip_len variable holds the length of
|
|
- the Ethernet frame that should be transmitted. */
|
|
-arp_out_t uip_arp_out(struct uip_stack *ustack);
|
|
-
|
|
-/* The uip_arp_timer() function should be called every ten seconds. It
|
|
- is responsible for flushing old entries in the ARP table. */
|
|
-void uip_arp_timer(void);
|
|
-
|
|
-int uip_lookup_arp_entry(uint32_t ip_addr, uint8_t *mac_addr);
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/**
|
|
- * \addtogroup uipconffunc
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Specifiy the Ethernet MAC address.
|
|
- *
|
|
- * The ARP code needs to know the MAC address of the Ethernet card in
|
|
- * order to be able to respond to ARP queries and to generate working
|
|
- * Ethernet headers.
|
|
- *
|
|
- * \note This macro only specifies the Ethernet MAC address to the ARP
|
|
- * code. It cannot be used to change the MAC address of the Ethernet
|
|
- * card.
|
|
- *
|
|
- * \param eaddr A pointer to a struct uip_eth_addr containing the
|
|
- * Ethernet MAC address of the Ethernet card.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define uip_setethaddr(eaddr) do { \
|
|
- uip_ethaddr.addr[0] = eaddr.addr[0]; \
|
|
- uip_ethaddr.addr[1] = eaddr.addr[1]; \
|
|
- uip_ethaddr.addr[2] = eaddr.addr[2]; \
|
|
- uip_ethaddr.addr[3] = eaddr.addr[3]; \
|
|
- uip_ethaddr.addr[4] = eaddr.addr[4]; \
|
|
- uip_ethaddr.addr[5] = eaddr.addr[5]; \
|
|
- } while (0)
|
|
-
|
|
-/** @} */
|
|
-/** @} */
|
|
-
|
|
-#endif /* __UIP_ARP_H__ */
|
|
diff --git a/iscsiuio/src/uip/uip_eth.c b/iscsiuio/src/uip/uip_eth.c
|
|
deleted file mode 100644
|
|
index 9e1ea81..0000000
|
|
--- a/iscsiuio/src/uip/uip_eth.c
|
|
+++ /dev/null
|
|
@@ -1,50 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * uip_eth.c - CNIC UIO uIP user space stack
|
|
- *
|
|
- */
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uip_eth.h"
|
|
-
|
|
-int is_vlan_packet(struct uip_vlan_eth_hdr *hdr)
|
|
-{
|
|
- /* The TPID field in a 802.1Q Header must be 0x8100 */
|
|
- if (hdr->tpid == const_htons(UIP_ETHTYPE_8021Q))
|
|
- return 1;
|
|
-
|
|
- return 0;
|
|
-}
|
|
diff --git a/iscsiuio/src/uip/uip_eth.h b/iscsiuio/src/uip/uip_eth.h
|
|
deleted file mode 100644
|
|
index 830c04c..0000000
|
|
--- a/iscsiuio/src/uip/uip_eth.h
|
|
+++ /dev/null
|
|
@@ -1,43 +0,0 @@
|
|
-#ifndef __UIP_ETH_H__
|
|
-#define __UIP_ETH_H__
|
|
-
|
|
-#include "uipopt.h"
|
|
-
|
|
-/*******************************************************************************
|
|
- * Ether types
|
|
- ******************************************************************************/
|
|
-#define UIP_ETHTYPE_ARP 0x0806
|
|
-#define UIP_ETHTYPE_IPv4 0x0800
|
|
-#define UIP_ETHTYPE_8021Q 0x8100
|
|
-#define UIP_ETHTYPE_IPv6 0x86dd
|
|
-
|
|
-/**
|
|
- * Representation of a 48-bit Ethernet address.
|
|
- */
|
|
-struct uip_eth_addr {
|
|
- u8_t addr[6];
|
|
-};
|
|
-
|
|
-/**
|
|
- * The Ethernet header.
|
|
- */
|
|
-struct __attribute__ ((__packed__)) uip_eth_hdr {
|
|
- struct uip_eth_addr dest;
|
|
- struct uip_eth_addr src;
|
|
- u16_t type;
|
|
-};
|
|
-
|
|
-/**
|
|
- * The 802.1Q Ethernet header (VLAN).
|
|
- */
|
|
-struct __attribute__ ((__packed__)) uip_vlan_eth_hdr {
|
|
- struct uip_eth_addr dest;
|
|
- struct uip_eth_addr src;
|
|
- u16_t tpid;
|
|
- u16_t vid;
|
|
- u16_t type;
|
|
-};
|
|
-
|
|
-int is_vlan_packet(struct uip_vlan_eth_hdr *hdr);
|
|
-
|
|
-#endif /* __UIP_ETH_H__ */
|
|
diff --git a/iscsiuio/src/uip/uipopt.h b/iscsiuio/src/uip/uipopt.h
|
|
deleted file mode 100644
|
|
index bcc8949..0000000
|
|
--- a/iscsiuio/src/uip/uipopt.h
|
|
+++ /dev/null
|
|
@@ -1,536 +0,0 @@
|
|
-/**
|
|
- * \defgroup uipopt Configuration options for uIP
|
|
- * @{
|
|
- *
|
|
- * uIP is configured using the per-project configuration file
|
|
- * uipopt.h. This file contains all compile-time options for uIP and
|
|
- * should be tweaked to match each specific project. The uIP
|
|
- * distribution contains a documented example "uipopt.h" that can be
|
|
- * copied and modified for each project.
|
|
- *
|
|
- * \note Most of the configuration options in the uipopt.h should not
|
|
- * be changed, but rather the per-project uip-conf.h file.
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Configuration options for uIP.
|
|
- * \author Adam Dunkels <adam@dunkels.com>
|
|
- *
|
|
- * This file is used for tweaking various configuration options for
|
|
- * uIP. You should make a copy of this file into one of your project's
|
|
- * directories instead of editing this example "uipopt.h" file that
|
|
- * comes with the uIP distribution.
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2001-2003, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __UIPOPT_H__
|
|
-#define __UIPOPT_H__
|
|
-
|
|
-#ifndef UIP_LITTLE_ENDIAN
|
|
-#define UIP_LITTLE_ENDIAN 3412
|
|
-#endif /* UIP_LITTLE_ENDIAN */
|
|
-#ifndef UIP_BIG_ENDIAN
|
|
-#define UIP_BIG_ENDIAN 1234
|
|
-#endif /* UIP_BIG_ENDIAN */
|
|
-
|
|
-#include "uip-conf.h"
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-
|
|
-/**
|
|
- * \name Static configuration options
|
|
- * @{
|
|
- *
|
|
- * These configuration options can be used for setting the IP address
|
|
- * settings statically, but only if UIP_FIXEDADDR is set to 1. The
|
|
- * configuration options for a specific node includes IP address,
|
|
- * netmask and default router as well as the Ethernet address. The
|
|
- * netmask, default router and Ethernet address are appliciable only
|
|
- * if uIP should be run over Ethernet.
|
|
- *
|
|
- * All of these should be changed to suit your project.
|
|
-*/
|
|
-
|
|
-/**
|
|
- * Determines if uIP should use a fixed IP address or not.
|
|
- *
|
|
- * If uIP should use a fixed IP address, the settings are set in the
|
|
- * uipopt.h file. If not, the macros uip_sethostaddr(),
|
|
- * uip_setdraddr() and uip_setnetmask() should be used instead.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_FIXEDADDR 0
|
|
-
|
|
-/**
|
|
- * Ping IP address asignment.
|
|
- *
|
|
- * uIP uses a "ping" packets for setting its own IP address if this
|
|
- * option is set. If so, uIP will start with an empty IP address and
|
|
- * the destination IP address of the first incoming "ping" (ICMP echo)
|
|
- * packet will be used for setting the hosts IP address.
|
|
- *
|
|
- * \note This works only if UIP_FIXEDADDR is 0.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_PINGADDRCONF
|
|
-#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF
|
|
-#else /* UIP_CONF_PINGADDRCONF */
|
|
-#define UIP_PINGADDRCONF 0
|
|
-#endif /* UIP_CONF_PINGADDRCONF */
|
|
-
|
|
-/**
|
|
- * Specifies if the uIP ARP module should be compiled with a fixed
|
|
- * Ethernet MAC address or not.
|
|
- *
|
|
- * If this configuration option is 0, the macro uip_setethaddr() can
|
|
- * be used to specify the Ethernet address at run-time.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_FIXEDETHADDR 0
|
|
-
|
|
-/** @} */
|
|
-/*------------------------------------------------------------------------------*/
|
|
-/**
|
|
- * \name IP configuration options
|
|
- * @{
|
|
- *
|
|
- */
|
|
-/**
|
|
- * The IP TTL (time to live) of IP packets sent by uIP.
|
|
- *
|
|
- * This should normally not be changed.
|
|
- */
|
|
-#define UIP_TTL 64
|
|
-
|
|
-/**
|
|
- * Turn on support for IP packet reassembly.
|
|
- *
|
|
- * uIP supports reassembly of fragmented IP packets. This features
|
|
- * requires an additonal amount of RAM to hold the reassembly buffer
|
|
- * and the reassembly code size is approximately 700 bytes. The
|
|
- * reassembly buffer is of the same size as the uip_buf buffer
|
|
- * (configured by UIP_BUFSIZE).
|
|
- *
|
|
- * \note IP packet reassembly is not heavily tested.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_REASSEMBLY 0
|
|
-
|
|
-/**
|
|
- * The maximum time an IP fragment should wait in the reassembly
|
|
- * buffer before it is dropped.
|
|
- *
|
|
- */
|
|
-#define UIP_REASS_MAXAGE 40
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-/**
|
|
- * \name UDP configuration options
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Toggles wether UDP support should be compiled in or not.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_UDP
|
|
-#define UIP_UDP UIP_CONF_UDP
|
|
-#else /* UIP_CONF_UDP */
|
|
-#define UIP_UDP 0
|
|
-#endif /* UIP_CONF_UDP */
|
|
-
|
|
-/**
|
|
- * Toggles if UDP checksums should be used or not.
|
|
- *
|
|
- * \note Support for UDP checksums is currently not included in uIP,
|
|
- * so this option has no function.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_UDP_CHECKSUMS
|
|
-#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS
|
|
-#else
|
|
-#define UIP_UDP_CHECKSUMS 0
|
|
-#endif
|
|
-
|
|
-/**
|
|
- * The maximum amount of concurrent UDP connections.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_UDP_CONNS
|
|
-#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS
|
|
-#else /* UIP_CONF_UDP_CONNS */
|
|
-#define UIP_UDP_CONNS 10
|
|
-#endif /* UIP_CONF_UDP_CONNS */
|
|
-
|
|
-/**
|
|
- * The name of the function that should be called when UDP datagrams arrive.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-
|
|
-/** @} */
|
|
-/*------------------------------------------------------------------------------*/
|
|
-/**
|
|
- * \name TCP configuration options
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * Determines if support for opening connections from uIP should be
|
|
- * compiled in.
|
|
- *
|
|
- * If the applications that are running on top of uIP for this project
|
|
- * do not need to open outgoing TCP connections, this configration
|
|
- * option can be turned off to reduce the code size of uIP.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_ACTIVE_OPEN 1
|
|
-
|
|
-/**
|
|
- * The maximum number of simultaneously open TCP connections.
|
|
- *
|
|
- * Since the TCP connections are statically allocated, turning this
|
|
- * configuration knob down results in less RAM used. Each TCP
|
|
- * connection requires approximatly 30 bytes of memory.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_MAX_CONNECTIONS
|
|
-#define UIP_CONNS 10
|
|
-#else /* UIP_CONF_MAX_CONNECTIONS */
|
|
-#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS
|
|
-#endif /* UIP_CONF_MAX_CONNECTIONS */
|
|
-
|
|
-/**
|
|
- * The maximum number of simultaneously listening TCP ports.
|
|
- *
|
|
- * Each listening TCP port requires 2 bytes of memory.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_MAX_LISTENPORTS
|
|
-#define UIP_LISTENPORTS 20
|
|
-#else /* UIP_CONF_MAX_LISTENPORTS */
|
|
-#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS
|
|
-#endif /* UIP_CONF_MAX_LISTENPORTS */
|
|
-
|
|
-/**
|
|
- * Determines if support for TCP urgent data notification should be
|
|
- * compiled in.
|
|
- *
|
|
- * Urgent data (out-of-band data) is a rarely used TCP feature that
|
|
- * very seldom would be required.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_URGDATA 0
|
|
-
|
|
-/**
|
|
- * The initial retransmission timeout counted in timer pulses.
|
|
- *
|
|
- * This should not be changed.
|
|
- */
|
|
-#define UIP_RTO 3
|
|
-
|
|
-/**
|
|
- * The maximum number of times a segment should be retransmitted
|
|
- * before the connection should be aborted.
|
|
- *
|
|
- * This should not be changed.
|
|
- */
|
|
-#define UIP_MAXRTX 8
|
|
-
|
|
-/**
|
|
- * The maximum number of times a SYN segment should be retransmitted
|
|
- * before a connection request should be deemed to have been
|
|
- * unsuccessful.
|
|
- *
|
|
- * This should not need to be changed.
|
|
- */
|
|
-#define UIP_MAXSYNRTX 5
|
|
-
|
|
-/**
|
|
- * The TCP maximum segment size.
|
|
- *
|
|
- * This is should not be to set to more than
|
|
- * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
|
|
- */
|
|
-#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCP_IPv4_HLEN)
|
|
-
|
|
-/**
|
|
- * The size of the advertised receiver's window.
|
|
- *
|
|
- * Should be set low (i.e., to the size of the uip_buf buffer) is the
|
|
- * application is slow to process incoming data, or high (32768 bytes)
|
|
- * if the application processes data quickly.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_RECEIVE_WINDOW
|
|
-#define UIP_RECEIVE_WINDOW UIP_TCP_MSS
|
|
-#else
|
|
-#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW
|
|
-#endif
|
|
-
|
|
-/**
|
|
- * How long a connection should stay in the TIME_WAIT state.
|
|
- *
|
|
- * This configiration option has no real implication, and it should be
|
|
- * left untouched.
|
|
- */
|
|
-#define UIP_TIME_WAIT_TIMEOUT 120
|
|
-
|
|
-/** @} */
|
|
-/*------------------------------------------------------------------------------*/
|
|
-/**
|
|
- * \name ARP configuration options
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * The size of the ARP table.
|
|
- *
|
|
- * This option should be set to a larger value if this uIP node will
|
|
- * have many connections from the local network.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_ARPTAB_SIZE
|
|
-#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE
|
|
-#else
|
|
-#define UIP_ARPTAB_SIZE 16
|
|
-#endif
|
|
-
|
|
-/**
|
|
- * The maxium age of ARP table entries measured in 10ths of seconds.
|
|
- *
|
|
- * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
|
|
- * default).
|
|
- * Changed the default to 30 which corresponds to 5 minutes (Linux default)
|
|
- */
|
|
-#define UIP_ARP_MAXAGE 30
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/*----------------------------------------------------------------------------*/
|
|
-
|
|
-/**
|
|
- * \name General configuration options
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * The size of the uIP packet buffer.
|
|
- *
|
|
- * The uIP packet buffer should not be smaller than 60 bytes, and does
|
|
- * not need to be larger than 1500 bytes. Lower size results in lower
|
|
- * TCP throughput, larger size results in higher TCP throughput.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_BUFFER_SIZE
|
|
-#define UIP_BUFSIZE 400
|
|
-#else /* UIP_CONF_BUFFER_SIZE */
|
|
-#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
|
|
-#endif /* UIP_CONF_BUFFER_SIZE */
|
|
-
|
|
-/**
|
|
- * Determines if statistics support should be compiled in.
|
|
- *
|
|
- * The statistics is useful for debugging and to show the user.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_STATISTICS
|
|
-#define UIP_STATISTICS 0
|
|
-#else /* UIP_CONF_STATISTICS */
|
|
-#define UIP_STATISTICS UIP_CONF_STATISTICS
|
|
-#endif /* UIP_CONF_STATISTICS */
|
|
-
|
|
-/**
|
|
- * Determines if logging of certain events should be compiled in.
|
|
- *
|
|
- * This is useful mostly for debugging. The function uip_log()
|
|
- * must be implemented to suit the architecture of the project, if
|
|
- * logging is turned on.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifndef UIP_CONF_LOGGING
|
|
-#define UIP_LOGGING 0
|
|
-#else /* UIP_CONF_LOGGING */
|
|
-#define UIP_LOGGING UIP_CONF_LOGGING
|
|
-#endif /* UIP_CONF_LOGGING */
|
|
-
|
|
-/**
|
|
- * Broadcast support.
|
|
- *
|
|
- * This flag configures IP broadcast support. This is useful only
|
|
- * together with UDP.
|
|
- *
|
|
- * \hideinitializer
|
|
- *
|
|
- */
|
|
-#ifndef UIP_CONF_BROADCAST
|
|
-#define UIP_BROADCAST 0
|
|
-#else /* UIP_CONF_BROADCAST */
|
|
-#define UIP_BROADCAST UIP_CONF_BROADCAST
|
|
-#endif /* UIP_CONF_BROADCAST */
|
|
-
|
|
-/**
|
|
- * Print out a uIP log message.
|
|
- *
|
|
- * This function must be implemented by the module that uses uIP, and
|
|
- * is called by uIP whenever a log message is generated.
|
|
- */
|
|
-void uip_log(char *msg);
|
|
-
|
|
-/**
|
|
- * The link level header length.
|
|
- *
|
|
- * This is the offset into the uip_buf where the IP header can be
|
|
- * found. For Ethernet, this should be set to 14. For SLIP, this
|
|
- * should be set to 0.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_LLH_LEN
|
|
-#define UIP_LLH_LEN UIP_CONF_LLH_LEN
|
|
-#else /* UIP_CONF_LLH_LEN */
|
|
-#define UIP_LLH_LEN 14
|
|
-#endif /* UIP_CONF_LLH_LEN */
|
|
-
|
|
-#if 0
|
|
-/** @} */
|
|
-/*------------------------------------------------------------------------------*/
|
|
-/**
|
|
- * \name CPU architecture configuration
|
|
- * @{
|
|
- *
|
|
- * The CPU architecture configuration is where the endianess of the
|
|
- * CPU on which uIP is to be run is specified. Most CPUs today are
|
|
- * little endian, and the most notable exception are the Motorolas
|
|
- * which are big endian. The BYTE_ORDER macro should be changed to
|
|
- * reflect the CPU architecture on which uIP is to be run.
|
|
- */
|
|
-
|
|
-/**
|
|
- * The byte order of the CPU architecture on which uIP is to be run.
|
|
- *
|
|
- * This option can be either BIG_ENDIAN (Motorola byte order) or
|
|
- * LITTLE_ENDIAN (Intel byte order).
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#ifdef UIP_CONF_BYTE_ORDER
|
|
-#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER
|
|
-#else /* UIP_CONF_BYTE_ORDER */
|
|
-#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
|
|
-#endif /* UIP_CONF_BYTE_ORDER */
|
|
-#endif
|
|
-
|
|
-/** @} */
|
|
-/*------------------------------------------------------------------------------*/
|
|
-
|
|
-/**
|
|
- * \name Appication specific configurations
|
|
- * @{
|
|
- *
|
|
- * An uIP application is implemented using a single application
|
|
- * function that is called by uIP whenever a TCP/IP event occurs. The
|
|
- * name of this function must be registered with uIP at compile time
|
|
- * using the UIP_APPCALL definition.
|
|
- *
|
|
- * uIP applications can store the application state within the
|
|
- * uip_conn structure by specifying the type of the application
|
|
- * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t.
|
|
- *
|
|
- * The file containing the definitions must be included in the
|
|
- * uipopt.h file.
|
|
- *
|
|
- * The following example illustrates how this can look.
|
|
- \code
|
|
-
|
|
-void httpd_appcall(void);
|
|
-#define UIP_APPCALL httpd_appcall
|
|
-
|
|
-struct httpd_state {
|
|
- u8_t state;
|
|
- u16_t count;
|
|
- char *dataptr;
|
|
- char *script;
|
|
-};
|
|
-typedef struct httpd_state uip_tcp_appstate_t
|
|
- \endcode
|
|
- */
|
|
-
|
|
-/**
|
|
- * \var #define UIP_APPCALL
|
|
- *
|
|
- * The name of the application function that uIP should call in
|
|
- * response to TCP/IP events.
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \var typedef uip_tcp_appstate_t
|
|
- *
|
|
- * The type of the application state that is to be stored in the
|
|
- * uip_conn structure. This usually is typedef:ed to a struct holding
|
|
- * application state information.
|
|
- */
|
|
-
|
|
-/**
|
|
- * \var typedef uip_udp_appstate_t
|
|
- *
|
|
- * The type of the application state that is to be stored in the
|
|
- * uip_conn structure. This usually is typedef:ed to a struct holding
|
|
- * application state information.
|
|
- */
|
|
-/** @} */
|
|
-/** @} */
|
|
-
|
|
-#endif /* __UIPOPT_H__ */
|
|
diff --git a/iscsiuio/src/unix/.gitignore b/iscsiuio/src/unix/.gitignore
|
|
deleted file mode 100644
|
|
index b3b37db..0000000
|
|
--- a/iscsiuio/src/unix/.gitignore
|
|
+++ /dev/null
|
|
@@ -1,3 +0,0 @@
|
|
-build_date.c
|
|
-build_date.h
|
|
-iscsiuio
|
|
diff --git a/iscsiuio/src/unix/Makefile.am b/iscsiuio/src/unix/Makefile.am
|
|
deleted file mode 100644
|
|
index a989ef0..0000000
|
|
--- a/iscsiuio/src/unix/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,41 +0,0 @@
|
|
-SUBDIRS= libs
|
|
-
|
|
-AM_CFLAGS = -I${top_srcdir}/src/uip \
|
|
- -I${top_srcdir}/src/apps/brcm-iscsi \
|
|
- -I${top_srcdir}/src/apps/dhcpc \
|
|
- -I${top_srcdir}/src/unix/libs \
|
|
- -I${top_srcdir}/../include \
|
|
- -I${top_srcdir}/../usr
|
|
-
|
|
-sbin_PROGRAMS = iscsiuio
|
|
-
|
|
-iscsiuio_SOURCES = build_date.c \
|
|
- main.c \
|
|
- clock-arch.c \
|
|
- logger.c \
|
|
- nic.c \
|
|
- nic_id.c \
|
|
- nic_vlan.c \
|
|
- nic_nl.c \
|
|
- nic_utils.c \
|
|
- packet.c \
|
|
- iscsid_ipc.c \
|
|
- ping.c \
|
|
- ${top_srcdir}/../utils/sysdeps/sysdeps.c
|
|
-
|
|
-iscsiuio_CFLAGS = $(AM_CFLAGS) \
|
|
- $(LIBNL_CFLAGS) \
|
|
- -DBYTE_ORDER=@ENDIAN@
|
|
-
|
|
-iscsiuio_LDFLAGS= $(AM_LDADD) \
|
|
- -ldl \
|
|
- -rdynamic \
|
|
- $(LIBNL_LIBS) \
|
|
- -lpthread
|
|
-
|
|
-iscsiuio_LDADD = ${top_srcdir}/src/uip/lib_iscsi_uip.a \
|
|
- ${top_srcdir}/src/apps/dhcpc/lib_apps_dhcpc.a\
|
|
- ${top_srcdir}/src/apps/brcm-iscsi/lib_apps_brcm_iscsi.a \
|
|
- ${top_srcdir}/src/unix/libs/lib_iscsiuio_hw_cnic.a
|
|
-
|
|
-iscsiuio_YFLAGS = -d
|
|
diff --git a/iscsiuio/src/unix/clock-arch.c b/iscsiuio/src/unix/clock-arch.c
|
|
deleted file mode 100644
|
|
index d853101..0000000
|
|
--- a/iscsiuio/src/unix/clock-arch.c
|
|
+++ /dev/null
|
|
@@ -1,54 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2006, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * Implementation of architecture-specific clock functionality
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-#include "clock-arch.h"
|
|
-#include <sys/time.h>
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
-clock_time_t clock_time(void)
|
|
-{
|
|
- struct timeval tv;
|
|
- struct timezone tz;
|
|
-
|
|
- gettimeofday(&tv, &tz);
|
|
-
|
|
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
-}
|
|
-
|
|
-/*---------------------------------------------------------------------------*/
|
|
diff --git a/iscsiuio/src/unix/clock-arch.h b/iscsiuio/src/unix/clock-arch.h
|
|
deleted file mode 100644
|
|
index 888933f..0000000
|
|
--- a/iscsiuio/src/unix/clock-arch.h
|
|
+++ /dev/null
|
|
@@ -1,39 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2006, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __CLOCK_ARCH_H__
|
|
-#define __CLOCK_ARCH_H__
|
|
-
|
|
-typedef int clock_time_t;
|
|
-#define CLOCK_CONF_SECOND 1000
|
|
-
|
|
-#endif /* __CLOCK_ARCH_H__ */
|
|
diff --git a/iscsiuio/src/unix/iscsid_ipc.c b/iscsiuio/src/unix/iscsid_ipc.c
|
|
deleted file mode 100644
|
|
index ea03d37..0000000
|
|
--- a/iscsiuio/src/unix/iscsid_ipc.c
|
|
+++ /dev/null
|
|
@@ -1,1255 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * iscsi_ipc.c - Generic NIC management/utility functions
|
|
- *
|
|
- */
|
|
-
|
|
-#define _GNU_SOURCE
|
|
-
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <signal.h>
|
|
-#include <string.h>
|
|
-#include <stdio.h>
|
|
-#include <unistd.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/time.h>
|
|
-#include <sys/un.h>
|
|
-#include <sys/types.h>
|
|
-#include <pwd.h>
|
|
-
|
|
-#define PFX "iscsi_ipc "
|
|
-
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "nic_vlan.h"
|
|
-#include "options.h"
|
|
-#include "mgmt_ipc.h"
|
|
-#include "iscsid_ipc.h"
|
|
-#include "uip.h"
|
|
-#include "uip_mgmt_ipc.h"
|
|
-#include "sysdeps.h"
|
|
-
|
|
-#include "logger.h"
|
|
-#include "uip.h"
|
|
-#include "ping.h"
|
|
-
|
|
-/* private iscsid options stucture */
|
|
-struct iscsid_options {
|
|
- int fd;
|
|
- pthread_t thread;
|
|
-};
|
|
-
|
|
-struct iface_rec_decode {
|
|
- /* General */
|
|
- int32_t iface_num;
|
|
- uint32_t ip_type;
|
|
-
|
|
- /* IPv4 */
|
|
- struct in_addr ipv4_addr;
|
|
- struct in_addr ipv4_subnet_mask;
|
|
- struct in_addr ipv4_gateway;
|
|
-
|
|
- /* IPv6 */
|
|
- struct in6_addr ipv6_addr;
|
|
- struct in6_addr ipv6_subnet_mask;
|
|
- uint32_t prefix_len;
|
|
- struct in6_addr ipv6_linklocal;
|
|
- struct in6_addr ipv6_router;
|
|
-
|
|
- uint8_t ipv6_autocfg;
|
|
- uint8_t linklocal_autocfg;
|
|
- uint8_t router_autocfg;
|
|
-
|
|
- uint8_t vlan_state;
|
|
- uint8_t vlan_priority;
|
|
- uint16_t vlan_id;
|
|
-
|
|
-#define MIN_MTU_SUPPORT 46
|
|
-#define MAX_MTU_SUPPORT 9000
|
|
- uint16_t mtu;
|
|
-};
|
|
-
|
|
-#define PEERUSER_MAX 64
|
|
-
|
|
-/******************************************************************************
|
|
- * Globals
|
|
- *****************************************************************************/
|
|
-static struct iscsid_options iscsid_opts = {
|
|
- .fd = INVALID_FD,
|
|
- .thread = INVALID_THREAD,
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * iscsid Functions
|
|
- *****************************************************************************/
|
|
-
|
|
-static void *enable_nic_thread(void *data)
|
|
-{
|
|
- nic_t *nic = (nic_t *) data;
|
|
-
|
|
- prepare_nic_thread(nic);
|
|
- LOG_INFO(PFX "%s: started NIC enable thread state: 0x%x",
|
|
- nic->log_name, nic->state)
|
|
-
|
|
- /* Enable the NIC */
|
|
- nic_enable(nic);
|
|
-
|
|
- nic->enable_thread = INVALID_THREAD;
|
|
-
|
|
- pthread_exit(NULL);
|
|
-}
|
|
-
|
|
-static int decode_cidr(char *in_ipaddr_str, struct iface_rec_decode *ird)
|
|
-{
|
|
- int rc = 0, i;
|
|
- char *tmp, *tok;
|
|
- char ipaddr_str[NI_MAXHOST];
|
|
- char str[INET6_ADDRSTRLEN];
|
|
- unsigned long keepbits = 0;
|
|
- struct in_addr ia;
|
|
- struct in6_addr ia6;
|
|
-
|
|
- strlcpy(ipaddr_str, in_ipaddr_str, NI_MAXHOST);
|
|
-
|
|
- /* Find the CIDR if any */
|
|
- tmp = strchr(ipaddr_str, '/');
|
|
- if (tmp) {
|
|
- /* CIDR found, now decode, tmpbuf = ip, tmp = netmask */
|
|
- tmp = ipaddr_str;
|
|
- tok = strsep(&tmp, "/");
|
|
- LOG_INFO(PFX "in cidr: bitmask '%s' ip '%s'", tmp, tok);
|
|
- keepbits = strtoull(tmp, NULL, 10);
|
|
- }
|
|
-
|
|
- /* Determine if the IP address passed from the iface file is
|
|
- * an IPv4 or IPv6 address */
|
|
- rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv6_addr);
|
|
- if (rc == 0) {
|
|
- /* Test to determine if the addres is an IPv6 address */
|
|
- rc = inet_pton(AF_INET6, ipaddr_str, &ird->ipv6_addr);
|
|
- if (rc == 0) {
|
|
- LOG_ERR(PFX "Could not parse IP address: '%s'",
|
|
- ipaddr_str);
|
|
- goto out;
|
|
- }
|
|
- ird->ip_type = AF_INET6;
|
|
- if (keepbits > 128) {
|
|
- LOG_ERR(PFX "CIDR netmask > 128 for IPv6: %d(%s)",
|
|
- keepbits, tmp);
|
|
- goto out;
|
|
- }
|
|
- if (!keepbits) {
|
|
- /* Default prefix mask to 64 */
|
|
- memcpy(&ird->ipv6_subnet_mask.s6_addr, all_zeroes_addr6,
|
|
- sizeof(struct in6_addr));
|
|
- ird->prefix_len = 64;
|
|
- for (i = 0; i < 2; i++)
|
|
- ird->ipv6_subnet_mask.s6_addr32[i] = 0xffffffff;
|
|
- goto out;
|
|
- }
|
|
- ird->prefix_len = keepbits;
|
|
- memcpy(&ia6.s6_addr, all_zeroes_addr6, sizeof(struct in6_addr));
|
|
- for (i = 0; i < 4; i++) {
|
|
- if (keepbits < 32) {
|
|
- ia6.s6_addr32[i] = keepbits > 0 ?
|
|
- 0x00 - (1 << (32 - keepbits)) : 0;
|
|
- ia6.s6_addr32[i] = htonl(ia6.s6_addr32[i]);
|
|
- break;
|
|
- } else
|
|
- ia6.s6_addr32[i] = 0xFFFFFFFF;
|
|
- keepbits -= 32;
|
|
- }
|
|
- ird->ipv6_subnet_mask = ia6;
|
|
- if (inet_ntop(AF_INET6, &ia6, str, sizeof(str)))
|
|
- LOG_INFO(PFX "Using netmask: %s", str);
|
|
- } else {
|
|
- ird->ip_type = AF_INET;
|
|
- rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv4_addr);
|
|
-
|
|
- if (keepbits > 32) {
|
|
- LOG_ERR(PFX "CIDR netmask > 32 for IPv4: %d(%s)",
|
|
- keepbits, tmp);
|
|
- goto out;
|
|
- }
|
|
- ia.s_addr = keepbits > 0 ? 0x00 - (1 << (32 - keepbits)) : 0;
|
|
- ird->ipv4_subnet_mask.s_addr = htonl(ia.s_addr);
|
|
- LOG_INFO(PFX "Using netmask: %s",
|
|
- inet_ntoa(ird->ipv4_subnet_mask));
|
|
- }
|
|
-out:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int decode_iface(struct iface_rec_decode *ird, struct iface_rec *rec)
|
|
-{
|
|
- int rc = 0;
|
|
- char ipaddr_str[NI_MAXHOST];
|
|
-
|
|
- /* Decodes the rec contents */
|
|
- memset(ird, 0, sizeof(struct iface_rec_decode));
|
|
-
|
|
- /* Detect for CIDR notation and strip off the netmask if present */
|
|
- rc = decode_cidr(rec->ipaddress, ird);
|
|
- if (rc && !ird->ip_type) {
|
|
- LOG_ERR(PFX "cidr decode err: rc=%d, ip_type=%d",
|
|
- rc, ird->ip_type);
|
|
- /* Can't decode address, just exit */
|
|
- return rc;
|
|
- }
|
|
- rc = 0;
|
|
- ird->iface_num = rec->iface_num;
|
|
- ird->vlan_id = rec->vlan_id;
|
|
- if (rec->iface_num != IFACE_NUM_INVALID) {
|
|
- ird->mtu = rec->mtu;
|
|
- if (rec->vlan_id && strcmp(rec->vlan_state, "disable")) {
|
|
- ird->vlan_state = 1;
|
|
- ird->vlan_priority = rec->vlan_priority;
|
|
- ird->vlan_id = rec->vlan_id;
|
|
- }
|
|
- if (ird->ip_type == AF_INET6) {
|
|
- if (!strcmp(rec->ipv6_autocfg, "dhcpv6"))
|
|
- ird->ipv6_autocfg = IPV6_AUTOCFG_DHCPV6;
|
|
- else if (!strcmp(rec->ipv6_autocfg, "nd"))
|
|
- ird->ipv6_autocfg = IPV6_AUTOCFG_ND;
|
|
- else
|
|
- ird->ipv6_autocfg = IPV6_AUTOCFG_NOTSPEC;
|
|
-
|
|
- if (!strcmp(rec->linklocal_autocfg, "auto"))
|
|
- ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
|
|
- else if (!strcmp(rec->linklocal_autocfg, "off"))
|
|
- ird->linklocal_autocfg = IPV6_LL_AUTOCFG_OFF;
|
|
- else /* default */
|
|
- ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
|
|
-
|
|
- if (!strcmp(rec->router_autocfg, "auto"))
|
|
- ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
|
|
- else if (!strcmp(rec->router_autocfg, "off"))
|
|
- ird->router_autocfg = IPV6_RTR_AUTOCFG_OFF;
|
|
- else /* default */
|
|
- ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
|
|
-
|
|
- /* Decode the addresses based on the control flags */
|
|
- /* For DHCP, ignore the IPv6 addr in the iface */
|
|
- if (ird->ipv6_autocfg == IPV6_AUTOCFG_DHCPV6)
|
|
- memcpy(&ird->ipv6_addr, all_zeroes_addr6,
|
|
- sizeof(struct in6_addr));
|
|
- /* Subnet mask priority: CIDR, then rec */
|
|
- if (!ird->ipv6_subnet_mask.s6_addr)
|
|
- inet_pton(AF_INET6, rec->subnet_mask,
|
|
- &ird->ipv6_subnet_mask);
|
|
-
|
|
- /* For LL on, ignore the IPv6 addr in the iface */
|
|
- if (ird->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF) {
|
|
- strlcpy(ipaddr_str, rec->ipv6_linklocal,
|
|
- NI_MAXHOST);
|
|
- inet_pton(AF_INET6, ipaddr_str,
|
|
- &ird->ipv6_linklocal);
|
|
- }
|
|
-
|
|
- /* For RTR on, ignore the IPv6 addr in the iface */
|
|
- if (ird->router_autocfg == IPV6_RTR_AUTOCFG_OFF) {
|
|
- strlcpy(ipaddr_str, rec->ipv6_router,
|
|
- NI_MAXHOST);
|
|
- inet_pton(AF_INET6, ipaddr_str,
|
|
- &ird->ipv6_router);
|
|
- }
|
|
- } else {
|
|
- /* Subnet mask priority: CIDR, rec, default */
|
|
- if (!ird->ipv4_subnet_mask.s_addr)
|
|
- inet_pton(AF_INET, rec->subnet_mask,
|
|
- &ird->ipv4_subnet_mask);
|
|
- if (!ird->ipv4_subnet_mask.s_addr)
|
|
- ird->ipv4_subnet_mask.s_addr =
|
|
- calculate_default_netmask(
|
|
- ird->ipv4_addr.s_addr);
|
|
-
|
|
- strlcpy(ipaddr_str, rec->gateway, NI_MAXHOST);
|
|
- inet_pton(AF_INET, ipaddr_str, &ird->ipv4_gateway);
|
|
- }
|
|
- } else {
|
|
- ird->ipv6_autocfg = IPV6_AUTOCFG_NOTUSED;
|
|
- ird->linklocal_autocfg = IPV6_LL_AUTOCFG_NOTUSED;
|
|
- ird->router_autocfg = IPV6_RTR_AUTOCFG_NOTUSED;
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void *perform_ping(void *arg)
|
|
-{
|
|
- struct ping_conf *png_c = (struct ping_conf *)arg;
|
|
- nic_interface_t *nic_iface = png_c->nic_iface;
|
|
- nic_t *nic = nic_iface->parent;
|
|
- iscsid_uip_broadcast_t *data;
|
|
- struct sockaddr_in *addr;
|
|
- struct sockaddr_in6 *addr6;
|
|
- uip_ip6addr_t dst_addr;
|
|
- int rc = 0;
|
|
- int datalen;
|
|
- struct timespec ts = {.tv_sec = 5,
|
|
- .tv_nsec = 0};
|
|
-
|
|
- data = (iscsid_uip_broadcast_t *)png_c->data;
|
|
- datalen = data->u.ping_rec.datalen;
|
|
- if ((datalen > STD_MTU_SIZE) || (datalen < 0)) {
|
|
- LOG_ERR(PFX "Ping datalen invalid: %d", datalen);
|
|
- rc = -EINVAL;
|
|
- goto ping_done;
|
|
- }
|
|
-
|
|
- memset(dst_addr, 0, sizeof(uip_ip6addr_t));
|
|
- if (nic_iface->protocol == AF_INET) {
|
|
- /* IPv4 */
|
|
- addr = (struct sockaddr_in *)&data->u.ping_rec.ipaddr;
|
|
- memcpy(dst_addr, &addr->sin_addr.s_addr, sizeof(uip_ip4addr_t));
|
|
- } else {
|
|
- /* IPv6 */
|
|
- addr6 = (struct sockaddr_in6 *)&data->u.ping_rec.ipaddr;
|
|
- memcpy(dst_addr, &addr6->sin6_addr.s6_addr,
|
|
- sizeof(uip_ip6addr_t));
|
|
- }
|
|
-
|
|
- /* Ensure that the NIC is RUNNING */
|
|
- if ((nic->state != NIC_RUNNING) || !(nic->flags & NIC_ENABLED)) {
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- rc = pthread_cond_timedwait(&nic->enable_done_cond,
|
|
- &nic->nic_mutex, &ts);
|
|
- if ((rc == 0) && (nic->state == NIC_RUNNING)) {
|
|
- LOG_DEBUG(PFX "%s: nic running", nic->log_name);
|
|
- } else if (rc) {
|
|
- LOG_DEBUG(PFX "%s: err %d", nic->log_name, rc);
|
|
- rc = -EAGAIN;
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- }
|
|
-
|
|
- if (rc || nic->state != NIC_RUNNING) {
|
|
- png_c->state = rc;
|
|
- goto ping_done;
|
|
- }
|
|
-
|
|
- ping_init(png_c, dst_addr, nic_iface->protocol, datalen);
|
|
-
|
|
- rc = do_ping_from_nic_iface(png_c);
|
|
- if (png_c->state == -1)
|
|
- png_c->state = rc;
|
|
-
|
|
-ping_done:
|
|
- LOG_INFO(PFX "ping thread end");
|
|
- nic->ping_thread = INVALID_THREAD;
|
|
- pthread_exit(NULL);
|
|
-}
|
|
-
|
|
-static int parse_iface(void *arg, int do_ping)
|
|
-{
|
|
- int rc, i;
|
|
- nic_t *nic = NULL;
|
|
- nic_interface_t *nic_iface;
|
|
- char *transport_name;
|
|
- size_t transport_name_size;
|
|
- nic_lib_handle_t *handle;
|
|
- iscsid_uip_broadcast_t *data;
|
|
- char ipv6_buf_str[INET6_ADDRSTRLEN];
|
|
- int request_type = 0;
|
|
- struct iface_rec *rec;
|
|
- struct iface_rec_decode ird;
|
|
- struct in_addr src_match, dst_match;
|
|
- pthread_attr_t attr;
|
|
- struct ping_conf *png_c;
|
|
-
|
|
- data = (iscsid_uip_broadcast_t *) arg;
|
|
- if (do_ping)
|
|
- rec = &data->u.ping_rec.ifrec;
|
|
- else
|
|
- rec = &data->u.iface_rec.rec;
|
|
-
|
|
- LOG_INFO(PFX "Received request for '%s' to set IP address: '%s' "
|
|
- "VLAN: '%d'",
|
|
- rec->netdev,
|
|
- rec->ipaddress,
|
|
- rec->vlan_id);
|
|
-
|
|
- rc = decode_iface(&ird, rec);
|
|
- if (ird.vlan_id && valid_vlan(ird.vlan_id) == 0) {
|
|
- LOG_ERR(PFX "Invalid VLAN tag: %d", ird.vlan_id);
|
|
- rc = -EIO;
|
|
- goto early_exit;
|
|
- }
|
|
- if (rc && !ird.ip_type) {
|
|
- LOG_ERR(PFX "iface err: rc=%d, ip_type=%d", rc, ird.ip_type);
|
|
- goto early_exit;
|
|
- }
|
|
-
|
|
- for (i = 0; i < 10; i++) {
|
|
- struct timespec sleep_req, sleep_rem;
|
|
-
|
|
- if (pthread_mutex_trylock(&nic_list_mutex) == 0)
|
|
- break;
|
|
-
|
|
- sleep_req.tv_sec = 0;
|
|
- sleep_req.tv_nsec = 100000;
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
-
|
|
- if (i >= 10) {
|
|
- LOG_WARN(PFX "Could not acquire nic_list_mutex lock");
|
|
- rc = -EIO;
|
|
- goto early_exit;
|
|
- }
|
|
-
|
|
- /* nic_list_mutex locked */
|
|
-
|
|
- /* Check if we can find the NIC device using the netdev
|
|
- * name */
|
|
- rc = from_netdev_name_find_nic(rec->netdev, &nic);
|
|
-
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "Couldn't find NIC: %s, creating an instance",
|
|
- rec->netdev);
|
|
-
|
|
- nic = nic_init();
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "Couldn't allocate space for NIC %s",
|
|
- rec->netdev);
|
|
-
|
|
- rc = -ENOMEM;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- strncpy(nic->eth_device_name,
|
|
- rec->netdev,
|
|
- sizeof(nic->eth_device_name));
|
|
- nic->config_device_name = nic->eth_device_name;
|
|
- nic->log_name = nic->eth_device_name;
|
|
-
|
|
- if (nic_fill_name(nic) != 0) {
|
|
- free(nic);
|
|
- rc = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- nic_add(nic);
|
|
- } else {
|
|
- LOG_INFO(PFX " %s, using existing NIC",
|
|
- rec->netdev);
|
|
- }
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (nic->flags & NIC_GOING_DOWN) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- rc = -EIO;
|
|
- LOG_INFO(PFX "nic->flags GOING DOWN");
|
|
- goto done;
|
|
- }
|
|
-
|
|
- /* If we retry too many times allow iscsid to timeout */
|
|
- if (nic->pending_count > 1000) {
|
|
- nic->pending_count = 0;
|
|
- nic->flags &= ~NIC_ENABLED_PENDING;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- LOG_WARN(PFX "%s: pending count exceeded 1000", nic->log_name);
|
|
-
|
|
- rc = 0;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if (nic->flags & NIC_ENABLED_PENDING) {
|
|
- struct timespec sleep_req, sleep_rem;
|
|
-
|
|
- nic->pending_count++;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- sleep_req.tv_sec = 2;
|
|
- sleep_req.tv_nsec = 0;
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (!(nic->flags & NIC_ENABLED) ||
|
|
- nic->state != NIC_RUNNING) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_INFO(PFX "%s: enabled pending", nic->log_name);
|
|
- rc = -EAGAIN;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- prepare_library(nic);
|
|
-
|
|
- /* Sanity Check to ensure the transport names are the same */
|
|
- handle = nic->nic_library;
|
|
- if (handle != NULL) {
|
|
- (*handle->ops->lib_ops.get_transport_name) (&transport_name,
|
|
- &transport_name_size);
|
|
-
|
|
- if (strncmp(transport_name,
|
|
- rec->transport_name,
|
|
- transport_name_size) != 0) {
|
|
- LOG_ERR(PFX "%s Transport name is not equal "
|
|
- "expected: %s got: %s",
|
|
- nic->log_name,
|
|
- rec->transport_name,
|
|
- transport_name);
|
|
- }
|
|
- } else {
|
|
- LOG_ERR(PFX "%s Couldn't find nic library ", nic->log_name);
|
|
- rc = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s library set using transport_name %s",
|
|
- nic->log_name, transport_name);
|
|
-
|
|
- /* Determine how to configure the IP address */
|
|
- if (ird.ip_type == AF_INET) {
|
|
- if (memcmp(&ird.ipv4_addr,
|
|
- all_zeroes_addr4, sizeof(uip_ip4addr_t)) == 0) {
|
|
- LOG_INFO(PFX "%s: requesting configuration using DHCP",
|
|
- nic->log_name);
|
|
- request_type = IPV4_CONFIG_DHCP;
|
|
- } else {
|
|
- LOG_INFO(PFX "%s: requesting configuration using "
|
|
- "static IP address", nic->log_name);
|
|
- request_type = IPV4_CONFIG_STATIC;
|
|
- }
|
|
- } else if (ird.ip_type == AF_INET6) {
|
|
- /* For the new 872_22, check ipv6_autocfg for DHCPv6 instead */
|
|
- switch (ird.ipv6_autocfg) {
|
|
- case IPV6_AUTOCFG_DHCPV6:
|
|
- request_type = IPV6_CONFIG_DHCP;
|
|
- break;
|
|
- case IPV6_AUTOCFG_ND:
|
|
- request_type = IPV6_CONFIG_STATIC;
|
|
- break;
|
|
- case IPV6_AUTOCFG_NOTSPEC:
|
|
- /* Treat NOTSPEC the same as NOTUSED for now */
|
|
- case IPV6_AUTOCFG_NOTUSED:
|
|
- /* For 871 */
|
|
- default:
|
|
- /* Just the IP address to determine */
|
|
- if (memcmp(&ird.ipv6_addr,
|
|
- all_zeroes_addr6,
|
|
- sizeof(struct in6_addr)) == 0)
|
|
- request_type = IPV6_CONFIG_DHCP;
|
|
- else
|
|
- request_type = IPV6_CONFIG_STATIC;
|
|
- }
|
|
- } else {
|
|
- LOG_ERR(PFX "%s: unknown ip_type to configure: 0x%x",
|
|
- nic->log_name, ird.ip_type);
|
|
-
|
|
- rc = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic_iface = nic_find_nic_iface(nic, ird.ip_type, ird.vlan_id,
|
|
- ird.iface_num, request_type);
|
|
-
|
|
- if (nic->flags & NIC_PATHREQ_WAIT) {
|
|
- if (!nic_iface ||
|
|
- !(nic_iface->flags & NIC_IFACE_PATHREQ_WAIT)) {
|
|
- int pathreq_wait;
|
|
-
|
|
- if (nic_iface &&
|
|
- (nic_iface->flags & NIC_IFACE_PATHREQ_WAIT2))
|
|
- pathreq_wait = 12;
|
|
- else
|
|
- pathreq_wait = 10;
|
|
-
|
|
- if (nic->pathreq_pending_count < pathreq_wait) {
|
|
- struct timespec sleep_req, sleep_rem;
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- nic->pathreq_pending_count++;
|
|
- sleep_req.tv_sec = 0;
|
|
- sleep_req.tv_nsec = 100000;
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- /* Somebody else is waiting for PATH_REQ */
|
|
- LOG_INFO(PFX "%s: path req pending cnt=%d",
|
|
- nic->log_name,
|
|
- nic->pathreq_pending_count);
|
|
- rc = -EAGAIN;
|
|
- goto done;
|
|
- } else {
|
|
- nic->pathreq_pending_count = 0;
|
|
- LOG_DEBUG(PFX "%s: path req pending cnt "
|
|
- "exceeded!", nic->log_name);
|
|
- /* Allow to fall thru */
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- nic->flags |= NIC_PATHREQ_WAIT;
|
|
-
|
|
- /* Create the network interface if it doesn't exist */
|
|
- if (nic_iface == NULL) {
|
|
- LOG_DEBUG(PFX "%s couldn't find interface with "
|
|
- "ip_type: 0x%x creating it",
|
|
- nic->log_name, ird.ip_type);
|
|
- nic_iface = nic_iface_init();
|
|
-
|
|
- if (nic_iface == NULL) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_ERR(PFX "%s Couldn't allocate "
|
|
- "interface with ip_type: 0x%x",
|
|
- nic->log_name, ird.ip_type);
|
|
- goto done;
|
|
- }
|
|
- nic_iface->protocol = ird.ip_type;
|
|
- nic_iface->vlan_id = ird.vlan_id;
|
|
- nic_iface->vlan_priority = ird.vlan_priority;
|
|
- if (ird.mtu >= MIN_MTU_SUPPORT && ird.mtu <= MAX_MTU_SUPPORT)
|
|
- nic_iface->mtu = ird.mtu;
|
|
- nic_iface->iface_num = ird.iface_num;
|
|
- nic_iface->request_type = request_type;
|
|
- nic_add_nic_iface(nic, nic_iface);
|
|
-
|
|
- persist_all_nic_iface(nic);
|
|
-
|
|
- LOG_INFO(PFX "%s: created network interface",
|
|
- nic->log_name);
|
|
- } else {
|
|
- /* Move the nic_iface to the front */
|
|
- set_nic_iface(nic, nic_iface);
|
|
- LOG_INFO(PFX "%s: using existing network interface",
|
|
- nic->log_name);
|
|
- }
|
|
-
|
|
- nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT1;
|
|
- if (nic->nl_process_thread == INVALID_THREAD) {
|
|
- pthread_attr_init(&attr);
|
|
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
- rc = pthread_create(&nic->nl_process_thread, &attr,
|
|
- nl_process_handle_thread, nic);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not create NIC NL "
|
|
- "processing thread [%s]", nic->log_name,
|
|
- strerror(rc));
|
|
- nic->nl_process_thread = INVALID_THREAD;
|
|
- /* Reset both WAIT flags */
|
|
- nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
|
|
- nic->flags &= ~NIC_PATHREQ_WAIT;
|
|
- }
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- if (nic_iface->ustack.ip_config == request_type) {
|
|
- /* Same request_type, check for STATIC address change */
|
|
- if (request_type == IPV4_CONFIG_STATIC) {
|
|
- if (memcmp(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
|
|
- sizeof(struct in_addr)))
|
|
- goto reacquire;
|
|
- } else if (request_type == IPV6_CONFIG_STATIC) {
|
|
- if (memcmp(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
|
|
- sizeof(struct in6_addr)))
|
|
- goto reacquire;
|
|
- else
|
|
- inet_ntop(AF_INET6, &ird.ipv6_addr,
|
|
- ipv6_buf_str,
|
|
- sizeof(ipv6_buf_str));
|
|
- }
|
|
- LOG_INFO(PFX "%s: IP configuration didn't change using 0x%x",
|
|
- nic->log_name, nic_iface->ustack.ip_config);
|
|
- /* No need to acquire the IP address */
|
|
- inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
|
|
- sizeof(ipv6_buf_str));
|
|
-
|
|
- goto enable_nic;
|
|
- }
|
|
-reacquire:
|
|
- /* Config needs to re-acquire for this nic_iface */
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- nic_iface->flags |= NIC_IFACE_ACQUIRE;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- /* Disable the nic loop from further processing, upon returned,
|
|
- the nic_iface should be cleared */
|
|
- nic_disable(nic, 0);
|
|
-
|
|
- /* Check to see if this is using DHCP or if this is
|
|
- * a static IPv4 address. This is done by checking
|
|
- * if the IP address is equal to 0.0.0.0. If it is
|
|
- * then the user has specified to use DHCP. If not
|
|
- * then the user has spcicied to use a static IP address
|
|
- * an the default netmask will be used */
|
|
- switch (request_type) {
|
|
- case IPV4_CONFIG_DHCP:
|
|
- memset(nic_iface->ustack.hostaddr, 0, sizeof(struct in_addr));
|
|
- LOG_INFO(PFX "%s: configuring using DHCP", nic->log_name);
|
|
- nic_iface->ustack.ip_config = IPV4_CONFIG_DHCP;
|
|
- break;
|
|
-
|
|
- case IPV4_CONFIG_STATIC:
|
|
- memcpy(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
|
|
- sizeof(struct in_addr));
|
|
- LOG_INFO(PFX "%s: configuring using static IP "
|
|
- "IPv4 address :%s ",
|
|
- nic->log_name, inet_ntoa(ird.ipv4_addr));
|
|
-
|
|
- if (ird.ipv4_subnet_mask.s_addr)
|
|
- memcpy(nic_iface->ustack.netmask,
|
|
- &ird.ipv4_subnet_mask, sizeof(struct in_addr));
|
|
- LOG_INFO(PFX " netmask: %s", inet_ntoa(ird.ipv4_subnet_mask));
|
|
-
|
|
- /* Default route */
|
|
- if (ird.ipv4_gateway.s_addr) {
|
|
- /* Check for validity */
|
|
- src_match.s_addr = ird.ipv4_addr.s_addr &
|
|
- ird.ipv4_subnet_mask.s_addr;
|
|
- dst_match.s_addr = ird.ipv4_gateway.s_addr &
|
|
- ird.ipv4_subnet_mask.s_addr;
|
|
- if (src_match.s_addr == dst_match.s_addr)
|
|
- memcpy(nic_iface->ustack.default_route_addr,
|
|
- &ird.ipv4_gateway,
|
|
- sizeof(struct in_addr));
|
|
- }
|
|
- nic_iface->ustack.ip_config = IPV4_CONFIG_STATIC;
|
|
- break;
|
|
-
|
|
- case IPV6_CONFIG_DHCP:
|
|
- memset(nic_iface->ustack.hostaddr6, 0,
|
|
- sizeof(struct in6_addr));
|
|
- nic_iface->ustack.prefix_len = ird.prefix_len;
|
|
- nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
|
|
- nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
|
|
- nic_iface->ustack.router_autocfg = ird.router_autocfg;
|
|
-
|
|
- if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
|
|
- sizeof(struct in6_addr)))
|
|
- memcpy(nic_iface->ustack.netmask6,
|
|
- &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
|
|
- if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
|
|
- memcpy(nic_iface->ustack.linklocal6,
|
|
- &ird.ipv6_linklocal, sizeof(struct in6_addr));
|
|
- if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
|
|
- memcpy(nic_iface->ustack.default_route_addr6,
|
|
- &ird.ipv6_router, sizeof(struct in6_addr));
|
|
- inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
|
|
- sizeof(ipv6_buf_str));
|
|
- LOG_INFO(PFX "%s: configuring using DHCPv6",
|
|
- nic->log_name);
|
|
- nic_iface->ustack.ip_config = IPV6_CONFIG_DHCP;
|
|
- break;
|
|
-
|
|
- case IPV6_CONFIG_STATIC:
|
|
- memcpy(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
|
|
- sizeof(struct in6_addr));
|
|
- nic_iface->ustack.prefix_len = ird.prefix_len;
|
|
- nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
|
|
- nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
|
|
- nic_iface->ustack.router_autocfg = ird.router_autocfg;
|
|
-
|
|
- if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
|
|
- sizeof(struct in6_addr)))
|
|
- memcpy(nic_iface->ustack.netmask6,
|
|
- &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
|
|
- if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
|
|
- memcpy(nic_iface->ustack.linklocal6,
|
|
- &ird.ipv6_linklocal, sizeof(struct in6_addr));
|
|
- if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
|
|
- memcpy(nic_iface->ustack.default_route_addr6,
|
|
- &ird.ipv6_router, sizeof(struct in6_addr));
|
|
-
|
|
- inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
|
|
- sizeof(ipv6_buf_str));
|
|
- LOG_INFO(PFX "%s: configuring using static IP "
|
|
- "IPv6 address: '%s'", nic->log_name, ipv6_buf_str);
|
|
-
|
|
- nic_iface->ustack.ip_config = IPV6_CONFIG_STATIC;
|
|
- break;
|
|
-
|
|
- default:
|
|
- LOG_INFO(PFX "%s: Unknown request type: 0x%x",
|
|
- nic->log_name, request_type);
|
|
-
|
|
- }
|
|
-
|
|
-enable_nic:
|
|
- switch (nic->state) {
|
|
- case NIC_STOPPED:
|
|
- /* This thread will be thrown away when completed */
|
|
- if (nic->enable_thread != INVALID_THREAD) {
|
|
- rc = pthread_cancel(nic->enable_thread);
|
|
- if (rc != 0) {
|
|
- LOG_INFO(PFX "%s: failed to cancel enable NIC "
|
|
- "thread\n", nic->log_name);
|
|
- goto eagain;
|
|
- }
|
|
- }
|
|
- pthread_attr_init(&attr);
|
|
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
- rc = pthread_create(&nic->enable_thread, &attr,
|
|
- enable_nic_thread, (void *)nic);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: failed starting enable NIC thread\n",
|
|
- nic->log_name);
|
|
-eagain:
|
|
- rc = -EAGAIN;
|
|
- break;
|
|
-
|
|
- case NIC_RUNNING:
|
|
- LOG_INFO(PFX "%s: NIC already enabled "
|
|
- "flags: 0x%x state: 0x%x\n",
|
|
- nic->log_name, nic->flags, nic->state);
|
|
- rc = 0;
|
|
- break;
|
|
- default:
|
|
- LOG_INFO(PFX "%s: NIC enable still in progress "
|
|
- "flags: 0x%x state: 0x%x\n",
|
|
- nic->log_name, nic->flags, nic->state);
|
|
- rc = -EAGAIN;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "ISCSID_UIP_IPC_GET_IFACE: command: %x "
|
|
- "name: %s, netdev: %s ipaddr: %s vlan: %d transport_name:%s",
|
|
- data->header.command, rec->name, rec->netdev,
|
|
- (ird.ip_type == AF_INET) ? inet_ntoa(ird.ipv4_addr) :
|
|
- ipv6_buf_str,
|
|
- ird.vlan_id, rec->transport_name);
|
|
-
|
|
- if (do_ping) {
|
|
- if (nic->ping_thread != INVALID_THREAD) {
|
|
- rc = pthread_cancel(nic->ping_thread);
|
|
- if (rc != 0) {
|
|
- LOG_INFO(PFX "%s: failed to cancel ping thread",
|
|
- nic->log_name);
|
|
- rc = -EAGAIN;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- png_c = malloc(sizeof(struct ping_conf));
|
|
- if (!png_c) {
|
|
- LOG_ERR(PFX "Memory alloc failed for ping conf");
|
|
- rc = -ENOMEM;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- memset(png_c, 0, sizeof(struct ping_conf));
|
|
- png_c->nic_iface = nic_iface;
|
|
- png_c->data = arg;
|
|
- nic_iface->ustack.ping_conf = png_c;
|
|
-
|
|
- /* Spawn a thread to perform ping operation.
|
|
- * This thread will exit when done.
|
|
- */
|
|
- rc = pthread_create(&nic->ping_thread, NULL,
|
|
- perform_ping, (void *)png_c);
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s: failed starting ping thread\n",
|
|
- nic->log_name);
|
|
- } else {
|
|
- pthread_join(nic->ping_thread, NULL);
|
|
- rc = png_c->state;
|
|
- if (rc == -EAGAIN)
|
|
- png_c->state = 0;
|
|
- }
|
|
- free(png_c);
|
|
- nic_iface->ustack.ping_conf = NULL;
|
|
- }
|
|
-
|
|
-done:
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
-early_exit:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * process_iscsid_broadcast() - This function is used to process the
|
|
- * broadcast messages from iscsid
|
|
- *
|
|
- * s2 is an open file descriptor, which
|
|
- * must not be left open upon return
|
|
- */
|
|
-int process_iscsid_broadcast(int s2)
|
|
-{
|
|
- int rc = 0;
|
|
- iscsid_uip_broadcast_t *data;
|
|
- iscsid_uip_rsp_t rsp;
|
|
- FILE *fd;
|
|
- size_t size;
|
|
- iscsid_uip_cmd_e cmd;
|
|
- uint32_t payload_len;
|
|
-
|
|
- fd = fdopen(s2, "r+");
|
|
- if (fd == NULL) {
|
|
- LOG_ERR(PFX "Couldn't open file descriptor: %d(%s)",
|
|
- errno, strerror(errno));
|
|
- close(s2);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- /* This will be freed by parse_iface_thread() */
|
|
- data = (iscsid_uip_broadcast_t *) calloc(1, sizeof(*data));
|
|
- if (data == NULL) {
|
|
- LOG_ERR(PFX "Couldn't allocate memory for iface data");
|
|
- rc = -ENOMEM;
|
|
- goto error;
|
|
- }
|
|
- memset(data, 0, sizeof(*data));
|
|
-
|
|
- size = fread(data, sizeof(iscsid_uip_broadcast_header_t), 1, fd);
|
|
- if (!size) {
|
|
- LOG_ERR(PFX "Could not read request: %d(%s)",
|
|
- errno, strerror(errno));
|
|
- rc = ferror(fd);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- cmd = data->header.command;
|
|
- payload_len = data->header.payload_len;
|
|
- if (payload_len > sizeof(data->u)) {
|
|
- LOG_ERR(PFX "Data payload length too large (%d). Corrupt payload?",
|
|
- payload_len);
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "recv iscsid request: cmd: %d, payload_len: %d",
|
|
- cmd, payload_len);
|
|
-
|
|
- memset(&rsp, 0, sizeof(rsp));
|
|
-
|
|
- switch (cmd) {
|
|
- case ISCSID_UIP_IPC_GET_IFACE:
|
|
- size = fread(&data->u.iface_rec, payload_len, 1, fd);
|
|
- if (!size) {
|
|
- LOG_ERR(PFX "Could not read data: %d(%s)",
|
|
- errno, strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = parse_iface(data, 0);
|
|
- switch (rc) {
|
|
- case 0:
|
|
- rsp.command = cmd;
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_DEVICE_UP;
|
|
- break;
|
|
- case -EAGAIN:
|
|
- rsp.command = cmd;
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_DEVICE_INITIALIZING;
|
|
- break;
|
|
- default:
|
|
- rsp.command = cmd;
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_ERR;
|
|
- }
|
|
-
|
|
- break;
|
|
- case ISCSID_UIP_IPC_PING:
|
|
- size = fread(&data->u.ping_rec, payload_len, 1, fd);
|
|
- if (!size) {
|
|
- LOG_ERR(PFX "Could not read data: %d(%s)",
|
|
- errno, strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = parse_iface(data, 1);
|
|
- rsp.command = cmd;
|
|
- rsp.ping_sc = rc;
|
|
-
|
|
- switch (rc) {
|
|
- case 0:
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_DEVICE_UP;
|
|
- break;
|
|
- case -EAGAIN:
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_DEVICE_INITIALIZING;
|
|
- break;
|
|
- default:
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_ERR;
|
|
- }
|
|
-
|
|
- break;
|
|
- default:
|
|
- LOG_WARN(PFX "Unknown iscsid broadcast command: %x",
|
|
- data->header.command);
|
|
-
|
|
- /* Send a response back to iscsid to tell it the
|
|
- operation succeeded */
|
|
- rsp.command = cmd;
|
|
- rsp.err = ISCSID_UIP_MGMT_IPC_OK;
|
|
- break;
|
|
- }
|
|
-
|
|
- size = fwrite(&rsp, sizeof(rsp), 1, fd);
|
|
- if (size == -1) {
|
|
- LOG_ERR(PFX "Could not send response: %d(%s)",
|
|
- errno, strerror(errno));
|
|
- rc = ferror(fd);
|
|
- }
|
|
-
|
|
-error:
|
|
- if (data)
|
|
- free(data);
|
|
- fclose(fd);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void iscsid_loop_close(void *arg)
|
|
-{
|
|
- close(iscsid_opts.fd);
|
|
-
|
|
- LOG_INFO(PFX "iSCSI daemon socket closed");
|
|
-}
|
|
-
|
|
-/*
|
|
- * check that the peer user is privilidged
|
|
- *
|
|
- * return 1 if peer is ok else 0
|
|
- *
|
|
- * XXX: this function is copied from iscsid_ipc.c and should be
|
|
- * moved into a common library
|
|
- */
|
|
-static int
|
|
-mgmt_peeruser(int sock, char *user)
|
|
-{
|
|
- struct ucred peercred;
|
|
- socklen_t so_len = sizeof(peercred);
|
|
- struct passwd *pass;
|
|
-
|
|
- errno = 0;
|
|
- if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred,
|
|
- &so_len) != 0 || so_len != sizeof(peercred)) {
|
|
- /* We didn't get a valid credentials struct. */
|
|
- LOG_ERR(PFX "peeruser_unux: error receiving credentials: %m");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- pass = getpwuid(peercred.uid);
|
|
- if (pass == NULL) {
|
|
- LOG_ERR(PFX "peeruser_unix: unknown local user with uid %d",
|
|
- (int) peercred.uid);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- strlcpy(user, pass->pw_name, PEERUSER_MAX);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-/**
|
|
- * iscsid_loop() - This is the function which will process the broadcast
|
|
- * messages from iscsid
|
|
- *
|
|
- */
|
|
-static void *iscsid_loop(void *arg)
|
|
-{
|
|
- int rc;
|
|
- sigset_t set;
|
|
- char user[PEERUSER_MAX];
|
|
-
|
|
- pthread_cleanup_push(iscsid_loop_close, arg);
|
|
-
|
|
- sigfillset(&set);
|
|
- rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX
|
|
- "Couldn't set signal mask for the iscisd listening "
|
|
- "thread");
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "Started iscsid listening thread");
|
|
-
|
|
- while (1) {
|
|
- struct sockaddr_un remote;
|
|
- socklen_t sock_len;
|
|
- int s2;
|
|
-
|
|
- LOG_DEBUG(PFX "Waiting for iscsid command");
|
|
-
|
|
- sock_len = sizeof(remote);
|
|
- s2 = accept(iscsid_opts.fd,
|
|
- (struct sockaddr *)&remote, &sock_len);
|
|
- if (s2 == -1) {
|
|
- if (errno == EAGAIN) {
|
|
- LOG_DEBUG("Got EAGAIN from accept");
|
|
- sleep(1);
|
|
- continue;
|
|
- } else if (errno == EINTR) {
|
|
- LOG_DEBUG("Got EINTR from accept");
|
|
- /* The program is terminating, time to exit */
|
|
- break;
|
|
- }
|
|
-
|
|
- LOG_ERR(PFX "Could not accept: %d(%s)",
|
|
- s2, strerror(errno));
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (!mgmt_peeruser(iscsid_opts.fd, user) || strncmp(user, "root", PEERUSER_MAX)) {
|
|
- close(s2);
|
|
- LOG_ERR(PFX "Access error: non-administrative connection rejected");
|
|
- break;
|
|
- }
|
|
-
|
|
- /* this closes the file descriptor s2 */
|
|
- process_iscsid_broadcast(s2);
|
|
- }
|
|
-
|
|
- pthread_cleanup_pop(0);
|
|
-
|
|
- LOG_ERR(PFX "exit iscsid listening thread");
|
|
-
|
|
- pthread_exit(NULL);
|
|
-}
|
|
-
|
|
-#define SD_SOCKET_FDS_START 3
|
|
-
|
|
-static int ipc_systemd(void)
|
|
-{
|
|
- char *env;
|
|
-
|
|
- env = getenv("LISTEN_PID");
|
|
-
|
|
- if (!env || (strtoul(env, NULL, 10) != getpid()))
|
|
- return -EINVAL;
|
|
-
|
|
- env = getenv("LISTEN_FDS");
|
|
-
|
|
- if (!env)
|
|
- return -EINVAL;
|
|
-
|
|
- if (strtoul(env, NULL, 10) != 1) {
|
|
- LOG_ERR("Did not receive exactly one IPC socket from systemd");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- return SD_SOCKET_FDS_START;
|
|
-}
|
|
-
|
|
-/******************************************************************************
|
|
- * Initialize/Cleanup routines
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * iscsid_init() - This function will setup the thread used to listen for
|
|
- * the iscsid broadcast messages
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int iscsid_init()
|
|
-{
|
|
- int rc, addr_len;
|
|
- struct sockaddr_un addr;
|
|
-
|
|
- iscsid_opts.fd = ipc_systemd();
|
|
- if (iscsid_opts.fd >= 0)
|
|
- return 0;
|
|
-
|
|
- iscsid_opts.fd = socket(AF_LOCAL, SOCK_STREAM, 0);
|
|
- if (iscsid_opts.fd < 0) {
|
|
- LOG_ERR(PFX "Can not create IPC socket");
|
|
- return iscsid_opts.fd;
|
|
- }
|
|
-
|
|
- addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(ISCSID_UIP_NAMESPACE) + 1;
|
|
-
|
|
- memset(&addr, 0, sizeof(addr));
|
|
- addr.sun_family = AF_LOCAL;
|
|
- memcpy((char *)&addr.sun_path + 1, ISCSID_UIP_NAMESPACE,
|
|
- strlen(ISCSID_UIP_NAMESPACE));
|
|
-
|
|
- rc = bind(iscsid_opts.fd, (struct sockaddr *)&addr, addr_len);
|
|
- if (rc < 0) {
|
|
- LOG_ERR(PFX "Can not bind IPC socket: %s", strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = listen(iscsid_opts.fd, 32);
|
|
- if (rc < 0) {
|
|
- LOG_ERR(PFX "Can not listen IPC socket: %s", strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-error:
|
|
- close(iscsid_opts.fd);
|
|
- iscsid_opts.fd = INVALID_FD;
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * iscsid_start() - This function will start the thread used to listen for
|
|
- * the iscsid broadcast messages
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int iscsid_start()
|
|
-{
|
|
- pthread_attr_t attr;
|
|
- int rc;
|
|
-
|
|
- pthread_attr_init(&attr);
|
|
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
- rc = pthread_create(&iscsid_opts.thread, &attr, iscsid_loop, NULL);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "Could not start iscsid listening thread rc=%d",
|
|
- rc);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- close(iscsid_opts.fd);
|
|
- iscsid_opts.fd = INVALID_FD;
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * iscsid_cleanup() - This is called when stoping the thread listening
|
|
- * for the iscsid broadcast messages
|
|
- */
|
|
-void iscsid_cleanup()
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if (iscsid_opts.fd != INVALID_FD &&
|
|
- iscsid_opts.thread != INVALID_THREAD) {
|
|
- rc = pthread_cancel(iscsid_opts.thread);
|
|
- if (rc != 0) {
|
|
- LOG_ERR("Could not cancel iscsid listening thread: %s",
|
|
- strerror(rc));
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "iscsid listening thread has shutdown");
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/iscsid_ipc.h b/iscsiuio/src/unix/iscsid_ipc.h
|
|
deleted file mode 100644
|
|
index 60bcd71..0000000
|
|
--- a/iscsiuio/src/unix/iscsid_ipc.h
|
|
+++ /dev/null
|
|
@@ -1,52 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * iscsid_ipc.h: Generic NIC management/utility functions
|
|
- *
|
|
- */
|
|
-#ifndef __ISCSID_IPC_H__
|
|
-#define __ISCSID_IPC_H__
|
|
-
|
|
-#include "uip.h"
|
|
-#include "mgmt_ipc.h"
|
|
-
|
|
-enum mgmt_ipc_err iscsid_connect(int *fd);
|
|
-int iscsid_get_ipaddr(int fd, uip_ip4addr_t *ipaddr);
|
|
-
|
|
-int iscsid_init();
|
|
-int iscsid_start();
|
|
-void iscsid_cleanup();
|
|
-
|
|
-#endif /* __ISCSID_IPC_H__ */
|
|
diff --git a/iscsiuio/src/unix/libs/Makefile.am b/iscsiuio/src/unix/libs/Makefile.am
|
|
deleted file mode 100644
|
|
index 737546b..0000000
|
|
--- a/iscsiuio/src/unix/libs/Makefile.am
|
|
+++ /dev/null
|
|
@@ -1,14 +0,0 @@
|
|
-AM_CFLAGS = -I${top_srcdir}/src/uip \
|
|
- -I${top_srcdir}/src/unix \
|
|
- -I${top_srcdir}/src/unix/libs \
|
|
- -I${top_srcdir}/src/apps/dhcpc \
|
|
- -I${top_srcdir}/../include \
|
|
- -I${top_srcdir}/../usr
|
|
-
|
|
-noinst_LIBRARIES = lib_iscsiuio_hw_cnic.a
|
|
-
|
|
-lib_iscsiuio_hw_cnic_a_SOURCES = ../build_date.c \
|
|
- cnic.c \
|
|
- bnx2.c \
|
|
- bnx2x.c \
|
|
- qedi.c
|
|
diff --git a/iscsiuio/src/unix/libs/bnx2.c b/iscsiuio/src/unix/libs/bnx2.c
|
|
deleted file mode 100644
|
|
index 1181cf4..0000000
|
|
--- a/iscsiuio/src/unix/libs/bnx2.c
|
|
+++ /dev/null
|
|
@@ -1,1165 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * bnx2.c - bnx2 user space driver
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <sys/mman.h>
|
|
-#include <sys/sysmacros.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/user.h>
|
|
-#include <fcntl.h>
|
|
-#include <unistd.h>
|
|
-
|
|
-#include "config.h"
|
|
-
|
|
-#include "build_date.h"
|
|
-#include "bnx2.h"
|
|
-#include "cnic.h"
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-
|
|
-#define PFX "bnx2 "
|
|
-
|
|
-/* Foward struct declarations */
|
|
-struct nic_ops bnx2_op;
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC Library Strings
|
|
- ******************************************************************************/
|
|
-static const char library_name[] = "bnx2";
|
|
-static const char library_version[] = PACKAGE_VERSION;
|
|
-static const char library_uio_name[] = "bnx2_cnic";
|
|
-
|
|
-/* The name that should be returned from /sys/class/uio/uio0/name */
|
|
-static const char cnic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
|
|
-static const char cnic_uio_sysfs_name[] = "bnx2_cnic";
|
|
-
|
|
-/*******************************************************************************
|
|
- * String constants used to display human readable adapter name
|
|
- ******************************************************************************/
|
|
-static const char hp_NC370T[] =
|
|
- "HP NC370T Multifunction Gigabit Server Adapter";
|
|
-static const char hp_NC370I[] =
|
|
- "HP NC370i Multifunction Gigabit Server Adapter";
|
|
-static const char brcm_5706S[] = "QLogic NetXtreme II BCM5706 1000Base-SX";
|
|
-static const char hp_NC370F[] =
|
|
- "HP NC370F Multifunction Gigabit Server Adapter";
|
|
-static const char brcm_5708C[] = "QLogic NetXtreme II BCM5708 1000Base-T";
|
|
-static const char brcm_5708S[] = "QLogic NetXtreme II BCM5708 1000Base-SX";
|
|
-static const char brcm_5709C[] = "QLogic NetXtreme II BCM5709 1000Base-T";
|
|
-static const char brcm_5709S[] = "QLogic NetXtreme II BCM5709 1000Base-SX";
|
|
-static const char brcm_5716C[] = "QLogic NetXtreme II BCM5716 1000Base-T";
|
|
-static const char brcm_5716S[] = "QLogic NetXtreme II BCM5716 1000Base-SX";
|
|
-
|
|
-/*******************************************************************************
|
|
- * PCI ID constants
|
|
- ******************************************************************************/
|
|
-#define PCI_VENDOR_ID_BROADCOM 0x14e4
|
|
-#define PCI_DEVICE_ID_NX2_5709 0x1639
|
|
-#define PCI_DEVICE_ID_NX2_5709S 0x163a
|
|
-#define PCI_DEVICE_ID_NX2_5706 0x164a
|
|
-#define PCI_DEVICE_ID_NX2_5708 0x164c
|
|
-#define PCI_DEVICE_ID_NX2_5706S 0x16aa
|
|
-#define PCI_DEVICE_ID_NX2_5708S 0x16ac
|
|
-
|
|
-#define PCI_VENDOR_ID_HP 0x103c
|
|
-
|
|
-#define PCI_ANY_ID (~0)
|
|
-
|
|
-/* This is the table used to match PCI vendor and device ID's to the
|
|
- * human readable string names of the devices */
|
|
-static const struct pci_device_id bnx2_pci_tbl[] = {
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
|
|
- PCI_VENDOR_ID_HP, 0x3101, hp_NC370T},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
|
|
- PCI_VENDOR_ID_HP, 0x3106, hp_NC370I},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5706S},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5708C},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
|
|
- PCI_VENDOR_ID_HP, 0x3102, hp_NC370F},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5706S},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5708S},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5709C},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5709S},
|
|
- {PCI_VENDOR_ID_BROADCOM, 0x163b,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5716C},
|
|
- {PCI_VENDOR_ID_BROADCOM, 0x163c,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_5716S},
|
|
-};
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2 Library Functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * bnx2_get_library_name() - Used to get the name of this NIC libary
|
|
- * @param name - This function will return the pointer to this NIC
|
|
- * library name
|
|
- * @param name_size
|
|
- */
|
|
-static void bnx2_get_library_name(char **name, size_t *name_size)
|
|
-{
|
|
- *name = (char *)library_name;
|
|
- *name_size = sizeof(library_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_library_version() - Used to get the version string of this
|
|
- * NIC libary
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library version string
|
|
- * @param version_size - This will be set with the version size
|
|
- */
|
|
-static void bnx2_get_library_version(char **version, size_t *version_size)
|
|
-{
|
|
- *version = (char *)library_version;
|
|
- *version_size = sizeof(library_version);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_build_date() - Used to get the build date string of this library
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library build date string
|
|
- * @param version_size - This will be set with the build date string size
|
|
- */
|
|
-static void bnx2_get_build_date(char **build, size_t *build_size)
|
|
-{
|
|
- *build = (char *)build_date;
|
|
- *build_size = sizeof(build_date);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_transport_name() - Used to get the transport name associated
|
|
- * with this this NIC libary
|
|
- * @param transport_name - This function will return the pointer to this NIC
|
|
- * library's associated transport string
|
|
- * @param transport_name_size - This will be set with the transport name size
|
|
- */
|
|
-static void bnx2_get_transport_name(char **transport_name,
|
|
- size_t *transport_name_size)
|
|
-{
|
|
- *transport_name = (char *)bnx2i_library_transport_name;
|
|
- *transport_name_size = bnx2i_library_transport_name_size;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_uio_name() - Used to get the uio name associated with this this
|
|
- * NIC libary
|
|
- * @param uio_name - This function will return the pointer to this NIC
|
|
- * library's associated uio string
|
|
- * @param transport_name_size - This will be set with the uio name size
|
|
- */
|
|
-static void bnx2_get_uio_name(char **uio_name, size_t *uio_name_size)
|
|
-{
|
|
- *uio_name = (char *)library_uio_name;
|
|
- *uio_name_size = sizeof(library_uio_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_pci_table() - Used to get the PCI table for this NIC libary
|
|
- * to determine which NIC's based off of PCI ID's
|
|
- * are supported
|
|
- * @param table - This function will return the pointer to the PCI table
|
|
- * @param entries - This function will return the number of entries in the NIC
|
|
- * library's PCI table
|
|
- */
|
|
-static void bnx2_get_pci_table(struct pci_device_id **table, uint32_t *entries)
|
|
-{
|
|
- *table = (struct pci_device_id *)bnx2_pci_tbl;
|
|
- *entries = (uint32_t) (sizeof(bnx2_pci_tbl) / sizeof(bnx2_pci_tbl[0]));
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_ops() - Used to get the NIC library op table
|
|
- * @param op - The op table of this NIC library
|
|
- */
|
|
-struct nic_ops *bnx2_get_ops()
|
|
-{
|
|
- return &bnx2_op;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2 Utility Functions
|
|
- ******************************************************************************/
|
|
-/*******************************************************************************
|
|
- * Utility Functions Used to read register from the bnx2 device
|
|
- ******************************************************************************/
|
|
-static void bnx2_wr32(bnx2_t *bp, __u32 off, __u32 val)
|
|
-{
|
|
- *((volatile __u32 *)(bp->reg + off)) = val;
|
|
-}
|
|
-
|
|
-static void bnx2_wr16(bnx2_t *bp, __u32 off, __u16 val)
|
|
-{
|
|
- *((volatile __u16 *)(bp->reg + off)) = val;
|
|
-}
|
|
-
|
|
-static __u32 bnx2_rd32(bnx2_t *bp, __u32 off)
|
|
-{
|
|
- return *((volatile __u32 *)(bp->reg + off));
|
|
-}
|
|
-
|
|
-static int bnx2_reg_sync(bnx2_t *bp, __u32 off, __u16 length)
|
|
-{
|
|
- return msync(bp->reg + off, length, MS_SYNC);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_chip_id() - Used to retrive the chip ID from the nic
|
|
- * @param dev - Device used to determin NIC type
|
|
- * @return Chip ID read from the MISC ID register
|
|
- */
|
|
-static int bnx2_get_chip_id(bnx2_t *bp)
|
|
-{
|
|
- return bnx2_rd32(bp, BNX2_MISC_ID);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_uio_verify()
|
|
- *
|
|
- */
|
|
-static int bnx2_uio_verify(nic_t *nic)
|
|
-{
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(cnic_uio_sysfs_name_tempate) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Build the path to determine uio name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- cnic_uio_sysfs_name_tempate, nic->uio_minor);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n')
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- if (strncmp(raw, cnic_uio_sysfs_name, sizeof(cnic_uio_sysfs_name)) !=
|
|
- 0) {
|
|
- LOG_ERR(PFX "%s: uio names not equal: "
|
|
- "expecting %s got %s from %s",
|
|
- nic->log_name, cnic_uio_sysfs_name, raw, temp_path);
|
|
- rc = -EIO;
|
|
- }
|
|
-
|
|
- free(raw);
|
|
-
|
|
- LOG_INFO(PFX "%s: Verified is a cnic_uio device", nic->log_name);
|
|
-
|
|
-error:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2 Utility Functions to get to the hardware consumer indexes
|
|
- ******************************************************************************/
|
|
-static __u16 bnx2_get_rx_msix(bnx2_t *bp)
|
|
-{
|
|
- struct status_block_msix *sblk = bp->status_blk.msix;
|
|
- __u16 rx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- rx_cons = sblk->status_rx_quick_consumer_index;
|
|
- barrier();
|
|
- if ((rx_cons & (MAX_RX_DESC_CNT)) == (MAX_RX_DESC_CNT))
|
|
- rx_cons++;
|
|
-
|
|
- return rx_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2_get_rx_msi(bnx2_t *bp)
|
|
-{
|
|
- struct status_block *sblk = bp->status_blk.msi;
|
|
- __u16 rx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- rx_cons = BNX2_SBLK_EVEN_IDX(sblk->rx2);
|
|
- barrier();
|
|
- if ((rx_cons & (MAX_RX_DESC_CNT)) == (MAX_RX_DESC_CNT))
|
|
- rx_cons++;
|
|
-
|
|
- return rx_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2_get_tx_msix(bnx2_t *bp)
|
|
-{
|
|
- struct status_block_msix *sblk = bp->status_blk.msix;
|
|
- __u16 tx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- tx_cons = sblk->status_tx_quick_consumer_index;
|
|
- barrier();
|
|
- if ((tx_cons & (MAX_TX_DESC_CNT)) == (MAX_TX_DESC_CNT))
|
|
- tx_cons++;
|
|
-
|
|
- return tx_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2_get_tx_msi(bnx2_t *bp)
|
|
-{
|
|
- struct status_block *sblk = bp->status_blk.msi;
|
|
- __u16 tx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- tx_cons = BNX2_SBLK_EVEN_IDX(sblk->tx2);
|
|
- barrier();
|
|
- if ((tx_cons & (MAX_TX_DESC_CNT)) == (MAX_TX_DESC_CNT))
|
|
- tx_cons++;
|
|
-
|
|
- return tx_cons;
|
|
-}
|
|
-
|
|
-typedef enum {
|
|
- CNIC_VLAN_STRIPPING_ENABLED = 1,
|
|
- CNIC_VLAN_STRIPPING_DISABLED = 2,
|
|
-} CNIC_VLAN_STRIPPING_MODE;
|
|
-
|
|
-/**
|
|
- * bnx2_strip_vlan_enabled() - This will query the device to determine whether
|
|
- * VLAN tag stripping is enabled or not
|
|
- * @param dev - device to check stripping or not
|
|
- * @ return CNIC_VLAN_STRIPPING_ENABLED stripping is enabled
|
|
- * CNIC_VLAN_STRIPPING_DISABLED stripping is not enabled
|
|
- */
|
|
-static CNIC_VLAN_STRIPPING_MODE bnx2_strip_vlan_enabled(bnx2_t *bp)
|
|
-{
|
|
- uint32_t val;
|
|
-
|
|
- val = bnx2_rd32(bp, BNX2_EMAC_RX_MODE);
|
|
-
|
|
- if (val & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)
|
|
- return CNIC_VLAN_STRIPPING_DISABLED;
|
|
- else
|
|
- return CNIC_VLAN_STRIPPING_ENABLED;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_free() - Used to free a bnx2 structure
|
|
- */
|
|
-static void bnx2_free(nic_t *nic)
|
|
-{
|
|
- if (nic->priv)
|
|
- free(nic->priv);
|
|
- nic->priv = NULL;
|
|
-}
|
|
-
|
|
-
|
|
-/**
|
|
- * bnx2_alloc() - Used to allocate a bnx2 structure
|
|
- */
|
|
-static bnx2_t *bnx2_alloc(nic_t *nic)
|
|
-{
|
|
- bnx2_t *bp = malloc(sizeof(*bp));
|
|
- if (bp == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate bnx2 space", nic->log_name);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /* Clear out the bnx2 contents */
|
|
- memset(bp, 0, sizeof(*bp));
|
|
-
|
|
- bp->bar0_fd = INVALID_FD;
|
|
- bp->flags = BNX2_UIO_TX_HAS_SENT;
|
|
-
|
|
- bp->parent = nic;
|
|
- nic->priv = (void *)bp;
|
|
-
|
|
- return bp;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_open() - This will initialize all the hardware resources
|
|
- * @param dev - The struct nic device to open
|
|
- * @return 0 on success, on failure a errno will be returned
|
|
- */
|
|
-static int bnx2_open(nic_t *nic)
|
|
-{
|
|
- bnx2_t *bp;
|
|
- struct stat uio_stat;
|
|
- int i, rc;
|
|
- __u32 val;
|
|
- uint32_t tx_cid;
|
|
- __u32 msix_vector = 0;
|
|
- char sysfs_resc_path[80];
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "bnx2_open(): nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((nic->priv) != NULL &&
|
|
- (((bnx2_t *) (nic->priv))->flags & BNX2_OPENED)) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- bp = bnx2_alloc(nic);
|
|
- if (bp == NULL) {
|
|
- LOG_ERR(PFX "bnx2_open(): Couldn't allocate bp priv struct",
|
|
- nic->log_name);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- while (nic->fd < 0) {
|
|
- nic->fd = open(nic->uio_device_name, O_RDWR | O_NONBLOCK);
|
|
- if (nic->fd != INVALID_FD) {
|
|
- LOG_ERR(PFX
|
|
- "%s: uio device has been brought up via pid: "
|
|
- "%d on fd: %d",
|
|
- nic->uio_device_name, getpid(), nic->fd);
|
|
-
|
|
- rc = bnx2_uio_verify(nic);
|
|
- if (rc != 0)
|
|
- continue;
|
|
-
|
|
- break;
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: Could not open device: %s, [%s]",
|
|
- nic->log_name, nic->uio_device_name,
|
|
- strerror(errno));
|
|
- manually_trigger_uio_event(nic, nic->uio_minor);
|
|
-
|
|
- /* udev might not have created the file yet */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- sleep(1);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- }
|
|
- }
|
|
- if (fstat(nic->fd, &uio_stat) < 0) {
|
|
- LOG_ERR(PFX "%s: Could not fstat device", nic->log_name);
|
|
- errno = -ENODEV;
|
|
- goto error_alloc_rx_ring;
|
|
- }
|
|
- nic->uio_minor = minor(uio_stat.st_rdev);
|
|
-
|
|
- cnic_get_sysfs_pci_resource_path(nic, 0, sysfs_resc_path, 80);
|
|
- bp->bar0_fd = open(sysfs_resc_path, O_RDWR | O_SYNC);
|
|
- if (bp->bar0_fd < 0) {
|
|
- LOG_ERR(PFX "%s: Could not open %s", nic->log_name,
|
|
- sysfs_resc_path);
|
|
- errno = -ENODEV;
|
|
- goto error_alloc_rx_ring;
|
|
- }
|
|
-
|
|
- /* TODO: hardcoded with the cnic driver */
|
|
- bp->rx_ring_size = 3;
|
|
- bp->rx_buffer_size = 0x400;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: using rx ring size: %d, rx buffer size: %d",
|
|
- nic->log_name, bp->rx_ring_size, bp->rx_buffer_size);
|
|
-
|
|
- /* Determine the number of UIO events that have already occured */
|
|
- rc = detemine_initial_uio_events(nic, &nic->intr_count);
|
|
- if (rc != 0) {
|
|
- LOG_ERR("Could not determine the number ofinitial UIO events");
|
|
- nic->intr_count = 0;
|
|
- }
|
|
-
|
|
- /* Allocate space for rx ring pointer */
|
|
- bp->rx_ring = malloc(sizeof(struct l2_fhdr *) * bp->rx_ring_size);
|
|
- if (bp->rx_ring == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate space for rx_ring",
|
|
- nic->log_name);
|
|
- errno = -ENOMEM;
|
|
- goto error_alloc_rx_ring;
|
|
- }
|
|
- mlock(bp->rx_ring, sizeof(struct l2_fhdr *) * bp->rx_ring_size);
|
|
-
|
|
- /* Allocate space for rx pkt ring */
|
|
- bp->rx_pkt_ring = malloc(sizeof(void *) * bp->rx_ring_size);
|
|
- if (bp->rx_pkt_ring == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate space for rx_pkt_ring",
|
|
- nic->log_name);
|
|
- errno = -ENOMEM;
|
|
- goto error_alloc_rx_pkt_ring;
|
|
- }
|
|
- mlock(bp->rx_pkt_ring, sizeof(void *) * bp->rx_ring_size);
|
|
-
|
|
- bp->reg = mmap(NULL, 0x12800, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
- bp->bar0_fd, (off_t) 0);
|
|
- if (bp->reg == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Couldn't mmap registers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->reg = NULL;
|
|
- goto error_regs;
|
|
- }
|
|
-
|
|
- msync(bp->reg, 0x12800, MS_SYNC);
|
|
- LOG_DEBUG(PFX "Chip ID: %x", bnx2_get_chip_id(bp));
|
|
-
|
|
- /* on a 5709 when using MSI-X the status block is at an offset */
|
|
- if (BNX2_CHIP_NUM(bnx2_get_chip_id(bp)) == CHIP_NUM_5709) {
|
|
- /* determine if we are using MSI-X */
|
|
- val = bnx2_rd32(bp, BNX2_TSCH_TSS_CFG);
|
|
- if (val) {
|
|
- /* We are in MSI-X mode */
|
|
- uint32_t base_cid = ((val >> 10) & 0x7ff) << 3;
|
|
- msix_vector = (val >> 24) & 0xf;
|
|
-
|
|
- bp->status_blk_size = (128 * 9);
|
|
-
|
|
- tx_cid = base_cid + msix_vector - 1;
|
|
- bp->flags |= BNX2_UIO_MSIX_ENABLED;
|
|
-
|
|
- bp->get_tx_cons = bnx2_get_tx_msix;
|
|
- bp->get_rx_cons = bnx2_get_rx_msix;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: tss_cfg: 0x%x tx cid: %d",
|
|
- nic->log_name, val, tx_cid);
|
|
-
|
|
- LOG_INFO(PFX "%s: detected using MSI-X vector: %d",
|
|
- nic->log_name, msix_vector);
|
|
- } else {
|
|
- /* We are not in MSI-X mode */
|
|
- bp->status_blk_size = 64;
|
|
- tx_cid = 20;
|
|
-
|
|
- bp->get_tx_cons = bnx2_get_tx_msi;
|
|
- bp->get_rx_cons = bnx2_get_rx_msi;
|
|
- }
|
|
- } else {
|
|
- bp->status_blk_size = 64;
|
|
- tx_cid = 20;
|
|
-
|
|
- bp->get_tx_cons = bnx2_get_tx_msi;
|
|
- bp->get_rx_cons = bnx2_get_rx_msi;
|
|
- }
|
|
-
|
|
- bp->sblk_map = mmap(NULL, bp->status_blk_size,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
- nic->fd, (off_t) nic->page_size);
|
|
- if (bp->sblk_map == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap status block: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- goto error_sblk;
|
|
- }
|
|
-
|
|
- if (bp->flags & BNX2_UIO_MSIX_ENABLED) {
|
|
- uint8_t *status_blk = (uint8_t *) bp->sblk_map;
|
|
- status_blk += (msix_vector * 128);
|
|
-
|
|
- bp->status_blk.msix = (struct status_block_msix *)status_blk;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: msix initial cons: tx:%d rx:%d",
|
|
- nic->log_name,
|
|
- bp->status_blk.msix->status_tx_quick_consumer_index,
|
|
- bp->status_blk.msix->status_rx_quick_consumer_index);
|
|
- } else {
|
|
- bp->status_blk.msi = (struct status_block *)bp->sblk_map;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: msi initial tx:%d rx:%d",
|
|
- nic->log_name,
|
|
- BNX2_SBLK_EVEN_IDX(bp->status_blk.msi->tx2),
|
|
- BNX2_SBLK_EVEN_IDX(bp->status_blk.msi->rx2));
|
|
- }
|
|
-
|
|
- bp->tx_ring = mmap(NULL, 2 * nic->page_size,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED, nic->fd,
|
|
- (off_t) 2 * nic->page_size);
|
|
- if (bp->tx_ring == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap tx ring: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->tx_ring = NULL;
|
|
- goto error_tx_ring;
|
|
- }
|
|
-
|
|
- bp->bufs = mmap(NULL, (bp->rx_ring_size + 1) * bp->rx_buffer_size,
|
|
- PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED, nic->fd, (off_t) 3 * nic->page_size);
|
|
- if (bp->bufs == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap buffers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->bufs = NULL;
|
|
- goto error_bufs;
|
|
- }
|
|
-
|
|
- bp->tx_bidx_io = MB_GET_CID_ADDR(tx_cid) + BNX2_L2CTX_TX_HOST_BIDX;
|
|
- bp->tx_bseq_io = MB_GET_CID_ADDR(tx_cid) + BNX2_L2CTX_TX_HOST_BSEQ;
|
|
- LOG_INFO(PFX "%s: tx_bidx_io: 0x%x tx_bseq_io: 0x%x",
|
|
- nic->log_name, bp->tx_bidx_io, bp->tx_bseq_io);
|
|
-
|
|
- bp->rx_bidx_io = MB_GET_CID_ADDR(2) + BNX2_L2CTX_HOST_BDIDX;
|
|
- bp->rx_bseq_io = MB_GET_CID_ADDR(2) + BNX2_L2CTX_HOST_BSEQ;
|
|
-
|
|
- bp->tx_cons = 0;
|
|
- bp->tx_prod = 0;
|
|
- bp->tx_pkt = bp->bufs;
|
|
-
|
|
- bp->rx_index = 0;
|
|
- bp->rx_cons = 0;
|
|
- bp->rx_prod = bp->rx_ring_size;
|
|
- bp->rx_bseq = bp->rx_prod * bp->rx_buffer_size;
|
|
- bnx2_wr16(bp, bp->rx_bidx_io, bp->rx_prod);
|
|
- bnx2_wr32(bp, bp->rx_bseq_io, bp->rx_bseq);
|
|
-
|
|
- bnx2_reg_sync(bp, bp->rx_bidx_io, sizeof(__u16));
|
|
- bnx2_reg_sync(bp, bp->rx_bseq_io, sizeof(__u32));
|
|
-
|
|
- for (i = 0; i < bp->rx_ring_size; i++) {
|
|
- void *ptr = bp->bufs + (bp->rx_buffer_size * (i + 1));
|
|
-
|
|
- bp->rx_ring[i] = (struct l2_fhdr *)ptr;
|
|
- bp->rx_pkt_ring[i] = ptr + sizeof(struct l2_fhdr) + 2;
|
|
- }
|
|
-
|
|
- /* Read the MAC address used for the iSCSI interface */
|
|
- val = bnx2_rd32(bp, BNX2_EMAC_MAC_MATCH4);
|
|
- nic->mac_addr[0] = (__u8) (val >> 8);
|
|
- nic->mac_addr[1] = (__u8) val;
|
|
-
|
|
- val = bnx2_rd32(bp, BNX2_EMAC_MAC_MATCH5);
|
|
- nic->mac_addr[2] = (__u8) (val >> 24);
|
|
- nic->mac_addr[3] = (__u8) (val >> 16);
|
|
- nic->mac_addr[4] = (__u8) (val >> 8);
|
|
- nic->mac_addr[5] = (__u8) val;
|
|
-
|
|
- LOG_INFO(PFX "%s: Using mac address: %2x:%2x:%2x:%2x:%2x:%2x",
|
|
- nic->log_name,
|
|
- nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2],
|
|
- nic->mac_addr[3], nic->mac_addr[4], nic->mac_addr[5]);
|
|
-
|
|
- /* Determine if Hardware VLAN tag stripping is enabled or not */
|
|
- if (CNIC_VLAN_STRIPPING_ENABLED == bnx2_strip_vlan_enabled(bp))
|
|
- nic->flags |= NIC_VLAN_STRIP_ENABLED;
|
|
-
|
|
- /* Prepare the multicast addresses */
|
|
- val = 4 | BNX2_RPM_SORT_USER2_BC_EN | BNX2_RPM_SORT_USER2_MC_EN;
|
|
- if (BNX2_CHIP_NUM(bnx2_get_chip_id(bp)) != CHIP_NUM_5709)
|
|
- val |= BNX2_RPM_SORT_USER2_PROM_VLAN;
|
|
-
|
|
- bnx2_wr32(bp, BNX2_RPM_SORT_USER2, 0x0);
|
|
- bnx2_wr32(bp, BNX2_RPM_SORT_USER2, val);
|
|
- bnx2_wr32(bp, BNX2_RPM_SORT_USER2, val | BNX2_RPM_SORT_USER2_ENA);
|
|
-
|
|
- rc = enable_multicast(nic);
|
|
- if (rc != 0) {
|
|
- errno = rc;
|
|
- goto error_bufs;
|
|
- }
|
|
- msync(bp->reg, 0x12800, MS_SYNC);
|
|
- LOG_INFO("%s: bnx2 uio initialized", nic->log_name);
|
|
-
|
|
- bp->flags |= BNX2_OPENED;
|
|
-
|
|
- return 0;
|
|
-
|
|
-error_bufs:
|
|
- munmap(bp->tx_ring, 2 * nic->page_size);
|
|
-
|
|
-error_tx_ring:
|
|
- munmap(bp->status_blk.msi, bp->status_blk_size);
|
|
-
|
|
-error_sblk:
|
|
- munmap(bp->reg, 0x12800);
|
|
-
|
|
-error_regs:
|
|
- munlock(bp->rx_pkt_ring, sizeof(void *) * bp->rx_ring_size);
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
-
|
|
-error_alloc_rx_pkt_ring:
|
|
- munlock(bp->rx_ring, sizeof(struct l2_fhdr *) * bp->rx_ring_size);
|
|
- free(bp->rx_ring);
|
|
- bp->rx_ring = NULL;
|
|
-
|
|
-error_alloc_rx_ring:
|
|
- if (nic->fd != INVALID_FD) {
|
|
- close(nic->fd);
|
|
- nic->fd = INVALID_FD;
|
|
- }
|
|
- bnx2_free(nic);
|
|
-
|
|
- return errno;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_uio_close_resources() - Used to free resource for the bnx2 NIC
|
|
- * @param nic - NIC device to free resource
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-static int bnx2_uio_close_resources(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- bnx2_t *bp = (bnx2_t *) nic->priv;
|
|
- int rc = 0;
|
|
-
|
|
- /* Remove the multicast addresses if added */
|
|
- if ((nic->flags & NIC_ADDED_MULICAST) &&
|
|
- (graceful == ALLOW_GRACEFUL_SHUTDOWN))
|
|
- disable_multicast(nic);
|
|
-
|
|
- /* Check if there is an assoicated bnx2 device */
|
|
- if (bp == NULL) {
|
|
- LOG_WARN(PFX "%s: when closing resources there is "
|
|
- "no assoicated bnx2", nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- /* Clean up allocated memory */
|
|
- if (bp->rx_ring != NULL) {
|
|
- free(bp->rx_ring);
|
|
- bp->rx_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->rx_pkt_ring != NULL) {
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
- }
|
|
-
|
|
- /* Clean up mapped registers */
|
|
- if (bp->bufs != NULL) {
|
|
- rc = munmap(bp->bufs,
|
|
- (bp->rx_ring_size + 1) * bp->rx_buffer_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap bufs", nic->log_name);
|
|
- bp->bufs = NULL;
|
|
- }
|
|
-
|
|
- if (bp->tx_ring != NULL) {
|
|
- rc = munmap(bp->tx_ring, 2 * nic->page_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap tx_rings",
|
|
- nic->log_name);
|
|
- bp->tx_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->status_blk.msix != NULL || bp->status_blk.msi != NULL) {
|
|
- rc = munmap(bp->sblk_map, bp->status_blk_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap status block",
|
|
- nic->log_name);
|
|
- bp->sblk_map = NULL;
|
|
-
|
|
- bp->status_blk.msix = NULL;
|
|
- bp->status_blk.msi = NULL;
|
|
- }
|
|
-
|
|
- if (bp->reg != NULL) {
|
|
- rc = munmap(bp->reg, 0x12800);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap regs", nic->log_name);
|
|
- bp->reg = NULL;
|
|
- }
|
|
-
|
|
- if (bp->bar0_fd != INVALID_FD) {
|
|
- close(bp->bar0_fd);
|
|
- bp->bar0_fd = INVALID_FD;
|
|
- }
|
|
-
|
|
- if (nic->fd != INVALID_FD) {
|
|
- rc = close(nic->fd);
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX
|
|
- "%s: Couldn't close uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: Closed uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- nic->fd = INVALID_FD;
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: Invalid uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: Closed all resources", nic->log_name);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_close() - Used to close the NIC device
|
|
- * @param nic - NIC device to close
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 if successful, <0 if there is an error
|
|
- */
|
|
-static int bnx2_close(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "bnx2_close(): nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "Closing NIC device: %s", nic->log_name);
|
|
-
|
|
- bnx2_uio_close_resources(nic, graceful);
|
|
- bnx2_free(nic);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void bnx2_prepare_xmit_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct packet *pkt)
|
|
-{
|
|
- bnx2_t *bp = (bnx2_t *) nic->priv;
|
|
- struct uip_vlan_eth_hdr *eth_vlan = (struct uip_vlan_eth_hdr *)pkt->buf;
|
|
- struct uip_eth_hdr *eth = (struct uip_eth_hdr *)bp->tx_pkt;
|
|
-
|
|
- if (eth_vlan->tpid == htons(UIP_ETHTYPE_8021Q)) {
|
|
- memcpy(bp->tx_pkt, pkt->buf, sizeof(struct uip_eth_hdr));
|
|
- eth->type = eth_vlan->type;
|
|
- pkt->buf_size -= (sizeof(struct uip_vlan_eth_hdr) -
|
|
- sizeof(struct uip_eth_hdr));
|
|
- memcpy(bp->tx_pkt + sizeof(struct uip_eth_hdr),
|
|
- pkt->buf + sizeof(struct uip_vlan_eth_hdr),
|
|
- pkt->buf_size - sizeof(struct uip_eth_hdr));
|
|
- } else
|
|
- memcpy(bp->tx_pkt, pkt->buf, pkt->buf_size);
|
|
-
|
|
- msync(bp->tx_pkt, pkt->buf_size, MS_SYNC);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_get_tx_pkt() - This function is used to a TX packet from the NIC
|
|
- * @param nic - The NIC device to send the packet
|
|
- *
|
|
- */
|
|
-void *bnx2_get_tx_pkt(nic_t *nic)
|
|
-{
|
|
- bnx2_t *bp = (bnx2_t *) nic->priv;
|
|
- return bp->tx_pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_start_xmit() - This function is used to send a packet of data
|
|
- * @param nic - The NIC device to send the packet
|
|
- * @param len - the length of the TX packet
|
|
- *
|
|
- */
|
|
-void bnx2_start_xmit(nic_t *nic, size_t len, u16_t vlan_id)
|
|
-{
|
|
- bnx2_t *bp = (bnx2_t *) nic->priv;
|
|
- uint16_t ring_prod;
|
|
- struct tx_bd *txbd;
|
|
- struct rx_bd *rxbd;
|
|
- rxbd = (struct rx_bd *)(((__u8 *) bp->tx_ring) + nic->page_size);
|
|
-
|
|
- if ((rxbd->rx_bd_haddr_hi == 0) && (rxbd->rx_bd_haddr_lo == 0)) {
|
|
- LOG_PACKET(PFX "%s: trying to transmit when device is closed",
|
|
- nic->log_name);
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
- return;
|
|
- }
|
|
-
|
|
- ring_prod = TX_RING_IDX(bp->tx_prod);
|
|
- txbd = &bp->tx_ring[ring_prod];
|
|
-
|
|
- txbd->tx_bd_mss_nbytes = len;
|
|
-
|
|
- if (vlan_id) {
|
|
- txbd->tx_bd_vlan_tag_flags = (vlan_id << 16) |
|
|
- TX_BD_FLAGS_VLAN_TAG | TX_BD_FLAGS_END | TX_BD_FLAGS_START;
|
|
- } else
|
|
- txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_END |
|
|
- TX_BD_FLAGS_START;
|
|
-
|
|
- bp->tx_bseq += len;
|
|
- bp->tx_prod = NEXT_TX_BD(bp->tx_prod);
|
|
-
|
|
- bnx2_wr16(bp, bp->tx_bidx_io, bp->tx_prod);
|
|
- bnx2_wr32(bp, bp->tx_bseq_io, bp->tx_bseq);
|
|
-
|
|
- bnx2_reg_sync(bp, bp->tx_bidx_io, sizeof(__u16));
|
|
- bnx2_reg_sync(bp, bp->tx_bseq_io, sizeof(__u32));
|
|
-
|
|
- LOG_PACKET(PFX "%s: sent %d bytes using dev->tx_prod: %d",
|
|
- nic->log_name, len, bp->tx_prod);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_write() - Used to write the data to the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data to be sent on the wire
|
|
- * @return 0 if successful, <0 if failed
|
|
- */
|
|
-int bnx2_write(nic_t *nic, nic_interface_t *nic_iface, packet_t *pkt)
|
|
-{
|
|
- bnx2_t *bp;
|
|
- struct uip_stack *uip;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL || nic_iface == NULL || pkt == NULL) {
|
|
- LOG_ERR(PFX "%s: bnx2_write() nic == 0x%p || "
|
|
- " nic_iface == 0x%p || "
|
|
- " pkt == 0x%x", nic, nic_iface, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2_t *)nic->priv;
|
|
- uip = &nic_iface->ustack;
|
|
-
|
|
- if (pkt->buf_size == 0) {
|
|
- LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
|
|
- LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- bnx2_prepare_xmit_packet(nic, nic_iface, pkt);
|
|
- bnx2_start_xmit(nic, pkt->buf_size,
|
|
- (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- /* bump the bnx2 dev send statistics */
|
|
- nic->stats.tx.packets++;
|
|
- nic->stats.tx.bytes += uip->uip_len;
|
|
-
|
|
- LOG_PACKET(PFX "%s: transmitted %d bytes "
|
|
- "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bseq:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bseq);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2_read() - Used to read the data from the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data
|
|
- * @return 0 if successful, <0 if failed
|
|
- */
|
|
-static int bnx2_read(nic_t *nic, packet_t *pkt)
|
|
-{
|
|
- bnx2_t *bp;
|
|
- int rc = 0;
|
|
- uint16_t hw_cons, sw_cons;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (unlikely(nic == NULL || pkt == NULL)) {
|
|
- LOG_ERR(PFX "%s: bnx2_write() nic == 0x%p || "
|
|
- " pkt == 0x%x", nic, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2_t *)nic->priv;
|
|
-
|
|
- hw_cons = bp->get_rx_cons(bp);
|
|
- sw_cons = bp->rx_cons;
|
|
-
|
|
- if (sw_cons != hw_cons) {
|
|
- uint8_t rx_index = bp->rx_index % 3;
|
|
- struct l2_fhdr *rx_hdr = bp->rx_ring[rx_index];
|
|
- void *rx_pkt = bp->rx_pkt_ring[rx_index];
|
|
- int len;
|
|
- uint16_t errors;
|
|
-
|
|
- LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d %d",
|
|
- nic->log_name, sw_cons, hw_cons, rx_index);
|
|
-
|
|
- msync(rx_hdr, sizeof(struct l2_fhdr), MS_SYNC);
|
|
- errors = ((rx_hdr->l2_fhdr_status & 0xffff0000) >> 16);
|
|
- len = ((rx_hdr->l2_fhdr_vtag_len & 0xffff0000) >> 16) - 4;
|
|
-
|
|
- if (unlikely((errors & (L2_FHDR_ERRORS_BAD_CRC |
|
|
- L2_FHDR_ERRORS_PHY_DECODE |
|
|
- L2_FHDR_ERRORS_ALIGNMENT |
|
|
- L2_FHDR_ERRORS_TOO_SHORT |
|
|
- L2_FHDR_ERRORS_GIANT_FRAME)) ||
|
|
- (len <= 0) ||
|
|
- (len > (bp->rx_buffer_size -
|
|
- (sizeof(struct l2_fhdr) + 2))) ||
|
|
- (len > pkt->max_buf_size))) {
|
|
- /* One of the fields in the BD is bad */
|
|
- uint16_t status = ((rx_hdr->l2_fhdr_status &
|
|
- 0x0000ffff));
|
|
-
|
|
- LOG_ERR(PFX "%s: Recv error: 0x%x status: 0x%x "
|
|
- "len: %d", nic->log_name, errors, status, len);
|
|
-
|
|
- if ((len < (bp->rx_buffer_size -
|
|
- (sizeof(struct l2_fhdr) + 2))) &&
|
|
- (len < pkt->max_buf_size))
|
|
- dump_packet_to_log(pkt->nic_iface, rx_pkt, len);
|
|
- } else {
|
|
- if (len < (bp->rx_buffer_size -
|
|
- (sizeof(struct l2_fhdr) + 2))) {
|
|
- msync(rx_pkt, len, MS_SYNC);
|
|
- /* Copy the data */
|
|
- memcpy(pkt->buf, rx_pkt, len);
|
|
- pkt->buf_size = len;
|
|
-
|
|
- /* Properly set the packet flags */
|
|
- /* check if there is VLAN tagging on the
|
|
- * packet */
|
|
- if (rx_hdr->l2_fhdr_status &
|
|
- L2_FHDR_STATUS_VLAN_TAG) {
|
|
- pkt->vlan_tag =
|
|
- rx_hdr->l2_fhdr_vtag_len & 0x0FFF;
|
|
- pkt->flags |= VLAN_TAGGED;
|
|
- } else {
|
|
- pkt->vlan_tag = 0;
|
|
- }
|
|
-
|
|
- rc = 1;
|
|
-
|
|
- LOG_PACKET(PFX "%s: processing packet "
|
|
- "length: %d", nic->log_name, len);
|
|
- } else {
|
|
- /* If the NIC passes up a packet bigger
|
|
- * then the RX buffer, flag it */
|
|
- LOG_ERR(PFX "%s: invalid packet length %d "
|
|
- "receive ", nic->log_name, len);
|
|
- }
|
|
- }
|
|
-
|
|
- bp->rx_index++;
|
|
- sw_cons = NEXT_RX_BD(sw_cons);
|
|
- bp->rx_prod = NEXT_RX_BD(bp->rx_prod);
|
|
- bp->rx_bseq += 0x400;
|
|
-
|
|
- bp->rx_cons = sw_cons;
|
|
- bnx2_wr16(bp, bp->rx_bidx_io, bp->rx_prod);
|
|
- bnx2_wr32(bp, bp->rx_bseq_io, bp->rx_bseq);
|
|
-
|
|
- bnx2_reg_sync(bp, bp->rx_bidx_io, sizeof(__u16));
|
|
- bnx2_reg_sync(bp, bp->rx_bseq_io, sizeof(__u32));
|
|
-
|
|
- /* bump the bnx2 dev recv statistics */
|
|
- nic->stats.rx.packets++;
|
|
- nic->stats.rx.bytes += pkt->buf_size;
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Clearing TX interrupts
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * bnx2_clear_tx_intr() - This routine is called when a TX interrupt occurs
|
|
- * @param nic - the nic the interrupt occured on
|
|
- * @return 0 on success
|
|
- */
|
|
-static int bnx2_clear_tx_intr(nic_t *nic)
|
|
-{
|
|
- bnx2_t *bp;
|
|
- uint16_t hw_cons;
|
|
-
|
|
- /* Sanity check: ensure the parameters passed in are valid */
|
|
- if (unlikely(nic == NULL)) {
|
|
- LOG_ERR(PFX "bnx2_read() nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2_t *) nic->priv;
|
|
- hw_cons = bp->get_tx_cons(bp);
|
|
-
|
|
- if (bp->flags & BNX2_UIO_TX_HAS_SENT)
|
|
- bp->flags &= ~BNX2_UIO_TX_HAS_SENT;
|
|
-
|
|
- LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
|
|
- nic->log_name, bp->tx_cons, hw_cons);
|
|
-
|
|
- bp->tx_cons = hw_cons;
|
|
-
|
|
- /* There is a queued TX packet that needs to be sent out. The usual
|
|
- * case is when stack will send an ARP packet out before sending the
|
|
- * intended packet */
|
|
- if (nic->tx_packet_queue != NULL) {
|
|
- packet_t *pkt;
|
|
-
|
|
- LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
|
|
- pkt = nic_dequeue_tx_packet(nic);
|
|
-
|
|
- /* Got a TX packet buffer of the TX queue and put it onto
|
|
- * the hardware */
|
|
- if (pkt != NULL) {
|
|
- bnx2_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
|
|
-
|
|
- bnx2_start_xmit(nic, pkt->buf_size,
|
|
- (pkt->nic_iface->vlan_priority << 12) |
|
|
- pkt->nic_iface->vlan_id);
|
|
-
|
|
- LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
|
|
- "dev->tx_cons: %d, dev->tx_prod: %d, "
|
|
- "dev->tx_bseq:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bseq);
|
|
-
|
|
- return -EAGAIN;
|
|
- }
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2 NIC op's table
|
|
- ******************************************************************************/
|
|
-struct nic_ops bnx2_op = {
|
|
- .description = "bnx2",
|
|
- .open = bnx2_open,
|
|
- .close = bnx2_close,
|
|
- .write = bnx2_write,
|
|
- .get_tx_pkt = bnx2_get_tx_pkt,
|
|
- .start_xmit = bnx2_start_xmit,
|
|
- .read = bnx2_read,
|
|
- .clear_tx_intr = bnx2_clear_tx_intr,
|
|
- .handle_iscsi_path_req = cnic_handle_iscsi_path_req,
|
|
-
|
|
- .lib_ops = {
|
|
- .get_library_name = bnx2_get_library_name,
|
|
- .get_pci_table = bnx2_get_pci_table,
|
|
- .get_library_version = bnx2_get_library_version,
|
|
- .get_build_date = bnx2_get_build_date,
|
|
- .get_transport_name = bnx2_get_transport_name,
|
|
- .get_uio_name = bnx2_get_uio_name,
|
|
- },
|
|
-};
|
|
diff --git a/iscsiuio/src/unix/libs/bnx2.h b/iscsiuio/src/unix/libs/bnx2.h
|
|
deleted file mode 100644
|
|
index 3ec9437..0000000
|
|
--- a/iscsiuio/src/unix/libs/bnx2.h
|
|
+++ /dev/null
|
|
@@ -1,304 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * bnx2.h - bnx2 user space driver
|
|
- *
|
|
- */
|
|
-#ifndef __BNX2_H__
|
|
-#define __BNX2_H__
|
|
-
|
|
-#include "nic.h"
|
|
-
|
|
-/******************************************************************************
|
|
- * Default BNX2 values
|
|
- ******************************************************************************/
|
|
-#define DEFAULT_NUM_RXBD 3
|
|
-#define DEFAULT_RX_LEN 0x400
|
|
-
|
|
-/******************************************************************************
|
|
- * BNX2 Hardware structures
|
|
- ******************************************************************************/
|
|
-/* status_block definition for MSI */
|
|
-struct status_block {
|
|
- volatile __u32 status_attn_bits;
|
|
- volatile __u32 status_attn_bits_ack;
|
|
- volatile __u32 tx0;
|
|
- volatile __u32 tx2;
|
|
- volatile __u32 rx0;
|
|
- volatile __u32 rx2;
|
|
- volatile __u32 rx4;
|
|
- volatile __u32 rx6;
|
|
- volatile __u32 rx8;
|
|
- volatile __u32 rx10;
|
|
- volatile __u32 rx12;
|
|
- volatile __u32 rx14;
|
|
- volatile __u32 cmd;
|
|
- volatile __u32 idx;
|
|
-};
|
|
-
|
|
-/* status_block definition for MSI-X */
|
|
-struct status_block_msix {
|
|
-#if 0
|
|
-#if defined(__BIG_ENDIAN)
|
|
- __u16 status_tx_quick_consumer_index;
|
|
- __u16 status_rx_quick_consumer_index;
|
|
- __u16 status_completion_producer_index;
|
|
- __u16 status_cmd_consumer_index;
|
|
- __u32 status_unused;
|
|
- __u16 status_idx;
|
|
- __u8 status_unused2;
|
|
- __u8 status_blk_num;
|
|
-#elif defined(__LITTLE_ENDIAN)
|
|
- __u16 status_rx_quick_consumer_index;
|
|
- __u16 status_tx_quick_consumer_index;
|
|
- __u16 status_cmd_consumer_index;
|
|
- __u16 status_completion_producer_index;
|
|
- __u32 status_unused;
|
|
- __u8 status_blk_num;
|
|
- __u8 status_unused2;
|
|
- __u16 status_idx;
|
|
-#endif
|
|
-#endif
|
|
- __u16 status_rx_quick_consumer_index;
|
|
- __u16 status_tx_quick_consumer_index;
|
|
- __u16 status_cmd_consumer_index;
|
|
- __u16 status_completion_producer_index;
|
|
- __u32 status_unused;
|
|
- __u8 status_blk_num;
|
|
- __u8 status_unused2;
|
|
- __u16 status_idx;
|
|
-};
|
|
-
|
|
-/* TX Buffer descriptor */
|
|
-struct tx_bd {
|
|
- __u32 tx_bd_haddr_hi;
|
|
- __u32 tx_bd_haddr_lo;
|
|
- __u32 tx_bd_mss_nbytes;
|
|
- __u32 tx_bd_vlan_tag_flags;
|
|
-#define TX_BD_FLAGS_VLAN_TAG (1<<3)
|
|
-#define TX_BD_FLAGS_END (1<<6)
|
|
-#define TX_BD_FLAGS_START (1<<7)
|
|
-};
|
|
-
|
|
-/* RX Buffer descriptor */
|
|
-struct rx_bd {
|
|
- __u32 rx_bd_haddr_hi;
|
|
- __u32 rx_bd_haddr_lo;
|
|
-
|
|
- __u32 rx_bd_len;
|
|
- __u32 rx_bd_flags;
|
|
-#define RX_BD_FLAGS_END (1<<2)
|
|
-#define RX_BD_FLAGS_START (1<<3)
|
|
-
|
|
-};
|
|
-
|
|
-/* This is the RX L2 Frame header */
|
|
-struct l2_fhdr {
|
|
- __u32 l2_fhdr_status;
|
|
-#define L2_FHDR_ERRORS_BAD_CRC (1<<17)
|
|
-#define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
|
|
-#define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
|
|
-#define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
|
|
-#define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
|
|
-#define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
|
|
-#define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
|
|
-
|
|
-#define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
|
|
-#define L2_FHDR_STATUS_TCP_DATAGRAM (1<<14)
|
|
-#define L2_FHDR_STATUS_IP_DATAGRAM (1<<13)
|
|
-#define L2_FHDR_STATUS_LLC_SNAP (1<<7)
|
|
-#define L2_FHDR_STATUS_VLAN_TAG (1<<6)
|
|
-
|
|
- __u32 l2_fhdr_hash;
|
|
-
|
|
- __u32 l2_fhdr_vtag_len;
|
|
- __u32 l2_fhdr_xsum;
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * BNX2 Registers Defitions/Values
|
|
- ******************************************************************************/
|
|
-#define BNX2_MISC_ID 0x00000808
|
|
-#define BNX2_EMAC_MAC_MATCH4 0x00001420
|
|
-#define BNX2_EMAC_MAC_MATCH5 0x00001424
|
|
-
|
|
-#define BNX2_EMAC_RX_MODE 0x000014c8
|
|
-#define BNX2_EMAC_RX_MODE_RESET (1L<<0)
|
|
-#define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2)
|
|
-#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3)
|
|
-#define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4)
|
|
-#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5)
|
|
-#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6)
|
|
-#define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7)
|
|
-#define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8)
|
|
-#define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9)
|
|
-#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10)
|
|
-#define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11)
|
|
-#define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12)
|
|
-
|
|
-#define BNX2_RPM_SORT_USER2 0x00001828
|
|
-#define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0)
|
|
-#define BNX2_RPM_SORT_USER2_BC_EN (1L<<16)
|
|
-#define BNX2_RPM_SORT_USER2_MC_EN (1L<<17)
|
|
-#define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18)
|
|
-#define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19)
|
|
-#define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20)
|
|
-#define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24)
|
|
-#define BNX2_RPM_SORT_USER2_ENA (1L<<31)
|
|
-
|
|
-/*
|
|
- * tsch_reg definition
|
|
- * offset: 0x4c00
|
|
- */
|
|
-#define BNX2_TSCH_TSS_CFG 0x00004c1c
|
|
-#define BNX2_TSCH_TSS_CFG_TSS_START_CID (0x7ffL<<8)
|
|
-#define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON (0xfL<<24)
|
|
-#define CNIC_UIO_INVALID_FD -1
|
|
-
|
|
-#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
|
|
-#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090
|
|
-
|
|
-#define BNX2_L2CTX_HOST_BDIDX 0x00000004
|
|
-#define BNX2_L2CTX_HOST_BSEQ 0x00000008
|
|
-
|
|
-/* Used to determin the CHIP ID */
|
|
-/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
|
|
-#define BNX2_CHIP_NUM(bp) ((bp) & 0xffff0000)
|
|
-#define CHIP_NUM_5706 0x57060000
|
|
-#define CHIP_NUM_5708 0x57080000
|
|
-#define CHIP_NUM_5709 0x57090000
|
|
-
|
|
-#define CHIP_REV(bp) ((bp) & 0x0000f000)
|
|
-#define CHIP_REV_Ax 0x00000000
|
|
-#define CHIP_REV_Bx 0x00001000
|
|
-#define CHIP_REV_Cx 0x00002000
|
|
-
|
|
-#define CHIP_METAL(bp) ((bp) & 0x00000ff0)
|
|
-#define CHIP_BONDING(bp) ((bp) & 0x0000000f)
|
|
-
|
|
-#define CHIP_ID(bp) ((bp) & 0xfffffff0)
|
|
-#define CHIP_ID_5706_A0 0x57060000
|
|
-#define CHIP_ID_5706_A1 0x57060010
|
|
-#define CHIP_ID_5706_A2 0x57060020
|
|
-#define CHIP_ID_5708_A0 0x57080000
|
|
-#define CHIP_ID_5708_B0 0x57081000
|
|
-#define CHIP_ID_5708_B1 0x57081010
|
|
-#define CHIP_ID_5709_A0 0x57090000
|
|
-#define CHIP_ID_5709_A1 0x57090010
|
|
-
|
|
-#define CHIP_BOND_ID(bp) ((bp) & 0xf)
|
|
-
|
|
-#define BNX2_SBLK_EVEN_IDX(x) (((x) & 0xffff0000) >> 16)
|
|
-
|
|
-#define TX_DESC_CNT (4096 / sizeof(struct tx_bd))
|
|
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
|
|
-
|
|
-#define NEXT_TX_BD(x) ((((x) & (MAX_TX_DESC_CNT - 1)) == \
|
|
- (MAX_TX_DESC_CNT - 1)) ? \
|
|
- (x) + 2 : (x) + 1)
|
|
-
|
|
-#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
|
|
-
|
|
-#define RX_DESC_CNT (4096 / sizeof(struct rx_bd))
|
|
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
|
|
-
|
|
-#define NEXT_RX_BD(x) ((((x) & (MAX_RX_DESC_CNT - 1)) == \
|
|
- (MAX_RX_DESC_CNT - 1)) ? \
|
|
- (x) + 2 : (x) + 1)
|
|
-
|
|
-#define MB_KERNEL_CTX_SHIFT 8
|
|
-#define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT)
|
|
-#define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1)
|
|
-#define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
|
|
-
|
|
-typedef struct bnx2 {
|
|
- nic_t *parent;
|
|
-
|
|
- uint16_t flags;
|
|
-#define BNX2_UIO_MSIX_ENABLED 0x0001
|
|
-#define BNX2_UIO_TX_HAS_SENT 0x0002
|
|
-#define BNX2_OPENED 0x0004
|
|
-
|
|
- int bar0_fd;
|
|
- void *reg; /* Pointer to the mapped registers */
|
|
-
|
|
- __u32 tx_bidx_io;
|
|
- __u32 tx_bseq_io;
|
|
-
|
|
- __u16 tx_prod;
|
|
- __u16 tx_cons;
|
|
- __u32 tx_bseq;
|
|
-
|
|
- __u32 rx_bidx_io;
|
|
- __u32 rx_bseq_io;
|
|
-
|
|
- __u16 rx_prod;
|
|
- __u16 rx_cons;
|
|
- __u32 rx_bseq;
|
|
-
|
|
- /* RX ring parameters */
|
|
- uint32_t rx_ring_size;
|
|
- uint32_t rx_buffer_size;
|
|
-
|
|
- void *bufs; /* Pointer to the mapped buffer space */
|
|
-
|
|
- /* Hardware Status Block locations */
|
|
- void *sblk_map;
|
|
- union {
|
|
- struct status_block *msi;
|
|
- struct status_block_msix *msix;
|
|
- } status_blk;
|
|
- size_t status_blk_size;
|
|
-
|
|
- __u16(*get_rx_cons) (struct bnx2 *);
|
|
- __u16(*get_tx_cons) (struct bnx2 *);
|
|
-
|
|
- uint16_t rx_index;
|
|
- struct l2_fhdr **rx_ring;
|
|
- void **rx_pkt_ring;
|
|
-
|
|
- struct tx_bd *tx_ring;
|
|
- void *tx_pkt;
|
|
-
|
|
- struct l2_fhdr rcv_l2_fhdr;
|
|
- __u8 rcv_buf[1500 + 2];
|
|
- __u32 rcv_size;
|
|
-} bnx2_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * bnx2 Function Declarations
|
|
- ******************************************************************************/
|
|
-struct nic_ops *bnx2_get_ops();
|
|
-#endif /* __BNX2_H__ */
|
|
diff --git a/iscsiuio/src/unix/libs/bnx2x.c b/iscsiuio/src/unix/libs/bnx2x.c
|
|
deleted file mode 100644
|
|
index 7481e86..0000000
|
|
--- a/iscsiuio/src/unix/libs/bnx2x.c
|
|
+++ /dev/null
|
|
@@ -1,1676 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * bnx2x.c - bnx2x user space driver
|
|
- *
|
|
- */
|
|
-
|
|
-/* include nic.h before linux/ethtool.h to avoid redefinitions of
|
|
- * eth structs
|
|
-*/
|
|
-#include "nic.h"
|
|
-#include <errno.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <linux/types.h> /* Needed for linux/ethtool.h on RHEL 5.x */
|
|
-#include <linux/sockios.h>
|
|
-#include <linux/ethtool.h>
|
|
-#include <sys/mman.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/sysmacros.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/user.h>
|
|
-#include <fcntl.h>
|
|
-#include <unistd.h>
|
|
-
|
|
-#include "config.h"
|
|
-
|
|
-#include "build_date.h"
|
|
-#include "bnx2x.h"
|
|
-#include "cnic.h"
|
|
-#include "logger.h"
|
|
-#include "nic_id.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-
|
|
-#define PFX "bnx2x "
|
|
-
|
|
-/* Foward struct declarations */
|
|
-struct nic_ops bnx2x_op;
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC Library Strings
|
|
- ******************************************************************************/
|
|
-static const char library_name[] = "bnx2x";
|
|
-static const char library_version[] = PACKAGE_VERSION;
|
|
-static const char library_uio_name[] = "bnx2x_cnic";
|
|
-
|
|
-/* The name that should be returned from /sys/class/uio/uio0/name */
|
|
-static const char cnic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
|
|
-static const char bnx2x_uio_sysfs_name[] = "bnx2x_cnic";
|
|
-
|
|
-/*******************************************************************************
|
|
- * String constants used to display human readable adapter name
|
|
- ******************************************************************************/
|
|
-static const char brcm_57710[] = "QLogic NetXtreme II BCM57710 10-Gigabit";
|
|
-static const char brcm_57711[] = "QLogic NetXtreme II BCM57711 10-Gigabit";
|
|
-static const char brcm_57711e[] = "QLogic NetXtreme II BCM57711E 10-Gigabit";
|
|
-static const char brcm_57712[] = "QLogic NetXtreme II BCM57712 10-Gigabit";
|
|
-static const char brcm_57712_MF[] = "QLogic NetXtreme II BCM57712 MF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57712_VF[] = "QLogic NetXtreme II BCM57712 VF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57713[] = "QLogic NetXtreme II BCM57713 10-Gigabit";
|
|
-static const char brcm_57713e[] = "QLogic NetXtreme II BCM57713E 10-Gigabit";
|
|
-static const char brcm_57800[] = "QLogic NetXtreme II BCM57800 10-Gigabit";
|
|
-static const char brcm_57800_MF[] = "QLogic NetXtreme II BCM57800 MF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57800_VF[] = "QLogic NetXtreme II BCM57800 VF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57810[] = "QLogic NetXtreme II BCM57810 10-Gigabit";
|
|
-static const char brcm_57810_MF[] = "QLogic NetXtreme II BCM57810 MF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57810_VF[] = "QLogic NetXtreme II BCM57810 VF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57811[] = "QLogic NetXtreme II BCM57811 10-Gigabit";
|
|
-static const char brcm_57811_MF[] = "QLogic NetXtreme II BCM57811 MF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57811_VF[] = "QLogic NetXtreme II BCM57811 VF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57840[] = "QLogic NetXtreme II BCM57840 10-Gigabit";
|
|
-static const char brcm_57840_MF[] = "QLogic NetXtreme II BCM57840 MF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57840_VF[] = "QLogic NetXtreme II BCM57840 VF "
|
|
- "10-Gigabit";
|
|
-static const char brcm_57840_4_10[] = "QLogic NetXtreme II BCM57840 4x"
|
|
- "10-Gigabit";
|
|
-static const char brcm_57840_2_20[] = "QLogic NetXtreme II BCM57840 2x"
|
|
- "20-Gigabit";
|
|
-
|
|
-/*******************************************************************************
|
|
- * PCI ID constants
|
|
- ******************************************************************************/
|
|
-#define PCI_VENDOR_ID_BROADCOM 0x14e4
|
|
-#define PCI_VENDOR_ID_QLOGIC 0x1077
|
|
-#define PCI_DEVICE_ID_NX2_57710 0x164e
|
|
-#define PCI_DEVICE_ID_NX2_57711 0x164f
|
|
-#define PCI_DEVICE_ID_NX2_57711E 0x1650
|
|
-#define PCI_DEVICE_ID_NX2_57712 0x1662
|
|
-#define PCI_DEVICE_ID_NX2_57712_MF 0x1663
|
|
-#define PCI_DEVICE_ID_NX2_57712_VF 0x166f
|
|
-#define PCI_DEVICE_ID_NX2_57713 0x1651
|
|
-#define PCI_DEVICE_ID_NX2_57713E 0x1652
|
|
-#define PCI_DEVICE_ID_NX2_57800 0x168a
|
|
-#define PCI_DEVICE_ID_NX2_57800_MF 0x16a5
|
|
-#define PCI_DEVICE_ID_NX2_57800_VF 0x16a9
|
|
-#define PCI_DEVICE_ID_NX2_57810 0x168e
|
|
-#define PCI_DEVICE_ID_NX2_57810_MF 0x16ae
|
|
-#define PCI_DEVICE_ID_NX2_57810_VF 0x16af
|
|
-#define PCI_DEVICE_ID_NX2_57811 0x163d
|
|
-#define PCI_DEVICE_ID_NX2_57811_MF 0x163e
|
|
-#define PCI_DEVICE_ID_NX2_57811_VF 0x163f
|
|
-#define PCI_DEVICE_ID_NX2_57840_OBSOLETE 0x168d
|
|
-#define PCI_DEVICE_ID_NX2_57840_MF_OBSOLETE 0x16ab
|
|
-#define PCI_DEVICE_ID_NX2_57840_4_10 0x16a1
|
|
-#define PCI_DEVICE_ID_NX2_57840_2_20 0x16a2
|
|
-#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4
|
|
-#define PCI_DEVICE_ID_NX2_57840_VF 0x16ad
|
|
-#define PCI_ANY_ID (~0)
|
|
-
|
|
-/* This is the table used to match PCI vendor and device ID's to the
|
|
- * human readable string names of the devices */
|
|
-static const struct pci_device_id bnx2x_pci_tbl[] = {
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57710,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57710},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57711},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711E,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57711e},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57712,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57712},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57712_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57712_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57712_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57712_VF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57713,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57713},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57713E,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57713e},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57800,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57800},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57800_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57800_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57800_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57800_VF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57810,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57810},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57810_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57810_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57810_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57810_VF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57811,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57811},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57811_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57811_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57811_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57811_VF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_OBSOLETE,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_MF_OBSOLETE,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_4_10,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_4_10},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_2_20,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_2_20},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_MF},
|
|
- {PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57840_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_VF},
|
|
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_NX2_57840_4_10,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_4_10},
|
|
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_NX2_57840_2_20,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_2_20},
|
|
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_NX2_57840_MF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_MF},
|
|
- {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_NX2_57840_VF,
|
|
- PCI_ANY_ID, PCI_ANY_ID, brcm_57840_VF},
|
|
-};
|
|
-
|
|
-static struct iro e1_iro[2] = {
|
|
- {0x45a0, 0x90, 0x8, 0x0, 0x8}, /* T6.0 */
|
|
- {0x50c8, 0x90, 0x8, 0x0, 0x8}, /* T6.4 */
|
|
-};
|
|
-
|
|
-static struct iro e1h_iro[2] = {
|
|
- {0x1c40, 0xe0, 0x8, 0x0, 0x8}, /* T6.0 */
|
|
- {0x1e00, 0xe0, 0x8, 0x0, 0x8}, /* T6.4 */
|
|
-};
|
|
-
|
|
-static struct iro e2_iro[2] = {
|
|
- {0x6000, 0x20, 0x0, 0x0, 0x8}, /* T6.0 */
|
|
- {0x6000, 0x20, 0x0, 0x0, 0x8}, /* T6.4 */
|
|
-};
|
|
-
|
|
-struct bnx2x_driver_version bnx2x_version = {
|
|
- BNX2X_UNKNOWN_MAJOR_VERSION,
|
|
- BNX2X_UNKNOWN_MINOR_VERSION,
|
|
- BNX2X_UNKNOWN_SUB_MINOR_VERSION,
|
|
-};
|
|
-
|
|
-static int bnx2x_clear_tx_intr(nic_t *nic);
|
|
-
|
|
-/*******************************************************************************
|
|
- * BNX2X Library Functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * bnx2x_get_library_name() - Used to get the name of this NIC libary
|
|
- * @param name - This function will return the pointer to this NIC
|
|
- * library name
|
|
- * @param name_size
|
|
- */
|
|
-static void bnx2x_get_library_name(char **name, size_t *name_size)
|
|
-{
|
|
- *name = (char *)library_name;
|
|
- *name_size = sizeof(library_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_library_version() - Used to get the version string of this
|
|
- * NIC libary
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library version string
|
|
- * @param version_size - This will be set with the version size
|
|
- */
|
|
-static void bnx2x_get_library_version(char **version, size_t *version_size)
|
|
-{
|
|
- *version = (char *)library_version;
|
|
- *version_size = sizeof(library_version);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_build_date() - Used to get the build date string of this library
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library build date string
|
|
- * @param version_size - This will be set with the build date string size
|
|
- */
|
|
-static void bnx2x_get_build_date(char **build, size_t *build_size)
|
|
-{
|
|
- *build = (char *)build_date;
|
|
- *build_size = sizeof(build_date);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_transport_name() - Used to get the transport name associated
|
|
- * with this this NIC libary
|
|
- * @param transport_name - This function will return the pointer to this NIC
|
|
- * library's associated transport string
|
|
- * @param transport_name_size - This will be set with the transport name size
|
|
- */
|
|
-static void bnx2x_get_transport_name(char **transport_name,
|
|
- size_t *transport_name_size)
|
|
-{
|
|
- *transport_name = (char *)bnx2i_library_transport_name;
|
|
- *transport_name_size = bnx2i_library_transport_name_size;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_uio_name() - Used to get the uio name associated with this this
|
|
- * NIC libary
|
|
- * @param uio_name - This function will return the pointer to this NIC
|
|
- * library's associated uio string
|
|
- * @param transport_name_size - This will be set with the uio name size
|
|
- */
|
|
-static void bnx2x_get_uio_name(char **uio_name, size_t *uio_name_size)
|
|
-{
|
|
- *uio_name = (char *)library_uio_name;
|
|
- *uio_name_size = sizeof(library_uio_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_pci_table() - Used to get the PCI table for this NIC libary to
|
|
- * determine which NIC's based off of PCI ID's are
|
|
- * supported
|
|
- * @param table - This function will return the pointer to the PCI table
|
|
- * @param entries - This function will return the number of entries in the NIC
|
|
- * library's PCI table
|
|
- */
|
|
-static void bnx2x_get_pci_table(struct pci_device_id **table,
|
|
- uint32_t *entries)
|
|
-{
|
|
- *table = (struct pci_device_id *)bnx2x_pci_tbl;
|
|
- *entries =
|
|
- (uint32_t) (sizeof(bnx2x_pci_tbl) / sizeof(bnx2x_pci_tbl[0]));
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_ops() - Used to get the NIC library op table
|
|
- * @param op - The op table of this NIC library
|
|
- */
|
|
-struct nic_ops *bnx2x_get_ops()
|
|
-{
|
|
- return &bnx2x_op;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2x Utility Functions
|
|
- ******************************************************************************/
|
|
-/*******************************************************************************
|
|
- * Utility Functions Used to read register from the bnx2x device
|
|
- ******************************************************************************/
|
|
-static void bnx2x_set_drv_version_unknown(bnx2x_t *bp)
|
|
-{
|
|
- bp->version.major = BNX2X_UNKNOWN_MAJOR_VERSION;
|
|
- bp->version.minor = BNX2X_UNKNOWN_MINOR_VERSION;
|
|
- bp->version.sub_minor = BNX2X_UNKNOWN_SUB_MINOR_VERSION;
|
|
-}
|
|
-
|
|
-/* Return: 1 = Unknown, 0 = Known */
|
|
-static int bnx2x_is_drv_version_unknown(struct bnx2x_driver_version *version)
|
|
-{
|
|
- if ((version->major == (uint16_t)BNX2X_UNKNOWN_MAJOR_VERSION) &&
|
|
- (version->minor == (uint16_t)BNX2X_UNKNOWN_MINOR_VERSION) &&
|
|
- (version->sub_minor == (uint16_t)BNX2X_UNKNOWN_SUB_MINOR_VERSION)) {
|
|
- return 1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void bnx2x_set_drv_version_default(bnx2x_t *bp)
|
|
-{
|
|
- bp->version.major = BNX2X_DEFAULT_MAJOR_VERSION;
|
|
- bp->version.minor = BNX2X_DEFAULT_MINOR_VERSION;
|
|
- bp->version.sub_minor = BNX2X_DEFAULT_SUB_MINOR_VERSION;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_drv_version() - Used to determine the driver version
|
|
- * @param bp - Device used to determine bnx2x driver version
|
|
- */
|
|
-static int bnx2x_get_drv_version(bnx2x_t *bp)
|
|
-{
|
|
- nic_t *nic = bp->parent;
|
|
- int fd, rc;
|
|
- struct ifreq ifr;
|
|
- struct ethtool_drvinfo drvinfo;
|
|
- char *tok, *save_ptr = NULL;
|
|
-
|
|
- /* Setup our control structures. */
|
|
- memset(&ifr, 0, sizeof(ifr));
|
|
- strcpy(ifr.ifr_name, nic->eth_device_name);
|
|
-
|
|
- /* Open control socket. */
|
|
- fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
- if (fd < 0) {
|
|
- LOG_ERR(PFX "%s: Cannot get socket to determine version "
|
|
- "[0x%x %s]", nic->log_name, errno, strerror(errno));
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- memset(&drvinfo, 0, sizeof(drvinfo));
|
|
- drvinfo.cmd = ETHTOOL_GDRVINFO;
|
|
- ifr.ifr_data = (caddr_t) &drvinfo;
|
|
- rc = ioctl(fd, SIOCETHTOOL, &ifr);
|
|
- if (rc < 0) {
|
|
- LOG_ERR(PFX "%s: call to ethool IOCTL failed [0x%x %s]",
|
|
- nic->log_name, errno, strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- tok = strtok_r(drvinfo.version, ".", &save_ptr);
|
|
- if (tok == NULL) {
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
- bp->version.major = atoi(tok);
|
|
-
|
|
- tok = strtok_r(NULL, ".", &save_ptr);
|
|
- if (tok == NULL) {
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
- bp->version.minor = atoi(tok);
|
|
-
|
|
- tok = strtok_r(NULL, ".", &save_ptr);
|
|
- if (tok == NULL) {
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
- bp->version.sub_minor = atoi(tok);
|
|
-
|
|
- LOG_INFO(PFX "%s: interface version %d.%d.%d", nic->log_name,
|
|
- bp->version.major, bp->version.minor, bp->version.sub_minor);
|
|
-
|
|
- close(fd);
|
|
-
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- close(fd);
|
|
- bnx2x_set_drv_version_unknown(bp);
|
|
-
|
|
- LOG_ERR(PFX "%s: error parsing driver string: '%s'",
|
|
- nic->log_name, drvinfo.version);
|
|
-
|
|
- return rc;
|
|
-
|
|
-}
|
|
-
|
|
-static inline int bnx2x_is_ver70(bnx2x_t *bp)
|
|
-{
|
|
- return (bp->version.major == 1 && bp->version.minor >= 70);
|
|
-}
|
|
-
|
|
-static inline int bnx2x_is_ver60(bnx2x_t *bp)
|
|
-{
|
|
- return (bp->version.major == 1 && (bp->version.minor == 60 ||
|
|
- bp->version.minor == 62 ||
|
|
- bp->version.minor == 64));
|
|
-}
|
|
-
|
|
-static inline int bnx2x_is_ver60_plus(bnx2x_t *bp)
|
|
-{
|
|
- return bnx2x_is_ver60(bp) || bnx2x_is_ver70(bp);
|
|
-}
|
|
-
|
|
-static inline int bnx2x_is_ver52(bnx2x_t *bp)
|
|
-{
|
|
- return (bp->version.major == 1 && bp->version.minor == 52);
|
|
-}
|
|
-
|
|
-static void bnx2x_wr32(bnx2x_t *bp, __u32 off, __u32 val)
|
|
-{
|
|
- *((volatile __u32 *)(bp->reg + off)) = val;
|
|
-}
|
|
-
|
|
-static void bnx2x_doorbell(bnx2x_t *bp, __u32 off, __u32 val)
|
|
-{
|
|
- *((volatile __u32 *)(bp->reg2 + off)) = val;
|
|
-}
|
|
-
|
|
-static void bnx2x_flush_doorbell(bnx2x_t *bp, __u32 off)
|
|
-{
|
|
- volatile __u32 tmp __attribute__((__unused__));
|
|
-
|
|
- barrier();
|
|
- tmp = *((volatile __u32 *)(bp->reg2 + off));
|
|
-}
|
|
-
|
|
-static __u32 bnx2x_rd32(bnx2x_t *bp, __u32 off)
|
|
-{
|
|
- return *((volatile __u32 *)(bp->reg + off));
|
|
-}
|
|
-
|
|
-static int bnx2x_reg_sync(bnx2x_t *bp, __u32 off, __u16 length)
|
|
-{
|
|
- return msync(bp->reg + off, length, MS_SYNC);
|
|
-}
|
|
-
|
|
-static void bnx2x_update_rx_prod(bnx2x_t *bp)
|
|
-{
|
|
- struct ustorm_eth_rx_producers rx_prods = { 0 };
|
|
- int i;
|
|
-
|
|
- rx_prods.bd_prod = bp->rx_bd_prod;
|
|
- rx_prods.cqe_prod = bp->rx_prod;
|
|
-
|
|
- barrier();
|
|
-
|
|
- for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
|
|
- bnx2x_wr32(bp, bp->rx_prod_io + i * 4,
|
|
- ((__u32 *)&rx_prods)[i]);
|
|
-
|
|
- barrier();
|
|
-
|
|
- bnx2x_reg_sync(bp, bp->rx_prod_io,
|
|
- sizeof(struct ustorm_eth_rx_producers));
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_chip_id() - Used to retrive the chip ID from the nic
|
|
- * @param dev - Device used to determin NIC type
|
|
- * @return Chip ID read from the MISC ID register
|
|
- */
|
|
-static int bnx2x_get_chip_id(bnx2x_t *bp)
|
|
-{
|
|
- int val, id;
|
|
-
|
|
- /* Get the chip revision id and number. */
|
|
- /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
|
|
- val = bnx2x_rd32(bp, BNX2X_MISC_REG_CHIP_NUM);
|
|
- id = ((val & 0xffff) << 16);
|
|
- val = bnx2x_rd32(bp, BNX2X_MISC_REG_CHIP_REV);
|
|
- id |= ((val & 0xf) << 12);
|
|
- val = bnx2x_rd32(bp, BNX2X_MISC_REG_CHIP_METAL);
|
|
- id |= ((val & 0xff) << 4);
|
|
- val = bnx2x_rd32(bp, BNX2X_MISC_REG_BOND_ID);
|
|
- id |= (val & 0xf);
|
|
-
|
|
- return id;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_uio_verify()
|
|
- *
|
|
- */
|
|
-static int bnx2x_uio_verify(nic_t *nic)
|
|
-{
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(cnic_uio_sysfs_name_tempate) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Build the path to determine uio name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- cnic_uio_sysfs_name_tempate, nic->uio_minor);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n')
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- if (strncmp(raw, bnx2x_uio_sysfs_name,
|
|
- sizeof(bnx2x_uio_sysfs_name)) != 0) {
|
|
- LOG_ERR(PFX "%s: uio names not equal: "
|
|
- "expecting %s got %s from %s",
|
|
- nic->log_name, bnx2x_uio_sysfs_name, raw, temp_path);
|
|
- rc = -EIO;
|
|
- }
|
|
-
|
|
- free(raw);
|
|
-
|
|
- LOG_INFO(PFX "%s: Verified is a cnic_uio device", nic->log_name);
|
|
-
|
|
-error:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2x Utility Functions to get to the hardware consumer indexes
|
|
- ******************************************************************************/
|
|
-static __u16 bnx2x_get_rx(bnx2x_t *bp)
|
|
-{
|
|
- struct host_def_status_block *sblk = bp->status_blk.def;
|
|
- __u16 rx_comp_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- rx_comp_cons =
|
|
- sblk->u_def_status_block.
|
|
- index_values[HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS];
|
|
- if ((rx_comp_cons & BNX2X_MAX_RCQ_DESC_CNT(bp)) ==
|
|
- BNX2X_MAX_RCQ_DESC_CNT(bp))
|
|
- rx_comp_cons++;
|
|
-
|
|
- return rx_comp_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2x_get_rx_60(bnx2x_t *bp)
|
|
-{
|
|
- struct host_sp_status_block *sblk = bp->status_blk.sp;
|
|
- __u16 rx_comp_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- rx_comp_cons =
|
|
- sblk->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
|
|
- if ((rx_comp_cons & BNX2X_MAX_RCQ_DESC_CNT(bp)) ==
|
|
- BNX2X_MAX_RCQ_DESC_CNT(bp))
|
|
- rx_comp_cons++;
|
|
-
|
|
- return rx_comp_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2x_get_tx(bnx2x_t *bp)
|
|
-{
|
|
- struct host_def_status_block *sblk = bp->status_blk.def;
|
|
- __u16 tx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- tx_cons =
|
|
- sblk->c_def_status_block.
|
|
- index_values[HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS];
|
|
-
|
|
- return tx_cons;
|
|
-}
|
|
-
|
|
-static __u16 bnx2x_get_tx_60(bnx2x_t *bp)
|
|
-{
|
|
- struct host_sp_status_block *sblk = bp->status_blk.sp;
|
|
- __u16 tx_cons;
|
|
-
|
|
- msync(sblk, sizeof(*sblk), MS_SYNC);
|
|
- tx_cons = sblk->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_CQ_CONS];
|
|
-
|
|
- return tx_cons;
|
|
-}
|
|
-
|
|
-typedef enum {
|
|
- CNIC_VLAN_STRIPPING_ENABLED = 1,
|
|
- CNIC_VLAN_STRIPPING_DISABLED = 2,
|
|
-} CNIC_VLAN_STRIPPING_MODE;
|
|
-
|
|
-/**
|
|
- * bnx2x_strip_vlan_enabled() - This will query the device to determine whether
|
|
- * VLAN tag stripping is enabled or not
|
|
- * @param dev - device to check stripping or not
|
|
- * @ return CNIC_VLAN_STRIPPING_ENABLED stripping is enabled
|
|
- * CNIC_VLAN_STRIPPING_DISABLED stripping is not enabled
|
|
- */
|
|
-static CNIC_VLAN_STRIPPING_MODE bnx2x_strip_vlan_enabled(bnx2x_t *bp)
|
|
-{
|
|
- return CNIC_VLAN_STRIPPING_DISABLED;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_free() - Used to free a bnx2x structure
|
|
- */
|
|
-static void bnx2x_free(nic_t *nic)
|
|
-{
|
|
- if (nic->priv)
|
|
- free(nic->priv);
|
|
- nic->priv = NULL;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_alloc() - Used to allocate a bnx2x structure
|
|
- */
|
|
-static bnx2x_t *bnx2x_alloc(nic_t *nic)
|
|
-{
|
|
- bnx2x_t *bp = malloc(sizeof(*bp));
|
|
-
|
|
- if (bp == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate BNX2X space",
|
|
- nic->log_name);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /* Clear out the CNIC contents */
|
|
- memset(bp, 0, sizeof(*bp));
|
|
-
|
|
- bp->bar0_fd = INVALID_FD;
|
|
- bp->bar2_fd = INVALID_FD;
|
|
-
|
|
- bp->parent = nic;
|
|
- nic->priv = (void *)bp;
|
|
-
|
|
- bnx2x_set_drv_version_unknown(bp);
|
|
-
|
|
- return bp;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_open() - This will initialize all the hardware resources underneath
|
|
- * a struct cnic_uio device
|
|
- * @param dev - The struct cnic_uio device to attach the hardware with
|
|
- * @return 0 on success, on failure a errno will be returned
|
|
- */
|
|
-static int bnx2x_open(nic_t *nic)
|
|
-{
|
|
- bnx2x_t *bp;
|
|
- struct stat uio_stat;
|
|
- int i, rc;
|
|
- __u32 val;
|
|
- int count;
|
|
- char sysfs_resc_path[80];
|
|
- uint32_t bus;
|
|
- uint32_t slot;
|
|
- uint32_t func;
|
|
- uint32_t mode;
|
|
- __u32 proto_offset;
|
|
- __u32 ovtag_offset;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((nic->priv) != NULL &&
|
|
- (((bnx2x_t *) (nic->priv))->flags & BNX2X_OPENED)) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- bp = bnx2x_alloc(nic);
|
|
- if (bp == NULL)
|
|
- return -ENOMEM;
|
|
-
|
|
- if (bnx2x_is_drv_version_unknown(&bnx2x_version)) {
|
|
- /* If version is unknown, go read from ethtool */
|
|
- rc = bnx2x_get_drv_version(bp);
|
|
- if (rc)
|
|
- bnx2x_set_drv_version_default(bp);
|
|
- else if (!(bnx2x_is_ver60_plus(bp) || bnx2x_is_ver52(bp)))
|
|
- bnx2x_set_drv_version_default(bp);
|
|
-
|
|
- LOG_INFO(PFX "%s: bnx2x Use baseline version %d.%d.%d",
|
|
- nic->log_name,
|
|
- bp->version.major, bp->version.minor,
|
|
- bp->version.sub_minor);
|
|
- } else {
|
|
- /* Version is not unknown, just use it */
|
|
- bnx2x_version.major = bp->version.major;
|
|
- bnx2x_version.minor = bp->version.minor;
|
|
- bnx2x_version.sub_minor = bp->version.sub_minor;
|
|
- }
|
|
-
|
|
- count = 0;
|
|
- while ((nic->fd < 0) && count < 15) {
|
|
- /* udev might not have created the file yet */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- sleep(1);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic->fd = open(nic->uio_device_name, O_RDWR | O_NONBLOCK);
|
|
- if (nic->fd != INVALID_FD) {
|
|
- LOG_ERR(PFX "%s: uio device has been brought up "
|
|
- "via pid: %d on fd: %d",
|
|
- nic->uio_device_name, getpid(), nic->fd);
|
|
-
|
|
- rc = bnx2x_uio_verify(nic);
|
|
- if (rc != 0)
|
|
- continue;
|
|
-
|
|
- break;
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: Could not open device: %s, [%s]",
|
|
- nic->log_name, nic->uio_device_name,
|
|
- strerror(errno));
|
|
-
|
|
- manually_trigger_uio_event(nic, nic->uio_minor);
|
|
-
|
|
- /* udev might not have created the file yet */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- sleep(1);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- count++;
|
|
- }
|
|
- }
|
|
- if (nic->fd == INVALID_FD) {
|
|
- LOG_ERR(PFX "%s: Could not open device: %s, [%s]",
|
|
- nic->log_name, nic->uio_device_name,
|
|
- strerror(errno));
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
- if (fstat(nic->fd, &uio_stat) < 0) {
|
|
- LOG_ERR(PFX "%s: Could not fstat device", nic->log_name);
|
|
- rc = -ENODEV;
|
|
- goto open_error;
|
|
- }
|
|
- nic->uio_minor = minor(uio_stat.st_rdev);
|
|
-
|
|
- cnic_get_sysfs_pci_resource_path(nic, 0, sysfs_resc_path, 80);
|
|
- bp->bar0_fd = open(sysfs_resc_path, O_RDWR | O_SYNC);
|
|
- if (bp->bar0_fd < 0) {
|
|
- LOG_ERR(PFX "%s: Could not open %s", nic->log_name,
|
|
- sysfs_resc_path);
|
|
- rc = -ENODEV;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->reg = mmap(NULL, BNX2X_BAR_SIZE, PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED, bp->bar0_fd, (off_t) 0);
|
|
-
|
|
- if (bp->reg == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Couldn't mmap BAR registers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->reg = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- msync(bp->reg, BNX2X_BAR_SIZE, MS_SYNC);
|
|
-
|
|
- cnic_get_sysfs_pci_resource_path(nic, 2, sysfs_resc_path, 80);
|
|
- bp->bar2_fd = open(sysfs_resc_path, O_RDWR | O_SYNC);
|
|
- if (bp->bar2_fd < 0) {
|
|
- LOG_ERR(PFX "%s: Could not open %s", nic->log_name,
|
|
- sysfs_resc_path);
|
|
- rc = -ENODEV;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->reg2 = mmap(NULL, BNX2X_BAR2_SIZE, PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED, bp->bar2_fd, (off_t) 0);
|
|
-
|
|
- if (bp->reg2 == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Couldn't mmap BAR2 registers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->reg2 = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- /* TODO: hardcoded with the cnic driver */
|
|
- bp->rx_ring_size = 15;
|
|
- bp->rx_buffer_size = 0x400;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: using rx ring size: %d, rx buffer size: %d",
|
|
- nic->log_name, bp->rx_ring_size, bp->rx_buffer_size);
|
|
-
|
|
- /* Determine the number of UIO events that have already occured */
|
|
- rc = detemine_initial_uio_events(nic, &nic->intr_count);
|
|
- if (rc != 0) {
|
|
- LOG_ERR("Could not determine the number ofinitial UIO events");
|
|
- nic->intr_count = 0;
|
|
- }
|
|
-
|
|
- /* Allocate space for rx pkt ring */
|
|
- bp->rx_pkt_ring = malloc(sizeof(void *) * bp->rx_ring_size);
|
|
- if (bp->rx_pkt_ring == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate space for rx_pkt_ring",
|
|
- nic->log_name);
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- if (bnx2x_is_ver60_plus(bp))
|
|
- bp->status_blk_size = sizeof(struct host_sp_status_block);
|
|
- else if (bnx2x_is_ver52(bp))
|
|
- bp->status_blk_size = sizeof(struct host_def_status_block);
|
|
- else {
|
|
- LOG_INFO(PFX "%s: Unsupported bnx2x driver [%d.%d]",
|
|
- nic->log_name, bp->version.major, bp->version.minor);
|
|
-
|
|
- rc = -ENOTSUP;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->status_blk.def = mmap(NULL, bp->status_blk_size,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
- nic->fd, (off_t) nic->page_size);
|
|
- if (bp->status_blk.def == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap status block: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->status_blk.def = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->tx_ring = mmap(NULL, 4 * nic->page_size,
|
|
- PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED | MAP_LOCKED,
|
|
- nic->fd, (off_t) 2 * nic->page_size);
|
|
- if (bp->tx_ring == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap tx ring: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->tx_ring = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->rx_comp_ring.cqe = (union eth_rx_cqe *)
|
|
- (((__u8 *) bp->tx_ring) + 2 * nic->page_size);
|
|
-
|
|
- bp->bufs = mmap(NULL, (bp->rx_ring_size + 1) * bp->rx_buffer_size,
|
|
- PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED | MAP_LOCKED,
|
|
- nic->fd, (off_t) 3 * nic->page_size);
|
|
- if (bp->bufs == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap buffers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->bufs = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->chip_id = bnx2x_get_chip_id(bp);
|
|
- LOG_DEBUG(PFX "Chip ID: %x", bp->chip_id);
|
|
-
|
|
- rc = get_bus_slot_func_num(nic, &bus, &slot, &func);
|
|
- if (rc != 0) {
|
|
- LOG_INFO(PFX "%s: Couldn't determine bus:slot.func",
|
|
- nic->log_name);
|
|
- goto open_error;
|
|
- }
|
|
- /* In E1/E1H use pci device function as read from sysfs.
|
|
- * In E2/E3 read physical function from ME register since these chips
|
|
- * support Physical Device Assignment where kernel BDF maybe arbitrary
|
|
- * (depending on hypervisor).
|
|
- */
|
|
- if (CHIP_IS_E2_PLUS(bp)) {
|
|
- func = (bnx2x_rd32(bp, BAR_ME_REGISTER) & ME_REG_ABS_PF_NUM) >>
|
|
- ME_REG_ABS_PF_NUM_SHIFT;
|
|
- }
|
|
- bp->func = func;
|
|
- bp->port = bp->func % PORT_MAX;
|
|
-
|
|
- if (CHIP_IS_E2_PLUS(bp)) {
|
|
- __u32 val = bnx2x_rd32(bp, MISC_REG_PORT4MODE_EN_OVWR);
|
|
- if (!(val & 1))
|
|
- val = bnx2x_rd32(bp, MISC_REG_PORT4MODE_EN);
|
|
- else
|
|
- val = (val >> 1) & 1;
|
|
-
|
|
- if (val)
|
|
- bp->pfid = func >> 1;
|
|
- else
|
|
- bp->pfid = func & 0x6;
|
|
- } else {
|
|
- bp->pfid = func;
|
|
- }
|
|
-
|
|
- if (bnx2x_is_ver60_plus(bp))
|
|
- bp->port = bp->pfid & 1;
|
|
-
|
|
- bp->cid = 17;
|
|
- bp->client_id = 17;
|
|
-
|
|
- if (bnx2x_is_ver60_plus(bp)) {
|
|
- struct client_init_general_data *data = bp->bufs;
|
|
-
|
|
- bp->client_id = data->client_id;
|
|
- if (data->uid.cid)
|
|
- bp->cid = data->uid.cid;
|
|
- if (bp->version.minor >= 78 && bp->version.sub_minor >= 55 &&
|
|
- data->uid.cid_override_key == UIO_USE_TX_DOORBELL) {
|
|
- bp->tx_doorbell = data->uid.tx_db_off;
|
|
- LOG_INFO(PFX "%s: tx doorbell override offset = 0x%x",
|
|
- nic->log_name, bp->tx_doorbell);
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: func 0x%x, pfid 0x%x, client_id 0x%x, cid 0x%x",
|
|
- nic->log_name, bp->func, bp->pfid, bp->client_id, bp->cid);
|
|
-
|
|
- if (CHIP_IS_E1(bp))
|
|
- bp->iro = e1_iro;
|
|
- else if (CHIP_IS_E1H(bp))
|
|
- bp->iro = e1h_iro;
|
|
- else if (CHIP_IS_E2_PLUS(bp))
|
|
- bp->iro = e2_iro;
|
|
-
|
|
- if (bnx2x_is_ver60_plus(bp)) {
|
|
- __u32 cl_qzone_id = BNX2X_CL_QZONE_ID(bp, bp->client_id);
|
|
-
|
|
- bp->iro_idx = 0;
|
|
- if (bp->version.minor >= 64) {
|
|
- bp->iro_idx = 1;
|
|
- cl_qzone_id = BNX2X_CL_QZONE_ID_64(bp, bp->client_id);
|
|
- }
|
|
-
|
|
- bp->rx_prod_io = BAR_USTRORM_INTMEM +
|
|
- (CHIP_IS_E2_PLUS(bp) ?
|
|
- USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
|
|
- USTORM_RX_PRODS_E1X_OFFSET(bp->port, bp->client_id));
|
|
-
|
|
- if (!bp->tx_doorbell)
|
|
- bp->tx_doorbell = bp->cid * 0x80 + 0x40;
|
|
-
|
|
- bp->get_rx_cons = bnx2x_get_rx_60;
|
|
- bp->get_tx_cons = bnx2x_get_tx_60;
|
|
- bp->tx_vlan_tag_bit = ETH_TX_BD_FLAGS_VLAN_TAG_T6X;
|
|
- } else {
|
|
- bp->rx_prod_io = BAR_USTRORM_INTMEM +
|
|
- USTORM_RX_PRODS_OFFSET(bp->port, bp->client_id);
|
|
-
|
|
- bp->tx_doorbell = bp->cid * nic->page_size + 0x40;
|
|
-
|
|
- bp->get_rx_cons = bnx2x_get_rx;
|
|
- bp->get_tx_cons = bnx2x_get_tx;
|
|
- bp->tx_vlan_tag_bit = ETH_TX_BD_FLAGS_VLAN_TAG_T5X;
|
|
- }
|
|
-
|
|
- bp->tx_cons = 0;
|
|
- bp->tx_prod = 0;
|
|
- bp->tx_bd_prod = 0;
|
|
- bp->tx_pkt = bp->bufs;
|
|
-
|
|
- bp->rx_index = 0;
|
|
- bp->rx_cons = 0;
|
|
- bp->rx_bd_cons = 0;
|
|
- bp->rx_prod = 127;
|
|
- bp->rx_bd_prod = bp->rx_ring_size;
|
|
-
|
|
- for (i = 0; i < bp->rx_ring_size; i++) {
|
|
- void *ptr = bp->bufs + (bp->rx_buffer_size * (i + 1));
|
|
-
|
|
- bp->rx_pkt_ring[i] = ptr;
|
|
- }
|
|
-
|
|
- val = bnx2x_rd32(bp, MISC_REG_SHARED_MEM_ADDR);
|
|
-
|
|
- bp->shmem_base = val;
|
|
- val = bnx2x_rd32(bp, bp->shmem_base + SHMEM_ISCSI_MAC_UPPER(bp));
|
|
- nic->mac_addr[0] = (__u8) (val >> 8);
|
|
- nic->mac_addr[1] = (__u8) val;
|
|
- val = bnx2x_rd32(bp, bp->shmem_base + SHMEM_ISCSI_MAC_LOWER(bp));
|
|
- nic->mac_addr[2] = (__u8) (val >> 24);
|
|
- nic->mac_addr[3] = (__u8) (val >> 16);
|
|
- nic->mac_addr[4] = (__u8) (val >> 8);
|
|
- nic->mac_addr[5] = (__u8) val;
|
|
-
|
|
- if (bnx2x_is_ver60_plus(bp) && CHIP_IS_E2_PLUS(bp)) {
|
|
- __u32 mf_cfg_addr = 0;
|
|
- __u32 mac_offset;
|
|
- __u8 mac[6];
|
|
-
|
|
- val = bnx2x_rd32(bp, (BNX2X_PATH(bp) ? MISC_REG_GENERIC_CR_1 :
|
|
- MISC_REG_GENERIC_CR_0));
|
|
- bp->shmem_base2 = val;
|
|
- if (bp->shmem_base2) {
|
|
- /* size */
|
|
- val = bnx2x_rd32(bp, bp->shmem_base2);
|
|
-
|
|
- if (val > 0x10)
|
|
- mf_cfg_addr =
|
|
- bnx2x_rd32(bp, bp->shmem_base2 + 0x10);
|
|
- }
|
|
-
|
|
- if (!mf_cfg_addr)
|
|
- mf_cfg_addr = bp->shmem_base + 0x7e4;
|
|
-
|
|
- /* shared_feat_cfg.config */
|
|
- mode = bnx2x_rd32(bp, bp->shmem_base + 0x354);
|
|
- mode &= 0x700;
|
|
- LOG_DEBUG(PFX "%s: mode = 0x%x", nic->log_name, mode);
|
|
- switch (mode) {
|
|
- case 0x300: /* SI mode */
|
|
- mac_offset = 0xe4 + (bp->func * 0x28) + 4;
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + mac_offset);
|
|
- mac[0] = (__u8) (val >> 8);
|
|
- mac[1] = (__u8) val;
|
|
- mac_offset += 4;
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + mac_offset);
|
|
- mac[2] = (__u8) (val >> 24);
|
|
- mac[3] = (__u8) (val >> 16);
|
|
- mac[4] = (__u8) (val >> 8);
|
|
- mac[5] = (__u8) val;
|
|
-
|
|
- if (mac[0] != 0xff) {
|
|
- memcpy(nic->mac_addr, mac, 6);
|
|
- } else if (bp->func > 1) {
|
|
- LOG_INFO(PFX "%s: Invalid mac address: "
|
|
- "%02x:%02x:%02x:%02x:%02x:%02x, abort",
|
|
- nic->log_name,
|
|
- mac[0], mac[1], mac[2],
|
|
- mac[3], mac[4], mac[5]);
|
|
- rc = -ENOTSUP;
|
|
- goto open_error;
|
|
- }
|
|
- break;
|
|
-
|
|
- case 0x0: /* MF SD mode */
|
|
- case 0x500:
|
|
- case 0x600:
|
|
- proto_offset = 0x24 + (bp->func * 0x18);
|
|
- ovtag_offset = proto_offset + 0xc;
|
|
-
|
|
- rc = -ENOTSUP;
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + ovtag_offset);
|
|
- val &= 0xffff;
|
|
- /* SD mode, check for valid outer VLAN */
|
|
- if (val == 0xffff) {
|
|
- LOG_ERR(PFX "%s: Invalid OV detected for SD, "
|
|
- " fallback to SF mode!\n",
|
|
- nic->log_name);
|
|
- goto SF;
|
|
- }
|
|
- /* Check for iSCSI protocol */
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + proto_offset);
|
|
- if ((val & 6) != 6)
|
|
- goto open_error;
|
|
-
|
|
- mac_offset = proto_offset + 0x4;
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + mac_offset);
|
|
- mac[0] = (__u8) (val >> 8);
|
|
- mac[1] = (__u8) val;
|
|
- mac_offset += 4;
|
|
- val = bnx2x_rd32(bp, mf_cfg_addr + mac_offset);
|
|
- mac[2] = (__u8) (val >> 24);
|
|
- mac[3] = (__u8) (val >> 16);
|
|
- mac[4] = (__u8) (val >> 8);
|
|
- mac[5] = (__u8) val;
|
|
- memcpy(nic->mac_addr, mac, 6);
|
|
- break;
|
|
- }
|
|
- }
|
|
-SF:
|
|
- LOG_INFO(PFX "%s: Using mac address: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- nic->log_name,
|
|
- nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2],
|
|
- nic->mac_addr[3], nic->mac_addr[4], nic->mac_addr[5]);
|
|
-
|
|
- /* Determine if Hardware VLAN tag stripping is enabled or not */
|
|
- if (CNIC_VLAN_STRIPPING_ENABLED == bnx2x_strip_vlan_enabled(bp))
|
|
- nic->flags |= NIC_VLAN_STRIP_ENABLED;
|
|
-
|
|
- msync(bp->reg, BNX2X_BAR_SIZE, MS_SYNC);
|
|
-
|
|
- LOG_INFO("%s: bnx2x initialized", nic->log_name);
|
|
-
|
|
- bnx2x_update_rx_prod(bp);
|
|
- bp->flags |= BNX2X_OPENED;
|
|
-
|
|
- return 0;
|
|
-
|
|
-open_error:
|
|
- if (bp->tx_ring) {
|
|
- munmap(bp->tx_ring, 4 * nic->page_size);
|
|
- bp->tx_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->status_blk.def) {
|
|
- munmap(bp->status_blk.def, bp->status_blk_size);
|
|
- bp->status_blk.def = NULL;
|
|
- }
|
|
-
|
|
- if (bp->reg) {
|
|
- munmap(bp->reg, BNX2X_BAR_SIZE);
|
|
- bp->reg = NULL;
|
|
- }
|
|
-
|
|
- if (bp->reg2) {
|
|
- munmap(bp->reg2, BNX2X_BAR2_SIZE);
|
|
- bp->reg2 = NULL;
|
|
- }
|
|
-
|
|
- if (bp->rx_pkt_ring) {
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->bar2_fd != INVALID_FD) {
|
|
- close(bp->bar2_fd);
|
|
- bp->bar2_fd = INVALID_FD;
|
|
- }
|
|
-
|
|
- if (bp->bar0_fd != INVALID_FD) {
|
|
- close(bp->bar0_fd);
|
|
- bp->bar0_fd = INVALID_FD;
|
|
- }
|
|
- if (nic->fd != INVALID_FD) {
|
|
- close(nic->fd);
|
|
- nic->fd = INVALID_FD;
|
|
- }
|
|
- bnx2x_free(nic);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_uio_close_resources() - Used to free resource for the NIC/CNIC
|
|
- * @param nic - NIC device to free resource
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-static int bnx2x_uio_close_resources(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
|
|
- int rc = 0;
|
|
-
|
|
- /* Check if there is an assoicated bnx2x device */
|
|
- if (bp == NULL) {
|
|
- LOG_WARN(PFX "%s: when closing resources there is "
|
|
- "no assoicated bnx2x", nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- /* Clean up allocated memory */
|
|
-
|
|
- if (bp->rx_pkt_ring != NULL) {
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
- }
|
|
-
|
|
- /* Clean up mapped registers */
|
|
- if (bp->bufs != NULL) {
|
|
- rc = munmap(bp->bufs,
|
|
- (bp->rx_ring_size + 1) * bp->rx_buffer_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap bufs", nic->log_name);
|
|
- bp->bufs = NULL;
|
|
- }
|
|
-
|
|
- if (bp->tx_ring != NULL) {
|
|
- rc = munmap(bp->tx_ring, 4 * nic->page_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap tx_rings",
|
|
- nic->log_name);
|
|
- bp->tx_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->status_blk.def != NULL) {
|
|
- rc = munmap(bp->status_blk.def, bp->status_blk_size);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap status block",
|
|
- nic->log_name);
|
|
- bp->status_blk.def = NULL;
|
|
- }
|
|
-
|
|
- if (bp->reg != NULL) {
|
|
- rc = munmap(bp->reg, BNX2X_BAR_SIZE);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap regs", nic->log_name);
|
|
- bp->reg = NULL;
|
|
- }
|
|
-
|
|
- if (bp->reg2 != NULL) {
|
|
- rc = munmap(bp->reg2, BNX2X_BAR2_SIZE);
|
|
- if (rc != 0)
|
|
- LOG_WARN(PFX "%s: Couldn't unmap regs", nic->log_name);
|
|
- bp->reg2 = NULL;
|
|
- }
|
|
-
|
|
- if (bp->bar2_fd != INVALID_FD) {
|
|
- close(bp->bar2_fd);
|
|
- bp->bar2_fd = INVALID_FD;
|
|
- }
|
|
-
|
|
- if (bp->bar0_fd != INVALID_FD) {
|
|
- close(bp->bar0_fd);
|
|
- bp->bar0_fd = INVALID_FD;
|
|
- }
|
|
-
|
|
- if (nic->fd != INVALID_FD) {
|
|
- rc = close(nic->fd);
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX
|
|
- "%s: Couldn't close uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: Closed uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- nic->fd = INVALID_FD;
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: Invalid uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- bnx2x_set_drv_version_unknown(bp);
|
|
-
|
|
- LOG_INFO(PFX "%s: Closed all resources", nic->log_name);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_close() - Used to close the NIC device
|
|
- * @param nic - NIC device to close
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 if successful, <0 if there is an error
|
|
- */
|
|
-static int bnx2x_close(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "bnx2x_close(): nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
- if (nic->priv == NULL) {
|
|
- LOG_ERR(PFX "bnx2x_close(): nic->priv == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "Closing NIC device: %s", nic->log_name);
|
|
-
|
|
- bnx2x_uio_close_resources(nic, graceful);
|
|
- bnx2x_free(nic);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void bnx2x_prepare_xmit_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct packet *pkt)
|
|
-{
|
|
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
|
|
- struct uip_vlan_eth_hdr *eth_vlan = (struct uip_vlan_eth_hdr *)pkt->buf;
|
|
- struct uip_eth_hdr *eth = (struct uip_eth_hdr *)bp->tx_pkt;
|
|
-
|
|
- if (eth_vlan->tpid == htons(UIP_ETHTYPE_8021Q)) {
|
|
- memcpy(bp->tx_pkt, pkt->buf, sizeof(struct uip_eth_hdr));
|
|
- eth->type = eth_vlan->type;
|
|
- pkt->buf_size -= (sizeof(struct uip_vlan_eth_hdr) -
|
|
- sizeof(struct uip_eth_hdr));
|
|
- memcpy(bp->tx_pkt + sizeof(struct uip_eth_hdr),
|
|
- pkt->buf + sizeof(struct uip_vlan_eth_hdr),
|
|
- pkt->buf_size - sizeof(struct uip_eth_hdr));
|
|
- } else
|
|
- memcpy(bp->tx_pkt, pkt->buf, pkt->buf_size);
|
|
-
|
|
- msync(bp->tx_pkt, pkt->buf_size, MS_SYNC);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_get_tx_pkt() - This function is used to a TX packet from the NIC
|
|
- * @param nic - The NIC device to send the packet
|
|
- */
|
|
-void *bnx2x_get_tx_pkt(nic_t *nic)
|
|
-{
|
|
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
|
|
- return bp->tx_pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_start_xmit() - This function is used to send a packet of data
|
|
- * @param nic - The NIC device to send the packet
|
|
- * @param len - the length of the TX packet
|
|
- *
|
|
- */
|
|
-void bnx2x_start_xmit(nic_t *nic, size_t len, u16_t vlan_id)
|
|
-{
|
|
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
|
|
- uint16_t ring_prod;
|
|
- struct eth_tx_start_bd *txbd;
|
|
- struct eth_tx_bd *txbd2;
|
|
- struct eth_rx_bd *rx_bd;
|
|
- rx_bd = (struct eth_rx_bd *)(((__u8 *) bp->tx_ring) + nic->page_size);
|
|
-
|
|
- if ((rx_bd->addr_hi == 0) && (rx_bd->addr_lo == 0)) {
|
|
- LOG_PACKET(PFX "%s: trying to transmit when device is closed",
|
|
- nic->log_name);
|
|
- return;
|
|
- }
|
|
-
|
|
- ring_prod = BNX2X_TX_RING_IDX(bp->tx_bd_prod);
|
|
- txbd = &bp->tx_ring[ring_prod];
|
|
-
|
|
- BNX2X_SET_TX_VLAN(bp, txbd, vlan_id);
|
|
-
|
|
- bp->tx_prod++;
|
|
- bp->tx_bd_prod = BNX2X_NEXT_TX_BD(bp->tx_bd_prod);
|
|
- bp->tx_bd_prod = BNX2X_NEXT_TX_BD(bp->tx_bd_prod);
|
|
-
|
|
- ring_prod = BNX2X_TX_RING_IDX(bp->tx_bd_prod);
|
|
- txbd2 = (struct eth_tx_bd *)&bp->tx_ring[ring_prod];
|
|
-
|
|
- txbd2->nbytes = len - 0x10;
|
|
- txbd2->total_pkt_bytes = len;
|
|
-
|
|
- bp->tx_bd_prod = BNX2X_NEXT_TX_BD(bp->tx_bd_prod);
|
|
-
|
|
- barrier();
|
|
- if (nic->nl_process_if_down == 0) {
|
|
- bnx2x_doorbell(bp, bp->tx_doorbell, 0x02 |
|
|
- (bp->tx_bd_prod << 16));
|
|
- bnx2x_flush_doorbell(bp, bp->tx_doorbell);
|
|
- } else {
|
|
- LOG_ERR(PFX "Pkt transmission failed.");
|
|
- }
|
|
-
|
|
- LOG_PACKET(PFX "%s: sent %d bytes using bp->tx_prod: %d",
|
|
- nic->log_name, len, bp->tx_prod);
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_write() - Used to write the data to the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data to be sent on the wire
|
|
- * @return 0 if successful, <0 if failed
|
|
- */
|
|
-int bnx2x_write(nic_t *nic, nic_interface_t *nic_iface, packet_t *pkt)
|
|
-{
|
|
- bnx2x_t *bp;
|
|
- struct uip_stack *uip;
|
|
- int i = 0;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL || nic_iface == NULL || pkt == NULL) {
|
|
- LOG_ERR(PFX "%s: bnx2x_write() nic == 0x%p || "
|
|
- " nic_iface == 0x%p || "
|
|
- " pkt == 0x%x", nic, nic_iface, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2x_t *) nic->priv;
|
|
- uip = &nic_iface->ustack;
|
|
-
|
|
- if (pkt->buf_size == 0) {
|
|
- LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Try to wait for a TX completion */
|
|
- for (i = 0; i < 15; i++) {
|
|
- struct timespec sleep_req = {.tv_sec = 0, .tv_nsec = 5000000 },
|
|
- sleep_rem;
|
|
-
|
|
- if (bnx2x_clear_tx_intr(nic) == 0)
|
|
- break;
|
|
-
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
-
|
|
- if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
|
|
- LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- bnx2x_prepare_xmit_packet(nic, nic_iface, pkt);
|
|
- bnx2x_start_xmit(nic, pkt->buf_size,
|
|
- (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- /* bump the cnic dev send statistics */
|
|
- nic->stats.tx.packets++;
|
|
- nic->stats.tx.bytes += uip->uip_len;
|
|
-
|
|
- LOG_PACKET(PFX "%s: transmitted %d bytes "
|
|
- "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline int bnx2x_get_rx_pad(bnx2x_t *bp, union eth_rx_cqe *cqe)
|
|
-{
|
|
- int pad = 0;
|
|
-
|
|
- if (bnx2x_is_ver70(bp))
|
|
- pad = ((union eth_rx_cqe_70 *)cqe)->fast_path_cqe_70. \
|
|
- placement_offset;
|
|
- else if (bnx2x_is_ver60(bp)) {
|
|
- if (bp->version.minor >= 64)
|
|
- pad = cqe->fast_path_cqe_64.placement_offset;
|
|
- else
|
|
- pad = cqe->fast_path_cqe.placement_offset;
|
|
- }
|
|
- return pad;
|
|
-}
|
|
-
|
|
-/**
|
|
- * bnx2x_read() - Used to read the data from the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data
|
|
- * @return 0 if successful, <0 if failed
|
|
- */
|
|
-static int bnx2x_read(nic_t *nic, packet_t *pkt)
|
|
-{
|
|
- bnx2x_t *bp;
|
|
- int rc = 0;
|
|
- uint16_t hw_cons, sw_cons, bd_cons, bd_prod;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (nic == NULL || pkt == NULL) {
|
|
- LOG_ERR(PFX "%s: bnx2x_read() nic == 0x%p || "
|
|
- " pkt == 0x%x", nic, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2x_t *) nic->priv;
|
|
-
|
|
- hw_cons = bp->get_rx_cons(bp);
|
|
- sw_cons = bp->rx_cons;
|
|
- bd_cons = BNX2X_RX_BD(bp->rx_bd_cons);
|
|
- bd_prod = BNX2X_RX_BD(bp->rx_bd_prod);
|
|
-
|
|
- if (sw_cons != hw_cons) {
|
|
- uint16_t comp_ring_index = sw_cons & BNX2X_MAX_RCQ_DESC_CNT(bp);
|
|
- uint8_t ring_index;
|
|
- union eth_rx_cqe *cqe;
|
|
- __u8 cqe_fp_flags;
|
|
- void *rx_pkt;
|
|
- int len, pad, cqe_size, max_len;
|
|
- rc = 1;
|
|
-
|
|
- if (bnx2x_is_ver70(bp)) {
|
|
- cqe = (union eth_rx_cqe *)
|
|
- &bp->rx_comp_ring.cqe70[comp_ring_index];
|
|
- cqe_size = sizeof(union eth_rx_cqe_70);
|
|
- } else {
|
|
- cqe = &bp->rx_comp_ring.cqe[comp_ring_index];
|
|
- cqe_size = sizeof(union eth_rx_cqe);
|
|
- }
|
|
- cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
|
|
-
|
|
- LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d",
|
|
- nic->log_name, sw_cons, hw_cons);
|
|
-
|
|
- msync(cqe, cqe_size, MS_SYNC);
|
|
-
|
|
- if (!(cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE)) {
|
|
- ring_index = bd_cons % 15;
|
|
- len = cqe->fast_path_cqe.pkt_len;
|
|
- pad = bnx2x_get_rx_pad(bp, cqe);
|
|
- rx_pkt = bp->rx_pkt_ring[ring_index] + pad;
|
|
-
|
|
- /* Doto query MTU size of physical device */
|
|
- /* Ensure len is valid */
|
|
- max_len = pkt->max_buf_size < bp->rx_buffer_size ?
|
|
- pkt->max_buf_size : bp->rx_buffer_size;
|
|
- if (len + pad > max_len) {
|
|
- LOG_DEBUG(PFX "%s: bad BD length: %d",
|
|
- nic->log_name, len);
|
|
- len = max_len - pad;
|
|
- }
|
|
- if (len > 0) {
|
|
- msync(rx_pkt, len, MS_SYNC);
|
|
- /* Copy the data */
|
|
- memcpy(pkt->buf, rx_pkt, len);
|
|
- pkt->buf_size = len;
|
|
-
|
|
- /* Properly set the packet flags */
|
|
- /* check if there is VLAN tagging */
|
|
- if (cqe->fast_path_cqe.vlan_tag != 0) {
|
|
- pkt->vlan_tag =
|
|
- cqe->fast_path_cqe.vlan_tag;
|
|
- pkt->flags |= VLAN_TAGGED;
|
|
- } else {
|
|
- pkt->vlan_tag = 0;
|
|
- }
|
|
-
|
|
- LOG_PACKET(PFX
|
|
- "%s: processing packet length: %d",
|
|
- nic->log_name, len);
|
|
-
|
|
- /* bump the cnic dev recv statistics */
|
|
- nic->stats.rx.packets++;
|
|
- nic->stats.rx.bytes += pkt->buf_size;
|
|
- }
|
|
-
|
|
- bd_cons = BNX2X_NEXT_RX_IDX(bd_cons);
|
|
- bd_prod = BNX2X_NEXT_RX_IDX(bd_prod);
|
|
-
|
|
- }
|
|
- sw_cons = BNX2X_NEXT_RCQ_IDX(bp, sw_cons);
|
|
- bp->rx_prod = BNX2X_NEXT_RCQ_IDX(bp, bp->rx_prod);
|
|
- }
|
|
- bp->rx_cons = sw_cons;
|
|
- bp->rx_bd_cons = bd_cons;
|
|
- bp->rx_bd_prod = bd_prod;
|
|
- bp->rx_hw_prod = hw_cons;
|
|
-
|
|
- if (rc)
|
|
- bnx2x_update_rx_prod(bp);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Clearing TX interrupts
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * bnx2x_clear_tx_intr() - This routine is called when a TX interrupt occurs
|
|
- * @param nic - the nic the interrupt occured on
|
|
- * @return 0 on success
|
|
- */
|
|
-static int bnx2x_clear_tx_intr(nic_t *nic)
|
|
-{
|
|
- bnx2x_t *bp;
|
|
- uint16_t hw_cons;
|
|
-
|
|
- /* Sanity check: ensure the parameters passed in are valid */
|
|
- if (unlikely(nic == NULL)) {
|
|
- LOG_ERR(PFX "bnx2x_read() nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (bnx2x_t *) nic->priv;
|
|
- hw_cons = bp->get_tx_cons(bp);
|
|
-
|
|
- if (bp->tx_cons == hw_cons) {
|
|
- if (bp->tx_cons == bp->tx_prod)
|
|
- return 0;
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- if (pthread_mutex_trylock(&nic->xmit_mutex)) {
|
|
- LOG_ERR(PFX "%s: unable to get xmit_mutex.", nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
|
|
- nic->log_name, bp->tx_cons, hw_cons);
|
|
- bp->tx_cons = hw_cons;
|
|
-
|
|
- /* There is a queued TX packet that needs to be sent out. The usual
|
|
- * case is when stack will send an ARP packet out before sending the
|
|
- * intended packet */
|
|
- if (nic->tx_packet_queue != NULL) {
|
|
- packet_t *pkt;
|
|
- int i;
|
|
-
|
|
- LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
|
|
- pkt = nic_dequeue_tx_packet(nic);
|
|
-
|
|
- /* Got a TX packet buffer of the TX queue and put it onto
|
|
- * the hardware */
|
|
- if (pkt != NULL) {
|
|
- bnx2x_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
|
|
-
|
|
- bnx2x_start_xmit(nic, pkt->buf_size,
|
|
- (pkt->nic_iface->vlan_priority << 12) |
|
|
- pkt->nic_iface->vlan_id);
|
|
-
|
|
- LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
|
|
- "dev->tx_cons: %d, dev->tx_prod: %d, "
|
|
- "dev->tx_bd_prod:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- /* Try to wait for a TX completion */
|
|
- for (i = 0; i < 15; i++) {
|
|
- struct timespec sleep_req = {.tv_sec = 0,
|
|
- .tv_nsec = 5000000
|
|
- }, sleep_rem;
|
|
-
|
|
- hw_cons = bp->get_tx_cons(bp);
|
|
- if (bp->tx_cons != hw_cons) {
|
|
- LOG_PACKET(PFX
|
|
- "%s: clearing tx interrupt [%d %d]",
|
|
- nic->log_name, bp->tx_cons, hw_cons);
|
|
- bp->tx_cons = hw_cons;
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * bnx2x NIC op's table
|
|
- ******************************************************************************/
|
|
-struct nic_ops bnx2x_op = {
|
|
- .description = "bnx2x",
|
|
- .open = bnx2x_open,
|
|
- .close = bnx2x_close,
|
|
- .write = bnx2x_write,
|
|
- .get_tx_pkt = bnx2x_get_tx_pkt,
|
|
- .start_xmit = bnx2x_start_xmit,
|
|
- .read = bnx2x_read,
|
|
- .clear_tx_intr = bnx2x_clear_tx_intr,
|
|
- .handle_iscsi_path_req = cnic_handle_iscsi_path_req,
|
|
-
|
|
- .lib_ops = {
|
|
- .get_library_name = bnx2x_get_library_name,
|
|
- .get_pci_table = bnx2x_get_pci_table,
|
|
- .get_library_version = bnx2x_get_library_version,
|
|
- .get_build_date = bnx2x_get_build_date,
|
|
- .get_transport_name = bnx2x_get_transport_name,
|
|
- .get_uio_name = bnx2x_get_uio_name,
|
|
- },
|
|
-};
|
|
diff --git a/iscsiuio/src/unix/libs/bnx2x.h b/iscsiuio/src/unix/libs/bnx2x.h
|
|
deleted file mode 100644
|
|
index e204cbb..0000000
|
|
--- a/iscsiuio/src/unix/libs/bnx2x.h
|
|
+++ /dev/null
|
|
@@ -1,715 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * bnx2x.h - bnx2x user space driver
|
|
- *
|
|
- */
|
|
-#ifndef __BNX2X_H__
|
|
-#define __BNX2X_H__
|
|
-
|
|
-#include "nic.h"
|
|
-
|
|
-/******************************************************************************
|
|
- * Default CNIC values
|
|
- ******************************************************************************/
|
|
-#define DEFAULT_BNX2X_NUM_RXBD 15
|
|
-#define DEFAULT_BNX2X_RX_LEN 0x400
|
|
-
|
|
-/******************************************************************************
|
|
- * BNX2X Hardware structures
|
|
- ******************************************************************************/
|
|
-#define HC_USTORM_DEF_SB_NUM_INDICES 8
|
|
-#define HC_CSTORM_DEF_SB_NUM_INDICES 8
|
|
-#define HC_XSTORM_DEF_SB_NUM_INDICES 4
|
|
-#define HC_TSTORM_DEF_SB_NUM_INDICES 4
|
|
-
|
|
-struct atten_def_status_block {
|
|
- volatile __u32 attn_bits;
|
|
- volatile __u32 attn_bits_ack;
|
|
- volatile __u8 status_block_id;
|
|
- volatile __u8 reserved0;
|
|
- volatile __u16 attn_bits_index;
|
|
- volatile __u32 reserved1;
|
|
-};
|
|
-
|
|
-struct cstorm_def_status_block_u {
|
|
- volatile __u16 index_values[HC_USTORM_DEF_SB_NUM_INDICES];
|
|
- volatile __u16 status_block_index;
|
|
- volatile __u8 func;
|
|
- volatile __u8 status_block_id;
|
|
- volatile __u32 __flags;
|
|
-};
|
|
-
|
|
-struct cstorm_def_status_block_c {
|
|
- volatile __u16 index_values[HC_CSTORM_DEF_SB_NUM_INDICES];
|
|
- volatile __u16 status_block_index;
|
|
- volatile __u8 func;
|
|
- volatile __u8 status_block_id;
|
|
- volatile __u32 __flags;
|
|
-};
|
|
-
|
|
-struct xstorm_def_status_block {
|
|
- volatile __u16 index_values[HC_XSTORM_DEF_SB_NUM_INDICES];
|
|
- volatile __u16 status_block_index;
|
|
- volatile __u8 func;
|
|
- volatile __u8 status_block_id;
|
|
- volatile __u32 __flags;
|
|
-};
|
|
-
|
|
-struct tstorm_def_status_block {
|
|
- volatile __u16 index_values[HC_TSTORM_DEF_SB_NUM_INDICES];
|
|
- volatile __u16 status_block_index;
|
|
- volatile __u8 func;
|
|
- volatile __u8 status_block_id;
|
|
- volatile __u32 __flags;
|
|
-};
|
|
-
|
|
-struct host_def_status_block {
|
|
- struct atten_def_status_block atten_status_block;
|
|
- struct cstorm_def_status_block_u u_def_status_block;
|
|
- struct cstorm_def_status_block_c c_def_status_block;
|
|
- struct xstorm_def_status_block x_def_status_block;
|
|
- struct tstorm_def_status_block t_def_status_block;
|
|
-};
|
|
-
|
|
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS 1
|
|
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_BD_CONS 3
|
|
-#define HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS 5
|
|
-
|
|
-struct atten_sp_status_block {
|
|
- __u32 attn_bits;
|
|
- __u32 attn_bits_ack;
|
|
- __u8 status_block_id;
|
|
- __u8 reserved0;
|
|
- __u16 attn_bits_index;
|
|
- __u32 reserved1;
|
|
-};
|
|
-
|
|
-#define HC_SP_SB_MAX_INDICES 16
|
|
-
|
|
-struct hc_sp_status_block {
|
|
- __u16 index_values[HC_SP_SB_MAX_INDICES];
|
|
- __u16 running_index;
|
|
- __u16 rsrv;
|
|
- __u32 rsrv1;
|
|
-};
|
|
-
|
|
-struct host_sp_status_block {
|
|
- struct atten_sp_status_block atten_status_block;
|
|
- struct hc_sp_status_block sp_sb;
|
|
-};
|
|
-
|
|
-#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS 5
|
|
-#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS 1
|
|
-
|
|
-/*
|
|
- * VLAN mode on TX BDs
|
|
- */
|
|
-enum eth_tx_vlan_type {
|
|
- X_ETH_NO_VLAN = 0,
|
|
- X_ETH_OUTBAND_VLAN = 1,
|
|
- X_ETH_INBAND_VLAN = 2,
|
|
- X_ETH_FW_ADDED_VLAN = 3,
|
|
- MAX_ETH_TX_VLAN_TYPE
|
|
-};
|
|
-
|
|
-/* TX Buffer descriptor */
|
|
-struct eth_tx_bd_flags {
|
|
- __u8 as_bitfield;
|
|
-/* t6.X HSI */
|
|
-#define ETH_TX_BD_FLAGS_IP_CSUM_T6X (0x1<<0)
|
|
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT_T6X 0
|
|
-#define ETH_TX_BD_FLAGS_L4_CSUM_T6X (0x1<<1)
|
|
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT_T6X 1
|
|
-#define ETH_TX_BD_FLAGS_VLAN_MODE_T6X (0x3<<2)
|
|
-#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT_T6X 2
|
|
-#define ETH_TX_BD_FLAGS_START_BD_T6X (0x1<<4)
|
|
-#define ETH_TX_BD_FLAGS_START_BD_SHIFT_T6X 4
|
|
-#define ETH_TX_BD_FLAGS_IS_UDP_T6X (0x1<<5)
|
|
-#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT_T6X 5
|
|
-#define ETH_TX_BD_FLAGS_SW_LSO_T6X (0x1<<6)
|
|
-#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT_T6X 6
|
|
-#define ETH_TX_BD_FLAGS_IPV6_T6X (0x1<<7)
|
|
-#define ETH_TX_BD_FLAGS_IPV6_SHIFT_T6X 7
|
|
-
|
|
-/* Legacy t5.2 HSI defines */
|
|
-#define ETH_TX_BD_FLAGS_VLAN_TAG_T5X (0x1<<0)
|
|
-#define ETH_TX_BD_FLAGS_VLAN_TAG_SHIFT_T5X 0
|
|
-#define ETH_TX_BD_FLAGS_IP_CSUM_T5X (0x1<<1)
|
|
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT_T5X 1
|
|
-#define ETH_TX_BD_FLAGS_L4_CSUM_T5X (0x1<<2)
|
|
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT_T5X 2
|
|
-#define ETH_TX_BD_FLAGS_END_BD_T5X (0x1<<3)
|
|
-#define ETH_TX_BD_FLAGS_END_BD_SHIFT_T5X 3
|
|
-#define ETH_TX_BD_FLAGS_START_BD_T5X (0x1<<4)
|
|
-#define ETH_TX_BD_FLAGS_START_BD_SHIFT_T5X 4
|
|
-#define ETH_TX_BD_FLAGS_HDR_POOL_T5X (0x1<<5)
|
|
-#define ETH_TX_BD_FLAGS_HDR_POOL_SHIFT_T5X 5
|
|
-#define ETH_TX_BD_FLAGS_SW_LSO_T5X (0x1<<6)
|
|
-#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT_T5X 6
|
|
-#define ETH_TX_BD_FLAGS_IPV6_T5X (0x1<<7)
|
|
-#define ETH_TX_BD_FLAGS_IPV6_SHIFT_T5X 7
|
|
-};
|
|
-
|
|
-#define ETH_TX_BD_FLAGS_VLAN_TAG_T6X \
|
|
- (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT_T6X)
|
|
-
|
|
-#define BNX2X_SET_TX_VLAN(bp, txbd, vlan_id) \
|
|
- do { \
|
|
- if (vlan_id) { \
|
|
- (txbd)->vlan = vlan_id; \
|
|
- (txbd)->bd_flags.as_bitfield |= \
|
|
- (bp)->tx_vlan_tag_bit; \
|
|
- } else { \
|
|
- (txbd)->vlan = (bp)->tx_prod; \
|
|
- (txbd)->bd_flags.as_bitfield &= \
|
|
- ~(bp)->tx_vlan_tag_bit; \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-struct eth_tx_start_bd {
|
|
- __u32 addr_lo;
|
|
- __u32 addr_hi;
|
|
- __u16 nbd;
|
|
- __u16 nbytes;
|
|
- __u16 vlan;
|
|
- struct eth_tx_bd_flags bd_flags;
|
|
- __u8 general_data;
|
|
-#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
|
|
-#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
|
|
-#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
|
|
-#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
|
|
-};
|
|
-
|
|
-struct eth_tx_bd {
|
|
- __u32 addr_lo;
|
|
- __u32 addr_hi;
|
|
- __u16 total_pkt_bytes;
|
|
- __u16 nbytes;
|
|
- __u8 reserved[4];
|
|
-};
|
|
-
|
|
-/* RX Buffer descriptor */
|
|
-struct eth_rx_bd {
|
|
- __u32 addr_lo;
|
|
- __u32 addr_hi;
|
|
-};
|
|
-
|
|
-struct ramrod_data {
|
|
- volatile __u32 data_lo;
|
|
- volatile __u32 data_hi;
|
|
-};
|
|
-
|
|
-struct common_ramrod_eth_rx_cqe {
|
|
- volatile __u8 ramrod_type;
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x1<<0)
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x7F<<1)
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 1
|
|
- volatile __u8 conn_type;
|
|
- volatile __u16 reserved1;
|
|
- volatile __u32 conn_and_cmd_data;
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_CID (0xFFFFFF<<0)
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_CID_SHIFT 0
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
|
|
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
|
|
- struct ramrod_data protocol_data;
|
|
- __u32 reserved2[4];
|
|
-};
|
|
-
|
|
-struct common_ramrod_eth_rx_cqe_70 {
|
|
- volatile __u8 ramrod_type;
|
|
- volatile __u8 conn_type;
|
|
- volatile __u16 reserved1;
|
|
- volatile __u32 conn_and_cmd_data;
|
|
- struct ramrod_data protocol_data;
|
|
- __u32 echo;
|
|
- __u32 reserved2[11];
|
|
-};
|
|
-
|
|
-struct parsing_flags {
|
|
- volatile __u16 flags;
|
|
-};
|
|
-
|
|
-struct eth_fast_path_rx_cqe {
|
|
- volatile __u8 type_error_flags;
|
|
-#define ETH_FAST_PATH_RX_CQE_TYPE (0x1<<0)
|
|
-#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
|
|
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<1)
|
|
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 1
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<2)
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 2
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<3)
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 3
|
|
-#define ETH_FAST_PATH_RX_CQE_START_FLG (0x1<<4)
|
|
-#define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
|
|
-#define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
|
|
-#define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
|
|
-#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
|
|
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
|
|
- volatile __u8 status_flags;
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3)
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3
|
|
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4)
|
|
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4
|
|
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5)
|
|
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6)
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
|
|
- volatile __u8 placement_offset;
|
|
- volatile __u8 queue_index;
|
|
- volatile __u32 rss_hash_result;
|
|
- volatile __u16 vlan_tag;
|
|
- volatile __u16 pkt_len;
|
|
- volatile __u16 len_on_bd;
|
|
- struct parsing_flags pars_flags;
|
|
- volatile __u16 sgl[8];
|
|
-};
|
|
-
|
|
-union eth_sgl_or_raw_data {
|
|
- volatile __u16 sgl[8];
|
|
- volatile __u32 raw_data[4];
|
|
-};
|
|
-
|
|
-struct eth_fast_path_rx_cqe_64 {
|
|
- volatile __u8 type_error_flags;
|
|
-#define ETH_FAST_PATH_RX_CQE_TYPE_64 (0x3<<0)
|
|
-#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT_64 0
|
|
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2)
|
|
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2
|
|
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_64 (0x1<<3)
|
|
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT_64 3
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_64 (0x1<<4)
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT_64 4
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_64 (0x1<<5)
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT_64 5
|
|
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_64 (0x3<<6)
|
|
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT_64 6
|
|
- volatile __u8 status_flags;
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3)
|
|
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3
|
|
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4)
|
|
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4
|
|
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5)
|
|
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6)
|
|
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
|
|
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
|
|
- volatile __u8 queue_index;
|
|
- volatile __u8 placement_offset;
|
|
- volatile __u32 rss_hash_result;
|
|
- volatile __u16 vlan_tag;
|
|
- volatile __u16 pkt_len;
|
|
- volatile __u16 len_on_bd;
|
|
- struct parsing_flags pars_flags;
|
|
- union eth_sgl_or_raw_data sgl_or_raw_data;
|
|
-};
|
|
-
|
|
-struct eth_fast_path_rx_cqe_70 {
|
|
- volatile __u8 type_error_flags;
|
|
- volatile __u8 status_flags;
|
|
- volatile __u8 queue_index;
|
|
- volatile __u8 placement_offset;
|
|
- volatile __u32 rss_hash_result;
|
|
- volatile __u16 vlan_tag;
|
|
- volatile __u16 pkt_len;
|
|
- volatile __u16 len_on_bd;
|
|
- struct parsing_flags pars_flags;
|
|
- union eth_sgl_or_raw_data sgl_or_raw_data;
|
|
- __u32 reserved1[8];
|
|
-};
|
|
-
|
|
-struct eth_rx_cqe_next_page {
|
|
- __u32 addr_lo;
|
|
- __u32 addr_hi;
|
|
- __u32 reserved[6];
|
|
-};
|
|
-
|
|
-struct eth_rx_cqe_next_page_70 {
|
|
- __u32 addr_lo;
|
|
- __u32 addr_hi;
|
|
- __u32 reserved[14];
|
|
-};
|
|
-
|
|
-union eth_rx_cqe {
|
|
- struct eth_fast_path_rx_cqe fast_path_cqe;
|
|
- struct eth_fast_path_rx_cqe_64 fast_path_cqe_64;
|
|
- struct common_ramrod_eth_rx_cqe ramrod_cqe;
|
|
- struct eth_rx_cqe_next_page next_page_cqe;
|
|
-};
|
|
-
|
|
-union eth_rx_cqe_70 {
|
|
- struct eth_fast_path_rx_cqe_70 fast_path_cqe_70;
|
|
- struct common_ramrod_eth_rx_cqe_70 ramrod_cqe_70;
|
|
- struct eth_rx_cqe_next_page_70 next_page_cqe_70;
|
|
-};
|
|
-
|
|
-struct uio_init_data {
|
|
- __u32 cid;
|
|
- __u32 tx_db_off;
|
|
- __u32 cid_override_key;
|
|
-#define UIO_USE_TX_DOORBELL 0x017855DB
|
|
-};
|
|
-
|
|
-struct client_init_general_data {
|
|
- __u8 client_id;
|
|
- __u8 statistics_counter_id;
|
|
- __u8 statistics_en_flg;
|
|
- __u8 is_fcoe_flg;
|
|
- __u8 activate_flg;
|
|
- __u8 sp_client_id;
|
|
- __u16 mtu;
|
|
- __u8 statistics_zero_flg;
|
|
- __u8 func_id;
|
|
- __u8 cos;
|
|
- __u8 traffic_type;
|
|
- struct uio_init_data uid;
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * BNX2X Registers and HSI
|
|
- ******************************************************************************/
|
|
-#define BNX2X_BAR_SIZE 0x500000
|
|
-#define BNX2X_BAR2_SIZE 0x12000
|
|
-
|
|
-#define BNX2X_CHIP_ID(bp) (bp->chip_id & 0xfffffff0)
|
|
-
|
|
-#define PORT_MAX 2
|
|
-
|
|
-/* [R 4] This field indicates the type of the device. '0' - 2 Ports; '1' - 1
|
|
- * Port. */
|
|
-#define BNX2X_MISC_REG_BOND_ID 0xa400
|
|
-/* [R 8] These bits indicate the metal revision of the chip. This value
|
|
- * starts at 0x00 for each all-layer tape-out and increments by one for each
|
|
- * tape-out. */
|
|
-#define BNX2X_MISC_REG_CHIP_METAL 0xa404
|
|
-/* [R 16] These bits indicate the part number for the chip. */
|
|
-#define BNX2X_MISC_REG_CHIP_NUM 0xa408
|
|
-/* [R 4] These bits indicate the base revision of the chip. This value
|
|
- * starts at 0x0 for the A0 tape-out and increments by one for each
|
|
- * all-layer tape-out. */
|
|
-#define BNX2X_MISC_REG_CHIP_REV 0xa40c
|
|
-
|
|
-/* From the bnx2x driver */
|
|
-#define CHIP_NUM(bp) (bp->chip_id >> 16)
|
|
-#define CHIP_NUM_57710 0x164e
|
|
-#define CHIP_NUM_57711 0x164f
|
|
-#define CHIP_NUM_57711E 0x1650
|
|
-#define CHIP_NUM_57712 0x1662
|
|
-#define CHIP_NUM_57712_MF 0x1663
|
|
-#define CHIP_NUM_57712_VF 0x166f
|
|
-#define CHIP_NUM_57713 0x1651
|
|
-#define CHIP_NUM_57713E 0x1652
|
|
-#define CHIP_NUM_57800 0x168a
|
|
-#define CHIP_NUM_57800_MF 0x16a5
|
|
-#define CHIP_NUM_57800_VF 0x16a9
|
|
-#define CHIP_NUM_57810 0x168e
|
|
-#define CHIP_NUM_57810_MF 0x16ae
|
|
-#define CHIP_NUM_57810_VF 0x16af
|
|
-#define CHIP_NUM_57811 0x163d
|
|
-#define CHIP_NUM_57811_MF 0x163e
|
|
-#define CHIP_NUM_57811_VF 0x163f
|
|
-#define CHIP_NUM_57840_OBSOLETE 0x168d
|
|
-#define CHIP_NUM_57840_MF_OBSOLETE 0x16ab
|
|
-#define CHIP_NUM_57840_4_10 0x16a1
|
|
-#define CHIP_NUM_57840_2_20 0x16a2
|
|
-#define CHIP_NUM_57840_MF 0x16a4
|
|
-#define CHIP_NUM_57840_VF 0x16ad
|
|
-
|
|
-#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
|
|
-#define CHIP_IS_57711(bp) (CHIP_NUM(bp) == CHIP_NUM_57711)
|
|
-#define CHIP_IS_57711E(bp) (CHIP_NUM(bp) == CHIP_NUM_57711E)
|
|
-#define CHIP_IS_57712(bp) (CHIP_NUM(bp) == CHIP_NUM_57712)
|
|
-#define CHIP_IS_57712_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57712_VF)
|
|
-#define CHIP_IS_57712_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57712_MF)
|
|
-#define CHIP_IS_57800(bp) (CHIP_NUM(bp) == CHIP_NUM_57800)
|
|
-#define CHIP_IS_57800_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57800_MF)
|
|
-#define CHIP_IS_57800_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57800_VF)
|
|
-#define CHIP_IS_57810(bp) (CHIP_NUM(bp) == CHIP_NUM_57810)
|
|
-#define CHIP_IS_57810_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57810_MF)
|
|
-#define CHIP_IS_57810_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57810_VF)
|
|
-#define CHIP_IS_57811(bp) (CHIP_NUM(bp) == CHIP_NUM_57811)
|
|
-#define CHIP_IS_57811_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57811_MF)
|
|
-#define CHIP_IS_57811_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57811_VF)
|
|
-
|
|
-#define CHIP_IS_57840(bp) \
|
|
- ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) || \
|
|
- (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) || \
|
|
- (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE))
|
|
-#define CHIP_IS_57840_MF(bp) ((CHIP_NUM(bp) == CHIP_NUM_57840_MF) || \
|
|
- (CHIP_NUM(bp) == CHIP_NUM_57840_MF_OBSOLETE))
|
|
-#define CHIP_IS_57840_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_VF)
|
|
-#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
|
|
- CHIP_IS_57711E(bp))
|
|
-
|
|
-#define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \
|
|
- CHIP_IS_57712_MF(bp) || \
|
|
- CHIP_IS_57712_VF(bp))
|
|
-#define CHIP_IS_E3(bp) (CHIP_IS_57800(bp) || \
|
|
- CHIP_IS_57800_MF(bp) || \
|
|
- CHIP_IS_57800_VF(bp) || \
|
|
- CHIP_IS_57810(bp) || \
|
|
- CHIP_IS_57810_MF(bp) || \
|
|
- CHIP_IS_57810_VF(bp) || \
|
|
- CHIP_IS_57840(bp) || \
|
|
- CHIP_IS_57840_MF(bp) || \
|
|
- CHIP_IS_57840_VF(bp) || \
|
|
- CHIP_IS_57811(bp) || \
|
|
- CHIP_IS_57811_MF(bp) || \
|
|
- CHIP_IS_57811_VF(bp))
|
|
-
|
|
-#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
|
|
-#define USES_WARPCORE(bp) (CHIP_IS_E3(bp))
|
|
-#define IS_E1H_OFFSET (!CHIP_IS_E1H(bp))
|
|
-/* End of From the bnx2x driver */
|
|
-
|
|
-#define CHIP_IS_E2_PLUS(bp) (CHIP_IS_E2(bp) || CHIP_IS_E3(bp))
|
|
-
|
|
-#define MISC_REG_SHARED_MEM_ADDR 0xa2b4
|
|
-
|
|
-#define MISC_REG_BOND_ID 0xa400
|
|
-#define MISC_REG_CHIP_METAL 0xa404
|
|
-#define MISC_REG_CHIP_NUM 0xa408
|
|
-#define MISC_REG_CHIP_REV 0xa40c
|
|
-
|
|
-#define MISC_REG_PORT4MODE_EN 0xa750
|
|
-#define MISC_REG_PORT4MODE_EN_OVWR 0xa720
|
|
-
|
|
-#define MISC_REG_GENERIC_CR_0 0xa460
|
|
-#define MISC_REG_GENERIC_CR_1 0xa464
|
|
-
|
|
-#define BAR_USTRORM_INTMEM 0x400000
|
|
-#define BAR_CSTRORM_INTMEM 0x410000
|
|
-#define BAR_XSTRORM_INTMEM 0x420000
|
|
-#define BAR_TSTRORM_INTMEM 0x430000
|
|
-
|
|
-#define BAR_ME_REGISTER 0x450000
|
|
-#define ME_REG_PF_NUM_SHIFT 0
|
|
-#define ME_REG_PF_NUM\
|
|
- (7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
|
|
-#define ME_REG_VF_VALID (1<<8)
|
|
-#define ME_REG_VF_NUM_SHIFT 9
|
|
-#define ME_REG_VF_NUM_MASK (0x3f<<ME_REG_VF_NUM_SHIFT)
|
|
-#define ME_REG_VF_ERR (0x1<<3)
|
|
-#define ME_REG_ABS_PF_NUM_SHIFT 16
|
|
-#define ME_REG_ABS_PF_NUM\
|
|
- (7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
|
|
-
|
|
-#define USTORM_RX_PRODS_OFFSET(port, client_id) \
|
|
- (IS_E1H_OFFSET ? (0x4000 + (port * 0x360) + (client_id * 0x30)) \
|
|
- :(0x1000 + (port * 0x680) + (client_id * 0x40)))
|
|
-
|
|
-struct iro {
|
|
- __u32 base;
|
|
- __u16 m1;
|
|
- __u16 m2;
|
|
- __u16 m3;
|
|
- __u16 size;
|
|
-};
|
|
-
|
|
-#define IRO_ENT (bp->iro[bp->iro_idx])
|
|
-
|
|
-#define USTORM_RX_PRODS_E1X_OFFSET(port, client_id) \
|
|
- (IRO_ENT.base + ((port) * IRO_ENT.m1) + ((client_id) * IRO_ENT.m2))
|
|
-
|
|
-#define USTORM_RX_PRODS_E2_OFFSET(qzone_id) \
|
|
- (IRO_ENT.base + ((qzone_id) * IRO_ENT.m1))
|
|
-
|
|
-#define ETH_MAX_RX_CLIENTS_E1H 28
|
|
-#define ETH_MAX_RX_CLIENTS_E2 28
|
|
-
|
|
-#define BNX2X_CL_QZONE_ID(bp, cli) \
|
|
- (cli + (bp->port * (CHIP_IS_E2(bp) ? \
|
|
- ETH_MAX_RX_CLIENTS_E2 : \
|
|
- ETH_MAX_RX_CLIENTS_E1H)))
|
|
-
|
|
-#define BNX2X_CL_QZONE_ID_64(bp, cli) \
|
|
- (CHIP_IS_E2_PLUS(bp) ? (cli) : \
|
|
- (cli + (bp->port * ETH_MAX_RX_CLIENTS_E1H)))
|
|
-
|
|
-#define BNX2X_PATH(bp) (!CHIP_IS_E2_PLUS(bp) ? 0 : (bp)->func & 1)
|
|
-
|
|
-#define SHMEM_P0_ISCSI_MAC_UPPER 0x4c
|
|
-#define SHMEM_P0_ISCSI_MAC_LOWER 0x50
|
|
-#define SHMEM_P1_ISCSI_MAC_UPPER 0x1dc
|
|
-#define SHMEM_P1_ISCSI_MAC_LOWER 0x1e0
|
|
-
|
|
-#define SHMEM_ISCSI_MAC_UPPER(bp) \
|
|
- (((bp)->port == 0) ? \
|
|
- SHMEM_P0_ISCSI_MAC_UPPER : SHMEM_P1_ISCSI_MAC_UPPER)
|
|
-
|
|
-#define SHMEM_ISCSI_MAC_LOWER(bp) \
|
|
- (((bp)->port == 0) ? \
|
|
- SHMEM_P0_ISCSI_MAC_LOWER : SHMEM_P1_ISCSI_MAC_LOWER)
|
|
-
|
|
-#define BNX2X_RCQ_DESC_CNT (4096 / sizeof(union eth_rx_cqe))
|
|
-#define BNX2X_RCQ_DESC_CNT_70 (4096 / sizeof(union eth_rx_cqe_70))
|
|
-#define BNX2X_MAX_RCQ_DESC_CNT(bp) \
|
|
- ((bnx2x_is_ver70(bp) ? BNX2X_RCQ_DESC_CNT_70 : BNX2X_RCQ_DESC_CNT) - 1)
|
|
-
|
|
-#define BNX2X_RX_DESC_CNT (4096 / sizeof(struct eth_rx_bd))
|
|
-#define BNX2X_MAX_RX_DESC_CNT (BNX2X_RX_DESC_CNT - 2)
|
|
-#define BNX2X_NUM_RX_BD (BNX2X_RX_DESC_CNT * 1)
|
|
-#define BNX2X_MAX_RX_BD (BNX2X_NUM_RX_BD - 1)
|
|
-
|
|
-#define BNX2X_TX_DESC_CNT (4096 / sizeof(struct eth_tx_start_bd))
|
|
-#define BNX2X_MAX_TX_DESC_CNT (BNX2X_TX_DESC_CNT - 1)
|
|
-
|
|
-#define BNX2X_NEXT_RX_IDX(x) ((((x) & (BNX2X_RX_DESC_CNT - 1)) == \
|
|
- (BNX2X_MAX_RX_DESC_CNT - 1)) ? \
|
|
- (x) + 3 : (x) + 1)
|
|
-
|
|
-#define BNX2X_NEXT_RCQ_IDX(bp, x) \
|
|
- ((((x) & BNX2X_MAX_RCQ_DESC_CNT(bp)) == \
|
|
- (BNX2X_MAX_RCQ_DESC_CNT(bp) - 1)) ? (x) + 2 : (x) + 1)
|
|
-#define BNX2X_RX_BD(x) ((x) & BNX2X_MAX_RX_BD)
|
|
-
|
|
-#define BNX2X_NEXT_TX_BD(x) ((((x) & (BNX2X_MAX_TX_DESC_CNT - 1)) == \
|
|
- (BNX2X_MAX_TX_DESC_CNT - 1)) ? \
|
|
- (x) + 2 : (x) + 1)
|
|
-
|
|
-#define BNX2X_TX_RING_IDX(x) ((x) & BNX2X_MAX_TX_DESC_CNT)
|
|
-
|
|
-struct ustorm_eth_rx_producers {
|
|
- __u16 cqe_prod;
|
|
- __u16 bd_prod;
|
|
- __u16 sge_prod;
|
|
- __u16 reserved;
|
|
-};
|
|
-
|
|
-#define BNX2X_DEFAULT_MAJOR_VERSION 1
|
|
-#define BNX2X_DEFAULT_MINOR_VERSION 70
|
|
-#define BNX2X_DEFAULT_SUB_MINOR_VERSION 1
|
|
-#define BNX2X_UNKNOWN_MAJOR_VERSION -1
|
|
-#define BNX2X_UNKNOWN_MINOR_VERSION -1
|
|
-#define BNX2X_UNKNOWN_SUB_MINOR_VERSION -1
|
|
-struct bnx2x_driver_version {
|
|
- uint16_t major;
|
|
- uint16_t minor;
|
|
- uint16_t sub_minor;
|
|
-};
|
|
-
|
|
-typedef struct bnx2x {
|
|
- nic_t *parent;
|
|
-
|
|
- struct bnx2x_driver_version version;
|
|
-
|
|
- uint16_t flags;
|
|
-#define CNIC_UIO_UNITIALIZED 0x0001
|
|
-#define CNIC_UIO_INITIALIZED 0x0002
|
|
-#define CNIC_UIO_ENABLED 0x0004
|
|
-#define CNIC_UIO_DISABLED 0x0008
|
|
-#define CNIC_UIO_IPv6_ENABLED 0x0010
|
|
-#define CNIC_UIO_ADDED_MULICAST 0x0020
|
|
-#define CNIC_UIO_MSIX_ENABLED 0x0200
|
|
-#define CNIC_UIO_TX_HAS_SENT 0x0400
|
|
-#define BNX2X_OPENED 0x0800
|
|
-
|
|
- void *reg; /* Pointer to the BAR1 mapped registers */
|
|
- void *reg2; /* Pointer to the BAR2 mapped registers */
|
|
-
|
|
- int bar0_fd;
|
|
- int bar2_fd;
|
|
-
|
|
- __u32 chip_id;
|
|
- __u32 shmem_base;
|
|
- __u32 shmem_base2;
|
|
- int func;
|
|
- int port;
|
|
- int pfid;
|
|
- __u32 cid;
|
|
- __u32 client_id;
|
|
-
|
|
- struct iro *iro;
|
|
- int iro_idx;
|
|
-
|
|
- __u32 tx_doorbell;
|
|
-
|
|
- __u16 tx_prod;
|
|
- __u16 tx_bd_prod;
|
|
- __u16 tx_cons;
|
|
- __u8 tx_vlan_tag_bit;
|
|
-
|
|
- __u32 rx_prod_io;
|
|
-
|
|
- __u16 rx_prod;
|
|
- __u16 rx_bd_prod;
|
|
- __u16 rx_cons;
|
|
- __u16 rx_bd_cons;
|
|
- __u16 rx_hw_prod;
|
|
-
|
|
- __u16(*get_rx_cons) (struct bnx2x *);
|
|
- __u16(*get_tx_cons) (struct bnx2x *);
|
|
-
|
|
- /* RX ring parameters */
|
|
- uint32_t rx_ring_size;
|
|
- uint32_t rx_buffer_size;
|
|
-
|
|
- void *bufs; /* Pointer to the mapped buffer space */
|
|
-
|
|
- /* Hardware Status Block locations */
|
|
- void *sblk_map;
|
|
- union {
|
|
- struct host_def_status_block *def;
|
|
- struct host_sp_status_block *sp;
|
|
- } status_blk;
|
|
-
|
|
- int status_blk_size;
|
|
-
|
|
- uint16_t rx_index;
|
|
- union {
|
|
- union eth_rx_cqe *cqe;
|
|
- union eth_rx_cqe_70 *cqe70;
|
|
- } rx_comp_ring;
|
|
- void **rx_pkt_ring;
|
|
-
|
|
- struct eth_tx_start_bd *tx_ring;
|
|
- void *tx_pkt;
|
|
-
|
|
-} bnx2x_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * bnx2x Function Declarations
|
|
- ******************************************************************************/
|
|
-void bnx2x_start_xmit(nic_t *nic, size_t len, u16_t vlan_id);
|
|
-
|
|
-struct nic_ops *bnx2x_get_ops();
|
|
-#endif /* __BNX2X_H__ */
|
|
diff --git a/iscsiuio/src/unix/libs/cnic.c b/iscsiuio/src/unix/libs/cnic.c
|
|
deleted file mode 100644
|
|
index 9cdf933..0000000
|
|
--- a/iscsiuio/src/unix/libs/cnic.c
|
|
+++ /dev/null
|
|
@@ -1,671 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * cnic.c - CNIC UIO uIP user space stack
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <signal.h>
|
|
-#include <stdio.h>
|
|
-#include <stdlib.h>
|
|
-#include <string.h>
|
|
-#include <unistd.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <linux/limits.h>
|
|
-#include <netinet/if_ether.h>
|
|
-#include <netinet/in.h>
|
|
-#include <netinet/ip6.h>
|
|
-#include <netinet/icmp6.h>
|
|
-#include <linux/netlink.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/time.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/user.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/mman.h>
|
|
-
|
|
-#include "uip_arp.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "logger.h"
|
|
-#include "options.h"
|
|
-
|
|
-#include "cnic.h"
|
|
-#include "iscsi_if.h"
|
|
-#include "ipv6_ndpc.h"
|
|
-#include "qedi.h"
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "CNIC "
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants shared between the bnx2 and bnx2x modules
|
|
- ******************************************************************************/
|
|
-const char bnx2i_library_transport_name[] = "bnx2i";
|
|
-const size_t bnx2i_library_transport_name_size =
|
|
- sizeof(bnx2i_library_transport_name);
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants for qedi module
|
|
- ******************************************************************************/
|
|
-const char qedi_library_transport_name[] = "qedi";
|
|
-const size_t qedi_library_transport_name_size =
|
|
- sizeof(qedi_library_transport_name);
|
|
-
|
|
-/******************************************************************************
|
|
- * Netlink Functions
|
|
- ******************************************************************************/
|
|
-
|
|
-static int cnic_arp_send(nic_t *nic, nic_interface_t *nic_iface, int fd,
|
|
- __u8 *mac_addr, __u32 ip_addr, char *addr_str)
|
|
-{
|
|
- struct ether_header *eth;
|
|
- struct ether_arp *arp;
|
|
- __u32 dst_ip = ip_addr;
|
|
- int pkt_size = sizeof(*eth) + sizeof(*arp);
|
|
- int rc;
|
|
- struct in_addr addr;
|
|
- static const uint8_t multicast_mac[] = {
|
|
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
-
|
|
- LOG_DEBUG(PFX "%s: host:%d - try getting xmit mutex cnic arp send",
|
|
- nic->log_name, nic->host_no);
|
|
- rc = pthread_mutex_trylock(&nic->xmit_mutex);
|
|
- if (rc != 0) {
|
|
- LOG_DEBUG(PFX "%s: could not get xmit_mutex", nic->log_name);
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- eth = (*nic->ops->get_tx_pkt) (nic);
|
|
- if (eth == NULL) {
|
|
- LOG_WARN(PFX "%s: couldn't get tx packet", nic->log_name);
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- nic_fill_ethernet_header(nic_iface, eth,
|
|
- nic->mac_addr, (void *)multicast_mac,
|
|
- &pkt_size, (void *)&arp, ETHERTYPE_ARP);
|
|
-
|
|
- arp->arp_hrd = htons(ARPHRD_ETHER);
|
|
- arp->arp_pro = htons(ETHERTYPE_IP);
|
|
- arp->arp_hln = ETH_ALEN;
|
|
- arp->arp_pln = 4;
|
|
- arp->arp_op = htons(ARPOP_REQUEST);
|
|
- memcpy(arp->arp_sha, nic->mac_addr, ETH_ALEN);
|
|
- memset(arp->arp_tha, 0, ETH_ALEN);
|
|
-
|
|
- /* Copy the IP address's into the ARP response */
|
|
- memcpy(arp->arp_spa, nic_iface->ustack.hostaddr, 4);
|
|
- memcpy(arp->arp_tpa, &dst_ip, 4);
|
|
-
|
|
- (*nic->nic_library->ops->start_xmit) (nic, pkt_size,
|
|
- (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- memcpy(&addr.s_addr, &dst_ip, sizeof(addr.s_addr));
|
|
- LOG_DEBUG(PFX "%s: Sent cnic arp request for IP: %s",
|
|
- nic->log_name, addr_str);
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int cnic_neigh_soliciation_send(nic_t *nic,
|
|
- nic_interface_t *nic_iface, int fd,
|
|
- __u8 *mac_addr,
|
|
- struct in6_addr *addr6_dst,
|
|
- char *addr_str)
|
|
-{
|
|
- struct ether_header *eth;
|
|
- struct ip6_hdr *ipv6_hdr;
|
|
- int rc, pkt_size;
|
|
- char buf[INET6_ADDRSTRLEN];
|
|
- struct ndpc_reqptr req_ptr;
|
|
-
|
|
- rc = pthread_mutex_trylock(&nic->xmit_mutex);
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s: could not get xmit_mutex", nic->log_name);
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- /* Build the ethernet header */
|
|
- eth = (*nic->ops->get_tx_pkt) (nic);
|
|
- if (eth == NULL) {
|
|
- LOG_WARN(PFX "%s: couldn't get tx packet", nic->log_name);
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- /* Copy the requested target address to the ipv6.dst */
|
|
- ipv6_hdr =
|
|
- (struct ip6_hdr *)((u8_t *) eth + sizeof(struct ether_header));
|
|
-
|
|
- memcpy(ipv6_hdr->ip6_dst.s6_addr, addr6_dst->s6_addr,
|
|
- sizeof(struct in6_addr));
|
|
-
|
|
- nic_fill_ethernet_header(nic_iface, eth, nic->mac_addr, nic->mac_addr,
|
|
- &pkt_size, (void *)&ipv6_hdr, ETHERTYPE_IPV6);
|
|
- req_ptr.eth = (void *)eth;
|
|
- req_ptr.ipv6 = (void *)ipv6_hdr;
|
|
- if (ndpc_request(&nic_iface->ustack, &req_ptr, &pkt_size,
|
|
- NEIGHBOR_SOLICIT))
|
|
- return -EAGAIN;
|
|
-
|
|
- /* Debug to print out the pkt context */
|
|
- inet_ntop(AF_INET6, ipv6_hdr->ip6_dst.s6_addr, buf, sizeof(buf));
|
|
- LOG_DEBUG(PFX "%s: ipv6 dst addr: %s", nic->log_name, buf);
|
|
- LOG_DEBUG(PFX "neighbor sol content "
|
|
- "dst mac %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- eth->ether_dhost[0], eth->ether_dhost[1],
|
|
- eth->ether_dhost[2], eth->ether_dhost[3],
|
|
- eth->ether_dhost[4], eth->ether_dhost[5]);
|
|
- LOG_DEBUG(PFX "src mac %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- eth->ether_shost[0], eth->ether_shost[1],
|
|
- eth->ether_shost[2], eth->ether_shost[3],
|
|
- eth->ether_shost[4], eth->ether_shost[5]);
|
|
- (*nic->nic_library->ops->start_xmit) (nic, pkt_size,
|
|
- (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: Sent cnic ICMPv6 neighbor request %s",
|
|
- nic->log_name, addr_str);
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int cnic_nl_neigh_rsp(nic_t *nic, int fd,
|
|
- struct iscsi_uevent *ev,
|
|
- struct iscsi_path *path_req,
|
|
- __u8 *mac_addr,
|
|
- nic_interface_t *nic_iface, int status, int type)
|
|
-{
|
|
- int rc;
|
|
- uint8_t *ret_buf;
|
|
- struct iscsi_uevent *ret_ev;
|
|
- struct iscsi_path *path_rsp;
|
|
- struct sockaddr_nl dest_addr;
|
|
- char addr_dst_str[INET6_ADDRSTRLEN];
|
|
-
|
|
- memset(&dest_addr, 0, sizeof(dest_addr));
|
|
- dest_addr.nl_family = AF_NETLINK;
|
|
- dest_addr.nl_pid = 0;
|
|
- dest_addr.nl_groups = 0; /* unicast */
|
|
-
|
|
- ret_buf = calloc(1, NLMSG_SPACE(sizeof(struct iscsi_uevent) + 256));
|
|
- if (ret_buf == NULL) {
|
|
- LOG_ERR(PFX "Could not allocate memory for path req resposne");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- memset(ret_buf, 0, NLMSG_SPACE(sizeof(struct iscsi_uevent) + 256));
|
|
-
|
|
- /* prepare the iscsi_uevent buffer */
|
|
- ret_ev = (struct iscsi_uevent *)ret_buf;
|
|
- ret_ev->type = ISCSI_UEVENT_PATH_UPDATE;
|
|
- ret_ev->transport_handle = ev->transport_handle;
|
|
- ret_ev->u.set_path.host_no = ev->r.req_path.host_no;
|
|
-
|
|
- /* Prepare the iscsi_path buffer */
|
|
- path_rsp = (struct iscsi_path *)(ret_buf + sizeof(*ret_ev));
|
|
- path_rsp->handle = path_req->handle;
|
|
- if (type == AF_INET) {
|
|
- path_rsp->ip_addr_len = 4;
|
|
- memcpy(&path_rsp->src.v4_addr, nic_iface->ustack.hostaddr,
|
|
- sizeof(nic_iface->ustack.hostaddr));
|
|
-
|
|
- inet_ntop(AF_INET, &path_rsp->src.v4_addr,
|
|
- addr_dst_str, sizeof(addr_dst_str));
|
|
- } else {
|
|
- u8_t *src_ipv6;
|
|
- int ret;
|
|
-
|
|
- /* Depending on the IPv6 address of the target we will need to
|
|
- * determine whether we use the assigned IPv6 address or the
|
|
- * link local IPv6 address */
|
|
- if (ndpc_request(&nic_iface->ustack, &path_req->dst.v6_addr,
|
|
- &ret, CHECK_LINK_LOCAL_ADDR)) {
|
|
- src_ipv6 = (u8_t *)all_zeroes_addr6;
|
|
- LOG_DEBUG(PFX "RSP Check LL failed");
|
|
- goto src_done;
|
|
- }
|
|
- if (ret) {
|
|
- /* Get link local IPv6 address */
|
|
- src_ipv6 = (u8_t *)&nic_iface->ustack.linklocal6;
|
|
- } else {
|
|
- if (ndpc_request(&nic_iface->ustack,
|
|
- &path_req->dst.v6_addr,
|
|
- &src_ipv6, GET_HOST_ADDR)) {
|
|
- src_ipv6 = (u8_t *)all_zeroes_addr6;
|
|
- LOG_DEBUG(PFX "RSP Get host addr failed");
|
|
- }
|
|
- if (src_ipv6 == NULL) {
|
|
- src_ipv6 = (u8_t *)all_zeroes_addr6;
|
|
- LOG_DEBUG(PFX "RSP no Best matched addr found");
|
|
- }
|
|
- }
|
|
-src_done:
|
|
- path_rsp->ip_addr_len = 16;
|
|
- memcpy(&path_rsp->src.v6_addr, src_ipv6,
|
|
- sizeof(nic_iface->ustack.hostaddr6));
|
|
-
|
|
- inet_ntop(AF_INET6, &path_rsp->src.v6_addr,
|
|
- addr_dst_str, sizeof(addr_dst_str));
|
|
- }
|
|
- memcpy(path_rsp->mac_addr, mac_addr, 6);
|
|
- path_rsp->vlan_id = (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id;
|
|
- path_rsp->pmtu = nic_iface->mtu ? nic_iface->mtu : path_req->pmtu;
|
|
-
|
|
- rc = __kipc_call(fd, ret_ev, sizeof(*ret_ev) + sizeof(*path_rsp));
|
|
- if (rc > 0) {
|
|
- LOG_DEBUG(PFX "neighbor reply sent back to kernel "
|
|
- "%s at %02x:%02x:%02x:%02x:%02x:%02x with vlan %d",
|
|
- addr_dst_str,
|
|
- mac_addr[0], mac_addr[1],
|
|
- mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- } else {
|
|
- LOG_ERR(PFX "send neighbor reply failed: %d", rc);
|
|
- }
|
|
-
|
|
- free(ret_buf);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static const struct timeval tp_wait = {
|
|
- .tv_sec = 0,
|
|
- .tv_usec = 250000,
|
|
-};
|
|
-
|
|
-/**
|
|
- * cnic_handle_ipv4_iscsi_path_req() - This function will handle the IPv4
|
|
- * path req calls the bnx2i kernel module
|
|
- * @param nic - The nic the message is directed towards
|
|
- * @param fd - The file descriptor to be used to extract the private data
|
|
- * @param ev - The iscsi_uevent
|
|
- * @param buf - The private message buffer
|
|
- */
|
|
-int cnic_handle_ipv4_iscsi_path_req(nic_t *nic, int fd,
|
|
- struct iscsi_uevent *ev,
|
|
- struct iscsi_path *path,
|
|
- nic_interface_t *nic_iface)
|
|
-{
|
|
- struct in_addr src_addr, dst_addr,
|
|
- src_matching_addr, dst_matching_addr, netmask;
|
|
- __u8 mac_addr[6];
|
|
- int rc;
|
|
- uint16_t arp_retry;
|
|
- int status = 0;
|
|
-#define MAX_ARP_RETRY 4
|
|
-
|
|
- memset(mac_addr, 0, sizeof(mac_addr));
|
|
- memcpy(&dst_addr, &path->dst.v4_addr, sizeof(dst_addr));
|
|
- memcpy(&src_addr, nic_iface->ustack.hostaddr, sizeof(src_addr));
|
|
-
|
|
- if (nic_iface->ustack.netmask[0] | nic_iface->ustack.netmask[1])
|
|
- memcpy(&netmask.s_addr, nic_iface->ustack.netmask,
|
|
- sizeof(src_addr));
|
|
- else
|
|
- netmask.s_addr = calculate_default_netmask(dst_addr.s_addr);
|
|
-
|
|
- src_matching_addr.s_addr = src_addr.s_addr & netmask.s_addr;
|
|
- dst_matching_addr.s_addr = dst_addr.s_addr & netmask.s_addr;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: src=%s", nic->log_name, inet_ntoa(src_addr));
|
|
- LOG_DEBUG(PFX "%s: dst=%s", nic->log_name, inet_ntoa(dst_addr));
|
|
- LOG_DEBUG(PFX "%s: nm=%s", nic->log_name, inet_ntoa(netmask));
|
|
- if (src_matching_addr.s_addr != dst_matching_addr.s_addr) {
|
|
- /* If there is an assigned gateway address then use it
|
|
- * if the source address doesn't match */
|
|
- if (nic_iface->ustack.default_route_addr[0] |
|
|
- nic_iface->ustack.default_route_addr[1]) {
|
|
- memcpy(&dst_addr,
|
|
- &nic_iface->ustack.default_route_addr,
|
|
- sizeof(dst_addr));
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: no default route address",
|
|
- nic->log_name);
|
|
- }
|
|
- }
|
|
- arp_retry = 0;
|
|
-
|
|
- rc = uip_lookup_arp_entry(dst_addr.s_addr, mac_addr);
|
|
- if (rc != 0) {
|
|
- while ((arp_retry < MAX_ARP_RETRY) && (event_loop_stop == 0)) {
|
|
- char *dst_addr_str;
|
|
- int count;
|
|
- struct timespec ts;
|
|
- struct timeval tp;
|
|
- struct timeval tp_abs;
|
|
-
|
|
- dst_addr_str = inet_ntoa(dst_addr);
|
|
-
|
|
- LOG_INFO(PFX "%s: Didn't find IPv4: '%s' in ARP table",
|
|
- nic->log_name, dst_addr_str);
|
|
- rc = cnic_arp_send(nic, nic_iface, fd,
|
|
- mac_addr,
|
|
- dst_addr.s_addr, dst_addr_str);
|
|
- if (rc != 0) {
|
|
- status = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- for (count = 0; count < 8; count++) {
|
|
- /* Convert from timeval to timespec */
|
|
- rc = gettimeofday(&tp, NULL);
|
|
-
|
|
- timeradd(&tp, &tp_wait, &tp_abs);
|
|
-
|
|
- ts.tv_sec = tp_abs.tv_sec;
|
|
- ts.tv_nsec = tp_abs.tv_usec * 1000;
|
|
-
|
|
- /* Wait 1s for if_down */
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- rc = pthread_cond_timedwait
|
|
- (&nic->nl_process_if_down_cond,
|
|
- &nic->nl_process_mutex, &ts);
|
|
-
|
|
- if (rc == ETIMEDOUT) {
|
|
- pthread_mutex_unlock
|
|
- (&nic->nl_process_mutex);
|
|
-
|
|
- rc = uip_lookup_arp_entry(dst_addr.
|
|
- s_addr,
|
|
- mac_addr);
|
|
- if (rc == 0)
|
|
- goto done;
|
|
- } else {
|
|
- nic->nl_process_if_down = 0;
|
|
- pthread_mutex_unlock
|
|
- (&nic->nl_process_mutex);
|
|
-
|
|
- arp_retry = MAX_ARP_RETRY;
|
|
- goto done;
|
|
-
|
|
- }
|
|
- }
|
|
-
|
|
- arp_retry++;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
-
|
|
- if (arp_retry >= MAX_ARP_RETRY) {
|
|
- status = -EIO;
|
|
- rc = -EIO;
|
|
- }
|
|
-
|
|
- if (ev) {
|
|
- cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
|
|
- nic_iface, status, AF_INET);
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * cnic_handle_ipv6_iscsi_path_req() - This function will handle the IPv4
|
|
- * path req calls the bnx2i kernel module
|
|
- * @param nic - The nic the message is directed towards
|
|
- * @param fd - The file descriptor to be used to extract the private data
|
|
- * @param ev - The iscsi_uevent
|
|
- * @param buf - The private message buffer
|
|
- */
|
|
-int cnic_handle_ipv6_iscsi_path_req(nic_t *nic, int fd,
|
|
- struct iscsi_uevent *ev,
|
|
- struct iscsi_path *path,
|
|
- nic_interface_t *nic_iface)
|
|
-{
|
|
- __u8 mac_addr[6];
|
|
- int rc, i;
|
|
- uint16_t neighbor_retry;
|
|
- int status = 0;
|
|
- char addr_dst_str[INET6_ADDRSTRLEN];
|
|
- struct in6_addr src_addr, dst_addr,
|
|
- src_matching_addr, dst_matching_addr, netmask;
|
|
- struct in6_addr *addr;
|
|
- struct ndpc_reqptr req_ptr;
|
|
-
|
|
- memset(mac_addr, 0, sizeof(mac_addr));
|
|
-
|
|
- inet_ntop(AF_INET6, &path->dst.v6_addr,
|
|
- addr_dst_str, sizeof(addr_dst_str));
|
|
-
|
|
- /* Depending on the IPv6 address of the target we will need to
|
|
- * determine whether we use the assigned IPv6 address or the
|
|
- * link local IPv6 address */
|
|
- memcpy(&dst_addr, &path->dst.v6_addr, sizeof(struct in6_addr));
|
|
- if (ndpc_request(&nic_iface->ustack, &dst_addr,
|
|
- &rc, CHECK_LINK_LOCAL_ADDR)) {
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- LOG_DEBUG(PFX "Check LL failed");
|
|
- goto done;
|
|
- }
|
|
- if (rc) {
|
|
- LOG_DEBUG(PFX "Use LL");
|
|
- /* Get link local IPv6 address */
|
|
- addr = (struct in6_addr *)&nic_iface->ustack.linklocal6;
|
|
- } else {
|
|
- LOG_DEBUG(PFX "Use Best matched");
|
|
- if (ndpc_request(&nic_iface->ustack,
|
|
- &dst_addr,
|
|
- &addr, GET_HOST_ADDR)) {
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- LOG_DEBUG(PFX "Use Best matched failed");
|
|
- goto done;
|
|
- }
|
|
- if (addr == NULL) {
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- LOG_DEBUG(PFX "No Best matched found");
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- /* Got the best matched src IP address */
|
|
- memcpy(&src_addr, addr, sizeof(struct in6_addr));
|
|
-
|
|
- if (nic_iface->ustack.netmask6[0] | nic_iface->ustack.netmask6[1] |
|
|
- nic_iface->ustack.netmask6[2] | nic_iface->ustack.netmask6[3] |
|
|
- nic_iface->ustack.netmask6[4] | nic_iface->ustack.netmask6[5] |
|
|
- nic_iface->ustack.netmask6[6] | nic_iface->ustack.netmask6[7])
|
|
- memcpy(&netmask.s6_addr, nic_iface->ustack.netmask6,
|
|
- sizeof(struct in6_addr));
|
|
- else
|
|
- memcpy(&netmask.s6_addr, all_zeroes_addr6,
|
|
- sizeof(struct in6_addr));
|
|
-
|
|
- inet_ntop(AF_INET6, &src_addr.s6_addr16, addr_dst_str,
|
|
- sizeof(addr_dst_str));
|
|
- LOG_DEBUG(PFX "src IP addr %s", addr_dst_str);
|
|
- inet_ntop(AF_INET6, &dst_addr.s6_addr16, addr_dst_str,
|
|
- sizeof(addr_dst_str));
|
|
- LOG_DEBUG(PFX "dst IP addr %s", addr_dst_str);
|
|
- inet_ntop(AF_INET6, &netmask.s6_addr16, addr_dst_str,
|
|
- sizeof(addr_dst_str));
|
|
- LOG_DEBUG(PFX "prefix mask %s", addr_dst_str);
|
|
-
|
|
- for (i = 0; i < 4; i++) {
|
|
- src_matching_addr.s6_addr32[i] = src_addr.s6_addr32[i] &
|
|
- netmask.s6_addr32[i];
|
|
- dst_matching_addr.s6_addr32[i] = dst_addr.s6_addr32[i] &
|
|
- netmask.s6_addr32[i];
|
|
- if (src_matching_addr.s6_addr32[i] !=
|
|
- dst_matching_addr.s6_addr32[i]) {
|
|
- /* No match with the prefix mask, use default route */
|
|
- if (memcmp(nic_iface->ustack.default_route_addr6,
|
|
- all_zeroes_addr6, sizeof(*addr))) {
|
|
- memcpy(&dst_addr,
|
|
- nic_iface->ustack.default_route_addr6,
|
|
- sizeof(dst_addr));
|
|
- inet_ntop(AF_INET6, &dst_addr.s6_addr16,
|
|
- addr_dst_str, sizeof(addr_dst_str));
|
|
- LOG_DEBUG(PFX "Use default router IP addr %s",
|
|
- addr_dst_str);
|
|
- break;
|
|
- } else {
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
-#define MAX_ARP_RETRY 4
|
|
- neighbor_retry = 0;
|
|
-
|
|
- req_ptr.eth = (void *)mac_addr;
|
|
- req_ptr.ipv6 = (void *)&dst_addr;
|
|
- if (ndpc_request(&nic_iface->ustack, &req_ptr, &rc, CHECK_ARP_TABLE)) {
|
|
- /* ndpc request failed, skip neighbor solicit send */
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- goto done;
|
|
- }
|
|
- if (!rc) {
|
|
- inet_ntop(AF_INET6, &dst_addr.s6_addr16,
|
|
- addr_dst_str, sizeof(addr_dst_str));
|
|
- LOG_DEBUG(PFX
|
|
- "%s: Preparing to send IPv6 neighbor solicitation "
|
|
- "to dst: '%s'", nic->log_name, addr_dst_str);
|
|
- while ((neighbor_retry < MAX_ARP_RETRY)
|
|
- && (event_loop_stop == 0)) {
|
|
- int count;
|
|
- struct timespec ts;
|
|
- struct timeval tp;
|
|
- struct timeval tp_abs;
|
|
-
|
|
- LOG_INFO(PFX "%s: Didn't find IPv6: '%s'\n",
|
|
- nic->log_name, addr_dst_str);
|
|
-
|
|
- rc = cnic_neigh_soliciation_send(nic, nic_iface, fd,
|
|
- mac_addr,
|
|
- &dst_addr,
|
|
- addr_dst_str);
|
|
- if (rc != 0) {
|
|
- status = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- for (count = 0; count < 8; count++) {
|
|
- /* Convert from timeval to timespec */
|
|
- rc = gettimeofday(&tp, NULL);
|
|
-
|
|
- timeradd(&tp, &tp_wait, &tp_abs);
|
|
-
|
|
- ts.tv_sec = tp_abs.tv_sec;
|
|
- ts.tv_nsec = tp_abs.tv_usec * 1000;
|
|
-
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- rc = pthread_cond_timedwait
|
|
- (&nic->nl_process_if_down_cond,
|
|
- &nic->nl_process_mutex, &ts);
|
|
-
|
|
- if (rc == ETIMEDOUT) {
|
|
- pthread_mutex_unlock
|
|
- (&nic->nl_process_mutex);
|
|
-
|
|
- req_ptr.eth = (void *)mac_addr;
|
|
- req_ptr.ipv6 = (void *)&dst_addr;
|
|
- if (ndpc_request
|
|
- (&nic_iface->ustack, &req_ptr, &rc,
|
|
- CHECK_ARP_TABLE)) {
|
|
- /* ndpc request failed,
|
|
- force retry */
|
|
- rc = 0;
|
|
- }
|
|
- if (rc)
|
|
- goto done;
|
|
- } else {
|
|
- nic->nl_process_if_down = 0;
|
|
- pthread_mutex_unlock
|
|
- (&nic->nl_process_mutex);
|
|
-
|
|
- neighbor_retry = MAX_ARP_RETRY;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
- neighbor_retry++;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
- if (neighbor_retry >= MAX_ARP_RETRY) {
|
|
- status = -EIO;
|
|
- rc = -EIO;
|
|
- }
|
|
-
|
|
- if (ev) {
|
|
- cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
|
|
- nic_iface, status, AF_INET6);
|
|
- }
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * cnic_handle_iscsi_path_req() - This function will handle the path req calls
|
|
- * the bnx2i kernel module
|
|
- * @param nic - The nic the message is directed towards
|
|
- * @param fd - The file descriptor to be used to extract the private data
|
|
- * @param ev - The iscsi_uevent
|
|
- * @param path - The private message buffer
|
|
- * @param nic_iface - The nic_iface to use for this connection request
|
|
- */
|
|
-int cnic_handle_iscsi_path_req(nic_t *nic, int fd, struct iscsi_uevent *ev,
|
|
- struct iscsi_path *path,
|
|
- nic_interface_t *nic_iface)
|
|
-{
|
|
-
|
|
- LOG_DEBUG(PFX "%s: Netlink message with VLAN ID: %d, path MTU: %d "
|
|
- "minor: %d ip_addr_len: %d",
|
|
- nic->log_name, path->vlan_id, path->pmtu, 0 /* TODO FIX */ ,
|
|
- path->ip_addr_len);
|
|
-
|
|
- if (path->ip_addr_len == 4)
|
|
- return cnic_handle_ipv4_iscsi_path_req(nic, fd, ev, path,
|
|
- nic_iface);
|
|
- else if (path->ip_addr_len == 16)
|
|
- return cnic_handle_ipv6_iscsi_path_req(nic, fd, ev, path,
|
|
- nic_iface);
|
|
- else {
|
|
- LOG_DEBUG(PFX "%s: unknown ip_addr_len: %d size dropping ",
|
|
- nic->log_name, path->ip_addr_len);
|
|
- return -EIO;
|
|
- }
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/libs/cnic.h b/iscsiuio/src/unix/libs/cnic.h
|
|
deleted file mode 100644
|
|
index c86595c..0000000
|
|
--- a/iscsiuio/src/unix/libs/cnic.h
|
|
+++ /dev/null
|
|
@@ -1,57 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * cnic.h - CNIC UIO uIP user space stack
|
|
- *
|
|
- */
|
|
-#ifndef __CNIC_NL_H__
|
|
-#define __CNIC_NL_H__
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants shared between the bnx2 and bnx2x modules
|
|
- ******************************************************************************/
|
|
-extern const char bnx2i_library_transport_name[];
|
|
-extern const size_t bnx2i_library_transport_name_size;
|
|
-extern const char qedi_library_transport_name[];
|
|
-extern const size_t qedi_library_transport_name_size;
|
|
-
|
|
-int cnic_nl_open();
|
|
-void cnic_nl_close();
|
|
-
|
|
-int cnic_handle_iscsi_path_req(nic_t *nic, int, struct iscsi_uevent *,
|
|
- struct iscsi_path *path,
|
|
- nic_interface_t *nic_iface);
|
|
-
|
|
-#endif /* __CNIC_NL_H__ */
|
|
diff --git a/iscsiuio/src/unix/libs/qedi.c b/iscsiuio/src/unix/libs/qedi.c
|
|
deleted file mode 100644
|
|
index 1af8d1b..0000000
|
|
--- a/iscsiuio/src/unix/libs/qedi.c
|
|
+++ /dev/null
|
|
@@ -1,1195 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2016, Cavium Inc.
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * qedi.c - qedi user space driver
|
|
- * This file handles different qedi NIC operations,
|
|
- * qedi_open - initializes all hardware resources under NIC device
|
|
- * qedi_close - closes the NIC device
|
|
- * qedi_read - reads data to the hardware
|
|
- * qedi_write - writes data to the hardware
|
|
- * qedi_start_xmit - sends a pkt of data on NIC device
|
|
- * qedi_get_tx_pkt - gets a Tx pkt from NIC
|
|
- * qedi_clear_tx_intr - clears the Tx interrupt
|
|
- * NOTE: nic_t is used as NIC device,
|
|
- * qedi is not attached to netdev hence it is not mandatory
|
|
- * for netdev to be upd
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <linux/types.h>
|
|
-#include <linux/sockios.h>
|
|
-#include <linux/netlink.h>
|
|
-#include <sys/mman.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/user.h>
|
|
-#include <fcntl.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/sysmacros.h>
|
|
-
|
|
-#include "config.h"
|
|
-
|
|
-#include "build_date.h"
|
|
-#include "bnx2x.h"
|
|
-#include "qedi.h"
|
|
-#include "cnic.h"
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_id.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-
|
|
-#define PFX "qedi "
|
|
-
|
|
-extern int nl_sock;
|
|
-
|
|
-static pthread_mutex_t host_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
-
|
|
-/* Foward struct declarations */
|
|
-struct nic_ops qedi_op;
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC Library Strings
|
|
- ******************************************************************************/
|
|
-static const char library_name[] = "qedi";
|
|
-static const char library_version[] = PACKAGE_VERSION;
|
|
-static const char library_uio_name[] = "qedi_uio";
|
|
-
|
|
-/* The name that should be returned from /sys/class/uio/uio0/name */
|
|
-static const char cnic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
|
|
-static const char qedi_uio_sysfs_name[] = "qedi_uio";
|
|
-static const char qedi_host_mac_template[] =
|
|
- "/sys/class/iscsi_host/host%i/hwaddress";
|
|
-
|
|
-struct qedi_driver_version qedi_version = {
|
|
- QEDI_UNKNOWN_MAJOR_VERSION,
|
|
- QEDI_UNKNOWN_MINOR_VERSION,
|
|
- QEDI_UNKNOWN_SUB_MINOR_VERSION,
|
|
-};
|
|
-
|
|
-static int qedi_clear_tx_intr(nic_t *nic);
|
|
-
|
|
-/*******************************************************************************
|
|
- * QEDI Library Functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * qedi_get_library_name() - Used to get the name of this NIC library
|
|
- * @param name - This function will return the pointer to this NIC
|
|
- * library name
|
|
- * @param name_size
|
|
- */
|
|
-static void qedi_get_library_name(char **name, size_t *name_size)
|
|
-{
|
|
- *name = (char *)library_name;
|
|
- *name_size = sizeof(library_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_library_version() - Used to get the version string of this
|
|
- * NIC library
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library version string
|
|
- * @param version_size - This will be set with the version size
|
|
- */
|
|
-static void qedi_get_library_version(char **version, size_t *version_size)
|
|
-{
|
|
- *version = (char *)library_version;
|
|
- *version_size = sizeof(library_version);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_build_date() - Used to get the build date string of this library
|
|
- * @param version - This function will return the pointer to this NIC
|
|
- * library build date string
|
|
- * @param version_size - This will be set with the build date string size
|
|
- */
|
|
-static void qedi_get_build_date(char **build, size_t *build_size)
|
|
-{
|
|
- *build = (char *)build_date;
|
|
- *build_size = sizeof(build_date);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_transport_name() - Used to get the transport name associated
|
|
- * with this this NIC library
|
|
- * @param transport_name - This function will return the pointer to this NIC
|
|
- * library's associated transport string
|
|
- * @param transport_name_size - This will be set with the transport name size
|
|
- */
|
|
-static void qedi_get_transport_name(char **transport_name,
|
|
- size_t *transport_name_size)
|
|
-{
|
|
- *transport_name = (char *)qedi_library_transport_name;
|
|
- *transport_name_size = qedi_library_transport_name_size;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_uio_name() - Used to get the uio name associated with this this
|
|
- * NIC library
|
|
- * @param uio_name - This function will return the pointer to this NIC
|
|
- * library's associated uio string
|
|
- * @param transport_name_size - This will be set with the uio name size
|
|
- */
|
|
-static void qedi_get_uio_name(char **uio_name, size_t *uio_name_size)
|
|
-{
|
|
- *uio_name = (char *)library_uio_name;
|
|
- *uio_name_size = sizeof(library_uio_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_ops() - Used to get the NIC library op table
|
|
- * @param op - The op table of this NIC library
|
|
- */
|
|
-struct nic_ops *qedi_get_ops()
|
|
-{
|
|
- return &qedi_op;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * qedi Utility Functions
|
|
- ******************************************************************************/
|
|
-/*******************************************************************************
|
|
- * Utility Functions Used to read register from the qedi device
|
|
- ******************************************************************************/
|
|
-static void qedi_set_drv_version_unknown(qedi_t *bp)
|
|
-{
|
|
- bp->version.major = QEDI_UNKNOWN_MAJOR_VERSION;
|
|
- bp->version.minor = QEDI_UNKNOWN_MINOR_VERSION;
|
|
- bp->version.sub_minor = QEDI_UNKNOWN_SUB_MINOR_VERSION;
|
|
-}
|
|
-
|
|
-/* Return: 1 = Unknown, 0 = Known */
|
|
-static int qedi_is_drv_version_unknown(struct qedi_driver_version *version)
|
|
-{
|
|
- if ((version->major == (uint16_t)QEDI_UNKNOWN_MAJOR_VERSION) &&
|
|
- (version->minor == (uint16_t)QEDI_UNKNOWN_MINOR_VERSION) &&
|
|
- (version->sub_minor == (uint16_t)QEDI_UNKNOWN_SUB_MINOR_VERSION)) {
|
|
- return 1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_drv_version() - Used to determine the driver version
|
|
- * @param bp - Device used to determine qedi driver version
|
|
- */
|
|
-static int qedi_get_drv_version(qedi_t *bp)
|
|
-{
|
|
- nic_t *nic = bp->parent;
|
|
-
|
|
- /*
|
|
- * CAPABILITIES: Get the iscsi driver version from qedi
|
|
- * This may be obtained from sysfs
|
|
- */
|
|
- LOG_INFO(PFX "%s: qedi driver using version %d.%d.%d",
|
|
- nic->log_name,
|
|
- bp->version.major, bp->version.minor, bp->version.sub_minor);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/******************************************************************************/
|
|
-
|
|
-/**
|
|
- * qedi_get_chip_id() - Used to retrieve the chip ID from the nic
|
|
- * @param dev - Device used to determin NIC type
|
|
- * @return Chip ID read from the MISC ID register
|
|
- */
|
|
-static int qedi_get_chip_id(qedi_t *bp)
|
|
-{
|
|
- /* int val, id; */
|
|
-
|
|
- /* Get the chip revision id and number. */
|
|
- /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
|
|
- /*
|
|
- * CAPABILITIES: Get the CHIP info from qedi through sysfs or uio struct.
|
|
- */
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_uio_verify()
|
|
- *
|
|
- */
|
|
-static int qedi_uio_verify(nic_t *nic)
|
|
-{
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(cnic_uio_sysfs_name_tempate) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Build the path to determine uio name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- cnic_uio_sysfs_name_tempate, nic->uio_minor);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n')
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- if (strncmp(raw, qedi_uio_sysfs_name,
|
|
- sizeof(qedi_uio_sysfs_name)) != 0) {
|
|
- LOG_ERR(PFX "%s: uio names not equal: expecting %s got %s from %s",
|
|
- nic->log_name, qedi_uio_sysfs_name, raw, temp_path);
|
|
- rc = -EIO;
|
|
- }
|
|
-
|
|
- free(raw);
|
|
-
|
|
- LOG_INFO(PFX "%s: Verified is a qedi_uio device", nic->log_name);
|
|
-
|
|
-error:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int qedi_get_mac_addr(qedi_t *bp)
|
|
-{
|
|
- nic_t *nic = bp->parent;
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(qedi_host_mac_template) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Build the path to determine mac address */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- qedi_host_mac_template, nic->host_no);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n')
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- rc = sscanf(raw, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
- (uint32_t *)&nic->mac_addr[0], (uint32_t *)&nic->mac_addr[1],
|
|
- (uint32_t *)&nic->mac_addr[2], (uint32_t *)&nic->mac_addr[3],
|
|
- (uint32_t *)&nic->mac_addr[4], (uint32_t *)&nic->mac_addr[5]);
|
|
- if (rc != 1) {
|
|
- LOG_WARN(PFX "%s: Could not parse mac_addr",
|
|
- nic->log_name);
|
|
- rc = -ENODEV;
|
|
- goto error;
|
|
- }
|
|
-
|
|
-error:
|
|
- if (raw)
|
|
- free(raw);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * qedi Utility Functions to get to the hardware consumer indexes
|
|
- ******************************************************************************/
|
|
-
|
|
-static __u32 qedi_get_rx(qedi_t *bp)
|
|
-{
|
|
- return ((struct qedi_uio_ctrl *)bp->uctrl_map)->host_rx_cons;
|
|
-}
|
|
-
|
|
-static __u32 qedi_get_tx(qedi_t *bp)
|
|
-{
|
|
- return ((struct qedi_uio_ctrl *)bp->uctrl_map)->hw_tx_cons;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_free() - Used to free a qedi structure
|
|
- */
|
|
-static void qedi_free(nic_t *nic)
|
|
-{
|
|
- if (nic->priv)
|
|
- free(nic->priv);
|
|
- nic->priv = NULL;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_alloc() - Used to allocate a qedi structure
|
|
- */
|
|
-static qedi_t *qedi_alloc(nic_t *nic)
|
|
-{
|
|
- qedi_t *bp = malloc(sizeof(*bp));
|
|
-
|
|
- if (!bp) {
|
|
- LOG_ERR(PFX "%s: Could not allocate QEDI space",
|
|
- nic->log_name);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /* Clear out the CNIC contents */
|
|
- memset(bp, 0, sizeof(*bp));
|
|
-
|
|
- bp->parent = nic;
|
|
- nic->priv = (void *)bp;
|
|
- get_iscsi_transport_handle(nic, &nic->transport_handle);
|
|
- qedi_set_drv_version_unknown(bp);
|
|
-
|
|
- return bp;
|
|
-}
|
|
-
|
|
-int uio_get_map_offset(nic_t *nic, uint8_t map, uint32_t *offset)
|
|
-{
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- ssize_t elements_read;
|
|
- char temp_path[sizeof(UIO_OFFSET_TMPL) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Capture RX buffer size */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- UIO_OFFSET_TMPL, nic->uio_minor, map);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- elements_read = sscanf(raw, "0x%x", offset);
|
|
- if (elements_read != 1) {
|
|
- LOG_ERR(PFX "%s: Couldn't get the offset from %s",
|
|
- nic->log_name, temp_path);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = 0;
|
|
-error:
|
|
- if (raw)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int uio_get_map_info(nic_t *nic, uint8_t map, char *attr, uint32_t *val)
|
|
-{
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- ssize_t elements_read;
|
|
- char temp_path[sizeof(UIO_ATTR_TMPL) + 8];
|
|
- int rc = 0;
|
|
-
|
|
- /* Capture RX buffer size */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- UIO_ATTR_TMPL, nic->uio_minor, map, attr);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- elements_read = sscanf(raw, "0x%x", val);
|
|
- if (elements_read != 1) {
|
|
- LOG_ERR(PFX "%s: Couldn't get the offset from %s",
|
|
- nic->log_name, temp_path);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = 0;
|
|
-error:
|
|
- if (raw)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_open() - This will initialize all the hardware resources underneath
|
|
- * a struct cnic_uio device
|
|
- * @param dev - The struct cnic_uio device to attach the hardware with
|
|
- * @return 0 on success, on failure a errno will be returned
|
|
- */
|
|
-static int qedi_open(nic_t *nic)
|
|
-{
|
|
- qedi_t *bp = NULL;
|
|
- struct stat uio_stat;
|
|
- int i, rc;
|
|
- size_t count;
|
|
- uint32_t bus;
|
|
- uint32_t slot;
|
|
- uint32_t func;
|
|
- uint32_t offset;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (!nic) {
|
|
- LOG_ERR(PFX "nic == NULL");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((nic->priv) != NULL &&
|
|
- (((qedi_t *)(nic->priv))->flags & QEDI_OPENED)) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (nic->host_no == INVALID_HOST_NO) {
|
|
- rc = sscanf(nic->config_device_name, "host%d", &nic->host_no);
|
|
- if (rc != 1) {
|
|
- LOG_WARN(PFX "%s: Could not parse for host number",
|
|
- nic->config_device_name);
|
|
- rc = -ENODEV;
|
|
- goto open_error;
|
|
- }
|
|
- }
|
|
-
|
|
- bp = qedi_alloc(nic);
|
|
- if (!bp)
|
|
- return -ENOMEM;
|
|
-
|
|
- if (qedi_is_drv_version_unknown(&qedi_version)) {
|
|
- /* If version is unknown, go read from ethtool */
|
|
- rc = qedi_get_drv_version(bp);
|
|
- if (rc)
|
|
- goto open_error;
|
|
- } else {
|
|
- /* Version is not unknown, just use it */
|
|
- qedi_version.major = bp->version.major;
|
|
- qedi_version.minor = bp->version.minor;
|
|
- qedi_version.sub_minor = bp->version.sub_minor;
|
|
- }
|
|
-
|
|
- count = 0;
|
|
- while ((nic->fd < 0) && count < 15) {
|
|
- /* udev might not have created the file yet */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- sleep(1);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic->fd = open(nic->uio_device_name, O_RDWR | O_NONBLOCK);
|
|
- if (nic->fd != INVALID_FD) {
|
|
- LOG_ERR(PFX "%s: uio device has been brought up via pid: %d on fd: %d",
|
|
- nic->uio_device_name, getpid(), nic->fd);
|
|
-
|
|
- rc = qedi_uio_verify(nic);
|
|
- if (rc != 0)
|
|
- continue;
|
|
-
|
|
- break;
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: Could not open device: %s, [%s]",
|
|
- nic->log_name, nic->uio_device_name,
|
|
- strerror(errno));
|
|
-
|
|
- manually_trigger_uio_event(nic, nic->uio_minor);
|
|
-
|
|
- /* udev might not have created the file yet */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- sleep(1);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- count++;
|
|
- }
|
|
- }
|
|
- if (nic->fd == INVALID_FD) {
|
|
- LOG_ERR(PFX "%s: Could not open device: %s, [%s]",
|
|
- nic->log_name, nic->uio_device_name,
|
|
- strerror(errno));
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
- if (fstat(nic->fd, &uio_stat) < 0) {
|
|
- LOG_ERR(PFX "%s: Could not fstat device", nic->log_name);
|
|
- rc = -ENODEV;
|
|
- goto open_error;
|
|
- }
|
|
- nic->uio_minor = minor(uio_stat.st_rdev);
|
|
-
|
|
- /*
|
|
- * CAPABILITIES: acquire the rx buffer size and rx ring size from qedi
|
|
- */
|
|
-
|
|
- bp->rx_ring_size = RX_RING_SIZE;
|
|
- bp->rx_buffer_size = PKT_BUF_SIZE;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: using rx ring size: %d, rx buffer size: %d",
|
|
- nic->log_name, bp->rx_ring_size, bp->rx_buffer_size);
|
|
-
|
|
- /* Determine the number of UIO events that have already occurred */
|
|
- rc = detemine_initial_uio_events(nic, &nic->intr_count);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "Could not get the no. of initial UIO events");
|
|
- nic->intr_count = 0;
|
|
- }
|
|
-
|
|
- /* Allocate space for rx pkt ring */
|
|
- bp->rx_pkt_ring = malloc(sizeof(void *) * bp->rx_ring_size);
|
|
- if (!bp->rx_pkt_ring) {
|
|
- LOG_ERR(PFX "%s: Could not allocate space for rx_pkt_ring",
|
|
- nic->log_name);
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Map the uio struct and packet buffer
|
|
- */
|
|
- offset = 0;
|
|
- rc = uio_get_map_info(nic, QEDI_UCTRL_MAP_REG, "size", &offset);
|
|
- if (rc) {
|
|
- LOG_INFO(PFX "Failed to get the map size rc=%d", rc);
|
|
- goto open_error;
|
|
- }
|
|
- LOG_INFO(PFX "uctrl map size=%u", offset);
|
|
-
|
|
- offset = 0;
|
|
- rc = uio_get_map_info(nic, QEDI_RING_MAP_REG, "size", &offset);
|
|
- if (rc) {
|
|
- LOG_INFO(PFX "Failed to get the map size rc=%d", rc);
|
|
- goto open_error;
|
|
- }
|
|
- LOG_INFO(PFX "ring map size=%u", offset);
|
|
-
|
|
- offset = 0;
|
|
- rc = uio_get_map_info(nic, QEDI_BUF_MAP_REG, "size", &offset);
|
|
- if (rc) {
|
|
- LOG_INFO(PFX "Failed to get the map size rc=%d", rc);
|
|
- goto open_error;
|
|
- }
|
|
- LOG_INFO(PFX "buf map size=%u", offset);
|
|
-
|
|
- offset = 0;
|
|
- rc = uio_get_map_offset(nic, QEDI_UCTRL_MAP_REG, &offset);
|
|
- if (rc) {
|
|
- LOG_INFO(PFX "Failed to get the map offset rc=%d", rc);
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->uctrl_map = mmap(NULL, sizeof(struct qedi_uio_ctrl),
|
|
- PROT_READ | PROT_WRITE,
|
|
- MAP_SHARED | MAP_LOCKED,
|
|
- nic->fd, (off_t)0);
|
|
- if (bp->uctrl_map == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap uio ctrl struct: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->uctrl_map = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->uctrl_map_offset = offset;
|
|
- bp->uctrl_map += offset;
|
|
-
|
|
- bp->rx_comp_ring = mmap(NULL, nic->page_size,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,
|
|
- nic->fd, (off_t)nic->page_size);
|
|
- if (bp->rx_comp_ring == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap rx_comp_ring: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->rx_comp_ring = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- bp->bufs = mmap(NULL, (bp->rx_ring_size + 1) * bp->rx_buffer_size,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,
|
|
- nic->fd, (off_t)2 * nic->page_size);
|
|
- if (bp->bufs == MAP_FAILED) {
|
|
- LOG_INFO(PFX "%s: Could not mmap pkt buffers: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- bp->bufs = NULL;
|
|
- rc = errno;
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Get all CHIP related info from qedi
|
|
- */
|
|
- bp->chip_id = qedi_get_chip_id(bp);
|
|
- LOG_DEBUG(PFX "Chip ID: %x", bp->chip_id);
|
|
-
|
|
- rc = get_bus_slot_func_num(nic, &bus, &slot, &func);
|
|
- if (rc != 0) {
|
|
- LOG_INFO(PFX "%s: Couldn't determine bus:slot.func",
|
|
- nic->log_name);
|
|
- goto open_error;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Get all function, pfid, client_id and cid info from qedi
|
|
- */
|
|
- LOG_INFO(PFX "%s: func 0x%x, pfid 0x%x, client_id 0x%x, cid 0x%x",
|
|
- nic->log_name, bp->func, bp->pfid, bp->client_id, bp->cid);
|
|
-
|
|
- bp->get_rx_cons = qedi_get_rx;
|
|
- bp->get_tx_cons = qedi_get_tx;
|
|
- bp->tx_cons = 0;
|
|
- bp->tx_prod = 0;
|
|
- bp->tx_bd_prod = 0;
|
|
- bp->tx_pkt = bp->bufs;
|
|
- bp->rx_pkts = bp->bufs + bp->rx_buffer_size;
|
|
-
|
|
- bp->rx_index = 0;
|
|
- bp->rx_cons = 0;
|
|
- bp->rx_bd_cons = 0;
|
|
- bp->rx_prod = 127;
|
|
- bp->rx_bd_prod = bp->rx_ring_size;
|
|
-
|
|
- for (i = 0; i < bp->rx_ring_size; i++) {
|
|
- void *ptr = bp->bufs + (bp->rx_buffer_size * (i + 1));
|
|
-
|
|
- bp->rx_pkt_ring[i] = ptr;
|
|
- }
|
|
-
|
|
- qedi_get_mac_addr(bp);
|
|
- LOG_INFO(PFX "%s: Using mac address: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- nic->log_name,
|
|
- nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2],
|
|
- nic->mac_addr[3], nic->mac_addr[4], nic->mac_addr[5]);
|
|
-
|
|
- qedi_get_library_name(&nic->library_name, &count);
|
|
- LOG_INFO("%s: qedi initialized", nic->log_name);
|
|
-
|
|
- bp->flags |= QEDI_OPENED;
|
|
-
|
|
- return 0;
|
|
-
|
|
-open_error:
|
|
-
|
|
- if (bp->bufs) {
|
|
- munmap(bp->bufs, (bp->rx_ring_size + 1) * bp->rx_buffer_size);
|
|
- bp->bufs = NULL;
|
|
- }
|
|
-
|
|
- if (bp->rx_comp_ring) {
|
|
- munmap(bp->rx_comp_ring, nic->page_size);
|
|
- bp->rx_comp_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->uctrl_map) {
|
|
- bp->uctrl_map -= bp->uctrl_map_offset;
|
|
- munmap(bp->uctrl_map, sizeof(struct qedi_uio_ctrl));
|
|
- bp->uctrl_map = NULL;
|
|
- }
|
|
-
|
|
- if (bp->rx_pkt_ring) {
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
- }
|
|
-
|
|
- if (nic->fd != INVALID_FD) {
|
|
- close(nic->fd);
|
|
- nic->fd = INVALID_FD;
|
|
- }
|
|
-
|
|
- qedi_free(nic);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_uio_close_resources() - Used to free resource for the NIC/CNIC
|
|
- * @param nic - NIC device to free resource
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-static int qedi_uio_close_resources(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- qedi_t *bp = (qedi_t *)nic->priv;
|
|
- int rc = 0;
|
|
-
|
|
- /* Check if there is an assoicated qedi device */
|
|
- if (!bp) {
|
|
- LOG_WARN(PFX "%s: when closing resources there is no assoicated qedi",
|
|
- nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- /* Clean up allocated memory */
|
|
-
|
|
- if (bp->rx_pkt_ring) {
|
|
- free(bp->rx_pkt_ring);
|
|
- bp->rx_pkt_ring = NULL;
|
|
- }
|
|
-
|
|
- /* Clean up mapped registers */
|
|
- if (bp->bufs) {
|
|
- rc = munmap(bp->bufs,
|
|
- (bp->rx_ring_size + 1) * bp->rx_buffer_size);
|
|
- if (rc != 0)
|
|
- LOG_ERR(PFX "%s: Couldn't unmap bufs", nic->log_name);
|
|
- bp->bufs = NULL;
|
|
- }
|
|
-
|
|
- if (bp->rx_comp_ring) {
|
|
- rc = munmap(bp->rx_comp_ring, nic->page_size);
|
|
- if (rc != 0)
|
|
- LOG_ERR(PFX "%s: Couldn't unmap ring", nic->log_name);
|
|
- bp->rx_comp_ring = NULL;
|
|
- }
|
|
-
|
|
- if (bp->uctrl_map) {
|
|
- bp->uctrl_map -= bp->uctrl_map_offset;
|
|
- rc = munmap(bp->uctrl_map, sizeof(struct qedi_uio_ctrl));
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Couldn't unmap uio ctrl",
|
|
- nic->log_name);
|
|
- }
|
|
- bp->uctrl_map = NULL;
|
|
- }
|
|
-
|
|
- if (nic->fd != INVALID_FD) {
|
|
- rc = close(nic->fd);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX
|
|
- "%s: Couldn't close uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: Closed uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- nic->fd = INVALID_FD;
|
|
- } else {
|
|
- LOG_ERR(PFX "%s: Invalid uio file descriptor: %d",
|
|
- nic->log_name, nic->fd);
|
|
- }
|
|
-
|
|
- qedi_set_drv_version_unknown(bp);
|
|
-
|
|
- LOG_INFO(PFX "%s: Closed all resources", nic->log_name);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_close() - Used to close the NIC device
|
|
- * @param nic - NIC device to close
|
|
- * @param graceful - whether to wait to close gracefully
|
|
- * @return 0 if successful, <0 if there is an error
|
|
- */
|
|
-static int qedi_close(nic_t *nic, NIC_SHUTDOWN_T graceful)
|
|
-{
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (!nic) {
|
|
- LOG_ERR(PFX "%s: nic == NULL", __func__);
|
|
- return -EINVAL;
|
|
- }
|
|
- if (!nic->priv) {
|
|
- LOG_ERR(PFX "%s: nic->priv == NULL", __func__);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "Closing NIC device: %s", nic->log_name);
|
|
-
|
|
- qedi_uio_close_resources(nic, graceful);
|
|
- qedi_free(nic);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void qedi_prepare_xmit_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct packet *pkt)
|
|
-{
|
|
- qedi_t *bp = (qedi_t *)nic->priv;
|
|
- struct uip_vlan_eth_hdr *eth_vlan = (struct uip_vlan_eth_hdr *)pkt->buf;
|
|
- struct uip_eth_hdr *eth = (struct uip_eth_hdr *)bp->tx_pkt;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: pkt->buf_size=%d tpid=0x%x", nic->log_name,
|
|
- pkt->buf_size, eth_vlan->tpid);
|
|
-
|
|
- if (eth_vlan->tpid == htons(UIP_ETHTYPE_8021Q)) {
|
|
- memcpy(bp->tx_pkt, pkt->buf, sizeof(struct uip_eth_hdr));
|
|
- eth->type = eth_vlan->type;
|
|
- pkt->buf_size -= (sizeof(struct uip_vlan_eth_hdr) -
|
|
- sizeof(struct uip_eth_hdr));
|
|
-
|
|
- LOG_DEBUG(PFX "%s: pkt->buf_size=%d type=0x%x", nic->log_name,
|
|
- pkt->buf_size, eth->type);
|
|
- LOG_DEBUG(PFX "%s: pkt->buf_size - eth_hdr_size = %d", nic->log_name,
|
|
- pkt->buf_size - sizeof(struct uip_eth_hdr));
|
|
-
|
|
- memcpy(bp->tx_pkt + sizeof(struct uip_eth_hdr),
|
|
- pkt->buf + sizeof(struct uip_vlan_eth_hdr),
|
|
- pkt->buf_size - sizeof(struct uip_eth_hdr));
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: NO VLAN pkt->buf_size=%d", nic->log_name,
|
|
- pkt->buf_size);
|
|
- memcpy(bp->tx_pkt, pkt->buf, pkt->buf_size);
|
|
- }
|
|
-
|
|
- msync(bp->tx_pkt, pkt->buf_size, MS_SYNC);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_get_tx_pkt() - This function is used to a TX packet from the NIC
|
|
- * @param nic - The NIC device to send the packet
|
|
- */
|
|
-void *qedi_get_tx_pkt(nic_t *nic)
|
|
-{
|
|
- qedi_t *bp = (qedi_t *)nic->priv;
|
|
-
|
|
- return bp->tx_pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_start_xmit() - This function is used to send a packet of data
|
|
- * @param nic - The NIC device to send the packet
|
|
- * @param len - the length of the TX packet
|
|
- *
|
|
- */
|
|
-void qedi_start_xmit(nic_t *nic, size_t len, u16_t vlan_id)
|
|
-{
|
|
- qedi_t *bp = (qedi_t *)nic->priv;
|
|
- uint8_t *ubuf;
|
|
- struct iscsi_uevent *ev;
|
|
- struct iscsi_path *path_data;
|
|
- struct qedi_uio_ctrl *uctrl;
|
|
- int rc = 0;
|
|
- uint16_t buflen;
|
|
-
|
|
- uctrl = (struct qedi_uio_ctrl *)bp->uctrl_map;
|
|
-
|
|
- buflen = sizeof(struct iscsi_uevent) + sizeof(struct iscsi_path);
|
|
- ubuf = calloc(1, NLMSG_SPACE(buflen));
|
|
- if (!ubuf) {
|
|
- LOG_ERR(PFX "%s: alloc failed for uevent buf", __func__);
|
|
- return;
|
|
- }
|
|
-
|
|
- memset(ubuf, 0, NLMSG_SPACE(buflen));
|
|
-
|
|
- /* prepare the iscsi_uevent buffer */
|
|
- ev = (struct iscsi_uevent *)ubuf;
|
|
- ev->type = ISCSI_UEVENT_PATH_UPDATE;
|
|
- ev->transport_handle = nic->transport_handle;
|
|
- ev->u.set_path.host_no = nic->host_no;
|
|
-
|
|
- /* Prepare the iscsi_path buffer */
|
|
- path_data = (struct iscsi_path *)(ubuf + sizeof(struct iscsi_uevent));
|
|
- path_data->handle = QEDI_PATH_HANDLE;
|
|
- path_data->vlan_id = vlan_id;
|
|
- uctrl->host_tx_pkt_len = len;
|
|
- LOG_DEBUG(PFX "%s: host_no:%d vlan_id=%d, tx_pkt_len=%d",
|
|
- nic->log_name, ev->u.set_path.host_no, path_data->vlan_id, uctrl->host_tx_pkt_len);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: ACQUIRE HOST MUTEX", nic->log_name);
|
|
- pthread_mutex_lock(&host_mutex);
|
|
- rc = __kipc_call(nl_sock, ev, buflen);
|
|
- if (rc > 0) {
|
|
- bp->tx_prod++;
|
|
- uctrl->host_tx_prod++;
|
|
- LOG_DEBUG(PFX "%s: bp->tx_prod: %d, uctrl->host_tx_prod=%d",
|
|
- nic->log_name, bp->tx_prod, uctrl->host_tx_prod);
|
|
-
|
|
- msync(uctrl, sizeof(struct qedi_uio_ctrl), MS_SYNC);
|
|
- LOG_PACKET(PFX "%s: sent %d bytes using bp->tx_prod: %d",
|
|
- nic->log_name, len, bp->tx_prod);
|
|
- } else {
|
|
- LOG_ERR(PFX "Pkt transmission failed: %d", rc);
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: RELEASE HOST MUTEX", nic->log_name);
|
|
- pthread_mutex_unlock(&host_mutex);
|
|
- free(ubuf);
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_write() - Used to write the data to the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data to be sent on the wire
|
|
- * @return 0 if successful, <0 if failed
|
|
- */
|
|
-int qedi_write(nic_t *nic, nic_interface_t *nic_iface, packet_t *pkt)
|
|
-{
|
|
- qedi_t *bp;
|
|
- struct uip_stack *uip;
|
|
- int i = 0;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (!nic || !nic_iface || !pkt) {
|
|
- LOG_ERR(PFX "%s: qedi_write() nic == 0x%p || nic_iface == 0x%p || pkt == 0x%x",
|
|
- nic, nic_iface, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
- bp = (qedi_t *)nic->priv;
|
|
- uip = &nic_iface->ustack;
|
|
-
|
|
- if (pkt->buf_size == 0) {
|
|
- LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Try to wait for a TX completion */
|
|
- for (i = 0; i < 15; i++) {
|
|
- struct timespec sleep_req = {.tv_sec = 0, .tv_nsec = 5000000 },
|
|
- sleep_rem;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: host:%d - calling clear_tx_intr from qedi_write",
|
|
- nic->log_name, nic->host_no);
|
|
- if (qedi_clear_tx_intr(nic) == 0)
|
|
- break;
|
|
-
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: host:%d - try getting xmit mutex",
|
|
- nic->log_name, nic->host_no);
|
|
- if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
|
|
- LOG_DEBUG(PFX "%s: Dropped previous transmitted packet",
|
|
- nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- qedi_prepare_xmit_packet(nic, nic_iface, pkt);
|
|
- qedi_start_xmit(nic, pkt->buf_size,
|
|
- (nic_iface->vlan_priority << 12) |
|
|
- nic_iface->vlan_id);
|
|
-
|
|
- /* bump up the tx stats */
|
|
- nic->stats.tx.packets++;
|
|
- nic->stats.tx.bytes += uip->uip_len;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: transmitted %d bytes dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: host:%d - releasing xmit mutex",
|
|
- nic->log_name, nic->host_no);
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * qedi_read() - Used to read the data from the hardware
|
|
- * @param nic - NIC hardware to read from
|
|
- * @param pkt - The packet which will hold the data
|
|
- * @return 0 if successful, < 0 if failed
|
|
- */
|
|
-static int qedi_read(nic_t *nic, packet_t *pkt)
|
|
-{
|
|
- qedi_t *bp;
|
|
- void *rx_pkt;
|
|
- int rc = 0;
|
|
- uint32_t sw_cons, bd_cons;
|
|
- uint32_t hw_prod, bd_prod;
|
|
- uint32_t rx_pkt_idx;
|
|
- int len;
|
|
- struct qedi_rx_bd *rx_bd;
|
|
- struct qedi_uio_ctrl *uctrl;
|
|
- uint16_t vlan_id;
|
|
-
|
|
- /* Sanity Check: validate the parameters */
|
|
- if (!nic || !pkt) {
|
|
- LOG_ERR(PFX "%s: qedi_read() nic == 0x%p || pkt == 0x%x",
|
|
- nic, pkt);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- bp = (qedi_t *)nic->priv;
|
|
- msync(bp->uctrl_map, sizeof(struct qedi_uio_ctrl), MS_SYNC);
|
|
- msync(bp->rx_comp_ring, nic->page_size, MS_SYNC);
|
|
- uctrl = (struct qedi_uio_ctrl *)bp->uctrl_map;
|
|
- hw_prod = uctrl->hw_rx_prod;
|
|
- bd_prod = uctrl->hw_rx_bd_prod;
|
|
- sw_cons = uctrl->host_rx_cons;
|
|
- bd_cons = uctrl->host_rx_bd_cons;
|
|
- rx_bd = bp->rx_comp_ring + (bd_prod * sizeof(*rx_bd));
|
|
- len = rx_bd->rx_pkt_len;
|
|
- rx_pkt_idx = rx_bd->rx_pkt_index;
|
|
- vlan_id = rx_bd->vlan_id;
|
|
-
|
|
- LOG_DEBUG(PFX "%s:hw_prod %d bd_prod %d, rx_pkt_idx %d, rxlen %d",
|
|
- nic->log_name, hw_prod, bd_prod, rx_bd->rx_pkt_index, len);
|
|
- LOG_DEBUG(PFX "%s: sw_con %d bd_cons %d num BD %d",
|
|
- nic->log_name, sw_cons, bd_cons, QEDI_NUM_RX_BD);
|
|
-
|
|
- if (bd_cons != bd_prod) {
|
|
- LOG_DEBUG(PFX "%s: clearing rx interrupt: %d %d",
|
|
- nic->log_name, sw_cons, hw_prod);
|
|
- rc = 1;
|
|
- rx_pkt = bp->rx_pkts + (bp->rx_buffer_size * rx_pkt_idx);
|
|
-
|
|
- if (len > 0) {
|
|
- msync(rx_pkt, len, MS_SYNC);
|
|
- /* Copy the data */
|
|
- memcpy(pkt->buf, rx_pkt, len);
|
|
- pkt->buf_size = len;
|
|
- if (vlan_id) {
|
|
- pkt->vlan_tag = vlan_id;
|
|
- pkt->flags |= VLAN_TAGGED;
|
|
- } else {
|
|
- pkt->vlan_tag = 0;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: processing packet length: %d",
|
|
- nic->log_name, len);
|
|
-
|
|
- /* bump up the recv stats */
|
|
- nic->stats.rx.packets++;
|
|
- nic->stats.rx.bytes += pkt->buf_size;
|
|
- } else {
|
|
- rc = 0;
|
|
- }
|
|
-
|
|
- sw_cons = (sw_cons + 1) % RX_RING_SIZE;
|
|
- bd_cons = (bd_cons + 1) % QEDI_NUM_RX_BD;
|
|
- uctrl->host_rx_cons_cnt++;
|
|
- }
|
|
-
|
|
- uctrl->host_rx_bd_cons = bd_cons;
|
|
- uctrl->host_rx_cons = sw_cons;
|
|
-
|
|
- msync(uctrl, sizeof(struct qedi_uio_ctrl), MS_SYNC);
|
|
- msync(bp->rx_comp_ring, nic->page_size, MS_SYNC);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Clearing TX interrupts
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * qedi_clear_tx_intr() - This routine is called when a TX interrupt occurs
|
|
- * @param nic - the nic the interrupt occurred on
|
|
- * @return 0 on success
|
|
- */
|
|
-
|
|
-static int qedi_clear_tx_intr(nic_t *nic)
|
|
-{
|
|
- qedi_t *bp;
|
|
- uint32_t hw_cons;
|
|
- struct qedi_uio_ctrl *uctrl;
|
|
-
|
|
- /* Sanity check: ensure the parameters passed in are valid */
|
|
- if (unlikely(!nic)) {
|
|
- LOG_ERR(PFX "%s: nic == NULL", __func__);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- bp = (qedi_t *)nic->priv;
|
|
- uctrl = (struct qedi_uio_ctrl *)bp->uctrl_map;
|
|
- msync(bp->uctrl_map, sizeof(struct qedi_uio_ctrl), MS_SYNC);
|
|
- hw_cons = uctrl->hw_tx_cons;
|
|
-
|
|
- if (bp->tx_cons == hw_cons) {
|
|
- if (bp->tx_cons == bp->tx_prod)
|
|
- return 0;
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- if (pthread_mutex_trylock(&nic->xmit_mutex)) {
|
|
- LOG_ERR(PFX "%s: unable to get xmit_mutex.", nic->log_name);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: clearing tx interrupt [%d %d]",
|
|
- nic->log_name, bp->tx_cons, hw_cons);
|
|
- bp->tx_cons = hw_cons;
|
|
-
|
|
- /* There is a queued TX packet that needs to be sent out. The usual
|
|
- * case is when stack will send an ARP packet out before sending the
|
|
- * intended packet
|
|
- */
|
|
- if (nic->tx_packet_queue) {
|
|
- packet_t *pkt;
|
|
- int i;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: sending queued tx packet", nic->log_name);
|
|
- pkt = nic_dequeue_tx_packet(nic);
|
|
-
|
|
- /* Got a TX packet buffer of the TX queue and put it onto
|
|
- * the hardware
|
|
- */
|
|
- if (pkt) {
|
|
- qedi_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
|
|
-
|
|
- qedi_start_xmit(nic, pkt->buf_size,
|
|
- (pkt->nic_iface->vlan_priority << 12) |
|
|
- pkt->nic_iface->vlan_id);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: transmitted queued packet %d bytes, dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
|
|
- nic->log_name, pkt->buf_size,
|
|
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
|
|
-
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- /* Try to wait for a TX completion */
|
|
- for (i = 0; i < 15; i++) {
|
|
- struct timespec sleep_req = {.tv_sec = 0,
|
|
- .tv_nsec = 5000000
|
|
- }, sleep_rem;
|
|
-
|
|
- hw_cons = uctrl->hw_tx_cons;
|
|
- if (bp->tx_cons != hw_cons) {
|
|
- LOG_PACKET(PFX
|
|
- "%s: clearing tx interrupt [%d %d]",
|
|
- nic->log_name, bp->tx_cons, hw_cons);
|
|
- bp->tx_cons = hw_cons;
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: host:%d - releasing xmit mutex",
|
|
- nic->log_name, nic->host_no);
|
|
- pthread_mutex_unlock(&nic->xmit_mutex);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * qedi NIC op's table
|
|
- ******************************************************************************/
|
|
-struct nic_ops qedi_op = {
|
|
- .description = "qedi",
|
|
- .open = qedi_open,
|
|
- .close = qedi_close,
|
|
- .write = qedi_write,
|
|
- .get_tx_pkt = qedi_get_tx_pkt,
|
|
- .start_xmit = qedi_start_xmit,
|
|
- .read = qedi_read,
|
|
- .clear_tx_intr = qedi_clear_tx_intr,
|
|
- .handle_iscsi_path_req = cnic_handle_iscsi_path_req,
|
|
-
|
|
- .lib_ops = {
|
|
- .get_library_name = qedi_get_library_name,
|
|
- .get_library_version = qedi_get_library_version,
|
|
- .get_build_date = qedi_get_build_date,
|
|
- .get_transport_name = qedi_get_transport_name,
|
|
- .get_uio_name = qedi_get_uio_name,
|
|
- },
|
|
-};
|
|
diff --git a/iscsiuio/src/unix/libs/qedi.h b/iscsiuio/src/unix/libs/qedi.h
|
|
deleted file mode 100644
|
|
index 7e0140a..0000000
|
|
--- a/iscsiuio/src/unix/libs/qedi.h
|
|
+++ /dev/null
|
|
@@ -1,159 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2016, Cavium Inc.
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * qedi.h - qedi user space driver
|
|
- *
|
|
- */
|
|
-#ifndef __QEDI_H__
|
|
-#define __QEDI_H__
|
|
-
|
|
-#include "nic.h"
|
|
-
|
|
-#define RX_RING_SIZE 15
|
|
-#define PKT_BUF_SIZE 0X400
|
|
-#define QEDI_PAGE_SIZE 4096
|
|
-
|
|
-#define QEDI_UNKNOWN_MAJOR_VERSION -1
|
|
-#define QEDI_UNKNOWN_MINOR_VERSION -1
|
|
-#define QEDI_UNKNOWN_SUB_MINOR_VERSION -1
|
|
-struct qedi_driver_version {
|
|
- uint16_t major;
|
|
- uint16_t minor;
|
|
- uint16_t sub_minor;
|
|
-};
|
|
-
|
|
-#define QEDI_UCTRL_MAP_REG 0
|
|
-#define QEDI_RING_MAP_REG 1
|
|
-#define QEDI_BUF_MAP_REG 2
|
|
-#define UIO_ATTR_TMPL "/sys/class/uio/uio%u/maps/map%u/%s"
|
|
-#define UIO_ADDR_TMPL "/sys/class/uio/uio%u/maps/map%u/addr"
|
|
-#define UIO_OFFSET_TMPL "/sys/class/uio/uio%u/maps/map%u/offset"
|
|
-#define UIO_SIZE_TMPL "/sys/class/uio/uio%u/maps/map%u/size"
|
|
-
|
|
-struct qedi_uio_ctrl {
|
|
- /* meta data */
|
|
- __u32 uio_hsi_version;
|
|
-
|
|
- /* user writes */
|
|
- __u32 host_tx_prod;
|
|
- __u32 host_rx_cons;
|
|
- __u32 host_rx_bd_cons;
|
|
- __u32 host_tx_pkt_len;
|
|
- __u32 host_rx_cons_cnt;
|
|
-
|
|
- /* driver writes */
|
|
- __u32 hw_tx_cons;
|
|
- __u32 hw_rx_prod;
|
|
- __u32 hw_rx_bd_prod;
|
|
- __u32 hw_rx_prod_cnt;
|
|
-
|
|
- /* other */
|
|
- __u8 mac_addr[6];
|
|
- __u8 reserve[2];
|
|
-};
|
|
-
|
|
-struct qedi_rx_bd {
|
|
- __u32 rx_pkt_index;
|
|
- __u32 rx_pkt_len;
|
|
- __u16 vlan_id;
|
|
-};
|
|
-
|
|
-#define QEDI_RX_DESC_CNT (QEDI_PAGE_SIZE / sizeof(struct qedi_rx_bd))
|
|
-#define QEDI_MAX_RX_DESC_CNT (QEDI_RX_DESC_CNT - 1)
|
|
-#define QEDI_NUM_RX_BD (QEDI_RX_DESC_CNT * 1)
|
|
-#define QEDI_MAX_RX_BD (QEDI_NUM_RX_BD - 1)
|
|
-
|
|
-#define QEDI_NEXT_RX_IDX(x) ((((x) & (QEDI_MAX_RX_DESC_CNT)) == \
|
|
- (QEDI_MAX_RX_DESC_CNT - 1)) ? \
|
|
- (x) + 2 : (x) + 1)
|
|
-
|
|
-#define QEDI_PATH_HANDLE 0xFE0000000
|
|
-
|
|
-typedef struct qedi {
|
|
- nic_t *parent;
|
|
-
|
|
- struct qedi_driver_version version;
|
|
-
|
|
- uint16_t flags;
|
|
-#define CNIC_UIO_UNITIALIZED 0x0001
|
|
-#define CNIC_UIO_INITIALIZED 0x0002
|
|
-#define CNIC_UIO_ENABLED 0x0004
|
|
-#define CNIC_UIO_DISABLED 0x0008
|
|
-#define CNIC_UIO_IPv6_ENABLED 0x0010
|
|
-#define CNIC_UIO_ADDED_MULICAST 0x0020
|
|
-#define CNIC_UIO_MSIX_ENABLED 0x0200
|
|
-#define CNIC_UIO_TX_HAS_SENT 0x0400
|
|
-#define QEDI_OPENED 0x0800
|
|
-
|
|
- __u32 chip_id;
|
|
- int func;
|
|
- int port;
|
|
- int pfid;
|
|
- __u32 cid;
|
|
- __u32 client_id;
|
|
-
|
|
- __u32 tx_prod;
|
|
- __u32 tx_bd_prod;
|
|
- __u32 tx_cons;
|
|
- __u8 tx_vlan_tag_bit;
|
|
-
|
|
- __u32 rx_prod;
|
|
- __u32 rx_bd_prod;
|
|
- __u32 rx_cons;
|
|
- __u32 rx_bd_cons;
|
|
- __u32 rx_hw_prod;
|
|
-
|
|
- __u32 (*get_rx_cons)(struct qedi *);
|
|
- __u32 (*get_tx_cons)(struct qedi *);
|
|
-
|
|
- /* RX ring parameters */
|
|
- uint32_t rx_ring_size;
|
|
- uint32_t rx_buffer_size;
|
|
-
|
|
- void *bufs; /* Pointer to the mapped buffer space */
|
|
- void *uctrl_map; /* UIO control structure */
|
|
- uint32_t uctrl_map_offset; /* UIO control structure mmap offset */
|
|
-
|
|
- uint32_t rx_index;
|
|
- void *rx_comp_ring;
|
|
- void **rx_pkt_ring;
|
|
- void *tx_pkt;
|
|
- void *rx_pkts;
|
|
-} qedi_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * qedi Function Declarations
|
|
- ******************************************************************************/
|
|
-void qedi_start_xmit(nic_t *nic, size_t len, u16_t vlan_id);
|
|
-struct nic_ops *qedi_get_ops();
|
|
-
|
|
-#endif /* __QEDI_H__ */
|
|
diff --git a/iscsiuio/src/unix/logger.c b/iscsiuio/src/unix/logger.c
|
|
deleted file mode 100644
|
|
index 87e16cd..0000000
|
|
--- a/iscsiuio/src/unix/logger.c
|
|
+++ /dev/null
|
|
@@ -1,181 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * logger.c - Logging Utilities
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <string.h>
|
|
-#include <time.h>
|
|
-#include <stdarg.h>
|
|
-#include <stdlib.h>
|
|
-
|
|
-#include "options.h"
|
|
-#include "logger.h"
|
|
-
|
|
-/******************************************************************************
|
|
- * Default logger values
|
|
- ******************************************************************************/
|
|
-static const char default_logger_filename[] = "/var/log/iscsiuio.log";
|
|
-
|
|
-struct logger main_log = {
|
|
- .enabled = LOGGER_ENABLED,
|
|
- .fp = NULL,
|
|
- .log_file = (char *)default_logger_filename,
|
|
- .level = LOG_LEVEL_INFO,
|
|
- .lock = PTHREAD_MUTEX_INITIALIZER,
|
|
-
|
|
- .stats = {
|
|
- .debug = 0,
|
|
- .info = 0,
|
|
- .warn = 0,
|
|
- .error = 0,
|
|
-
|
|
- .last_log_time = 0,
|
|
- },
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * Logger Functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * log_uip() - Main logging function
|
|
- * @param level_str - log level string
|
|
- * @param fmt - log format
|
|
- */
|
|
-void log_uip(char *level_str, char *fmt, ...)
|
|
-{
|
|
- char time_buf[32];
|
|
- va_list ap, ap2;
|
|
-
|
|
- pthread_mutex_lock(&main_log.lock);
|
|
- va_start(ap, fmt);
|
|
-
|
|
- if (main_log.fp == NULL)
|
|
- goto end;
|
|
-
|
|
- main_log.stats.last_log_time = time(NULL);
|
|
- strftime(time_buf, 26, "%a %b %d %T %Y",
|
|
- localtime(&main_log.stats.last_log_time));
|
|
- va_copy(ap2, ap);
|
|
-
|
|
- if (main_log.enabled == LOGGER_ENABLED) {
|
|
- fprintf(main_log.fp, "%s [%s]", level_str, time_buf);
|
|
- vfprintf(main_log.fp, fmt, ap);
|
|
- fprintf(main_log.fp, "\n");
|
|
- }
|
|
-
|
|
- if (opt.debug == DEBUG_ON) {
|
|
- fprintf(stdout, "%s [%s]", level_str, time_buf);
|
|
- vfprintf(stdout, fmt, ap2);
|
|
- fprintf(stdout, "\n");
|
|
-
|
|
- /* Force the printing of the log file */
|
|
- fflush(main_log.fp);
|
|
-
|
|
- /* Force the printing of the log out to standard output */
|
|
- fflush(stdout);
|
|
- }
|
|
-
|
|
-end:
|
|
- va_end(ap2);
|
|
- va_end(ap);
|
|
- pthread_mutex_unlock(&main_log.lock);
|
|
-}
|
|
-
|
|
-/******************************************************************************
|
|
- * Initialize/Clean up routines
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * init_logger() - Prepare the logger
|
|
- * @param filename - path to where the log will be written to
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int init_logger(char *filename)
|
|
-{
|
|
- int rc = 0;
|
|
-
|
|
- pthread_mutex_lock(&main_log.lock);
|
|
-
|
|
- if (opt.debug != DEBUG_ON) {
|
|
- rc = -EIO;
|
|
- goto disable;
|
|
- }
|
|
- main_log.fp = fopen(filename, "a");
|
|
- if (main_log.fp == NULL) {
|
|
- fprintf(stderr, "WARN: Could not create log file: %s <%s>\n",
|
|
- filename, strerror(errno));
|
|
- rc = -EIO;
|
|
- }
|
|
-disable:
|
|
- if (rc)
|
|
- main_log.enabled = LOGGER_DISABLED;
|
|
- else
|
|
- main_log.enabled = LOGGER_ENABLED;
|
|
-
|
|
- pthread_mutex_unlock(&main_log.lock);
|
|
-
|
|
- if (!rc)
|
|
- LOG_INFO("Initialize logger using log file: %s", filename);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-void fini_logger(int type)
|
|
-{
|
|
- pthread_mutex_lock(&main_log.lock);
|
|
-
|
|
- if (main_log.fp != NULL) {
|
|
- fclose(main_log.fp);
|
|
- main_log.fp = NULL;
|
|
-
|
|
- if (opt.debug == DEBUG_ON) {
|
|
- printf("Closed logger\n");
|
|
- fflush(stdout);
|
|
- }
|
|
- }
|
|
-
|
|
- if (type == SHUTDOWN_LOGGER) {
|
|
- if ((main_log.log_file != NULL) &&
|
|
- (main_log.log_file != default_logger_filename)) {
|
|
- free(main_log.log_file);
|
|
- main_log.log_file = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- main_log.enabled = LOGGER_DISABLED;
|
|
-
|
|
- pthread_mutex_unlock(&main_log.lock);
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/logger.h b/iscsiuio/src/unix/logger.h
|
|
deleted file mode 100644
|
|
index 06e2084..0000000
|
|
--- a/iscsiuio/src/unix/logger.h
|
|
+++ /dev/null
|
|
@@ -1,129 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * logger.h - Logging Utilities
|
|
- *
|
|
- */
|
|
-#ifndef __LOGGER_H__
|
|
-#define __LOGGER_H__
|
|
-
|
|
-#include <pthread.h>
|
|
-#include <stdio.h>
|
|
-#include <time.h>
|
|
-#include <stdint.h>
|
|
-#include <sys/types.h>
|
|
-
|
|
-/*******************************************************************************
|
|
- * Logger Levels
|
|
- ******************************************************************************/
|
|
-#define LOG_LEVEL_PACKET 5
|
|
-#define LOG_LEVEL_DEBUG 4
|
|
-#define LOG_LEVEL_INFO 3
|
|
-#define LOG_LEVEL_WARN 2
|
|
-#define LOG_LEVEL_ERR 1
|
|
-#define LOG_LEVEL_UNKNOWN 0
|
|
-
|
|
-#define LOG_LEVEL_PACKET_STR "PKT "
|
|
-#define LOG_LEVEL_DEBUG_STR "DBG "
|
|
-#define LOG_LEVEL_INFO_STR "INFO "
|
|
-#define LOG_LEVEL_WARN_STR "WARN "
|
|
-#define LOG_LEVEL_ERR_STR "ERR "
|
|
-#define LOG_LEVEL_UNKNOWN_STR "? "
|
|
-
|
|
-/*******************************************************************************
|
|
- * Logging Macro's
|
|
- ******************************************************************************/
|
|
-#define LOG_PACKET(fmt, args...) { if (LOG_LEVEL_PACKET <= \
|
|
- main_log.level) { \
|
|
- log_uip(LOG_LEVEL_PACKET_STR, fmt,\
|
|
- ##args);\
|
|
- } }
|
|
-#define LOG_DEBUG(fmt, args...) { if (LOG_LEVEL_DEBUG <= main_log.level) { \
|
|
- log_uip(LOG_LEVEL_DEBUG_STR, fmt,\
|
|
- ##args);\
|
|
- } }
|
|
-
|
|
-#define LOG_INFO(fmt, args...) { if (LOG_LEVEL_INFO <= main_log.level) { \
|
|
- log_uip(LOG_LEVEL_INFO_STR, fmt,\
|
|
- ##args); \
|
|
- } }
|
|
-#define LOG_WARN(fmt, args...) { if (LOG_LEVEL_WARN <= main_log.level) { \
|
|
- log_uip(LOG_LEVEL_WARN_STR, fmt,\
|
|
- ##args); \
|
|
- } }
|
|
-#define LOG_ERR(fmt, args...) { if (LOG_LEVEL_ERR <= main_log.level) { \
|
|
- log_uip(LOG_LEVEL_ERR_STR, fmt,\
|
|
- ##args); \
|
|
- } }
|
|
-
|
|
-/*******************************************************************************
|
|
- * Logging Statistics
|
|
- ******************************************************************************/
|
|
-struct logger_stats {
|
|
- uint64_t debug;
|
|
- uint64_t info;
|
|
- uint64_t warn;
|
|
- uint64_t error;
|
|
-
|
|
- time_t last_log_time;
|
|
-};
|
|
-
|
|
-/*******************************************************************************
|
|
- * Logger Structure
|
|
- ******************************************************************************/
|
|
-struct logger {
|
|
- FILE *fp;
|
|
- char *log_file;
|
|
- int8_t level;
|
|
-
|
|
-#define LOGGER_ENABLED 0x01
|
|
-#define LOGGER_DISABLED 0x02
|
|
- int8_t enabled;
|
|
-
|
|
- pthread_mutex_t lock;
|
|
-
|
|
- struct logger_stats stats;
|
|
-};
|
|
-
|
|
-extern struct logger main_log;
|
|
-
|
|
-int init_logger(char *);
|
|
-void log_uip(char *level_str, char *fmt, ...);
|
|
-void fini_logger(int);
|
|
-
|
|
-#define CLOSE_LOGGER 0x01
|
|
-#define SHUTDOWN_LOGGER 0x02
|
|
-
|
|
-#endif
|
|
diff --git a/iscsiuio/src/unix/main.c b/iscsiuio/src/unix/main.c
|
|
deleted file mode 100644
|
|
index 0c9ad49..0000000
|
|
--- a/iscsiuio/src/unix/main.c
|
|
+++ /dev/null
|
|
@@ -1,442 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2001, Adam Dunkels.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack.
|
|
- *
|
|
- *
|
|
- */
|
|
-
|
|
-#include <dlfcn.h>
|
|
-#include <errno.h>
|
|
-#include <fcntl.h>
|
|
-#include <string.h>
|
|
-#include <signal.h>
|
|
-#include <stdlib.h>
|
|
-#include <getopt.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/utsname.h>
|
|
-#include <net/ethernet.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <sys/mman.h>
|
|
-#ifndef NO_SYSTEMD
|
|
-#include <systemd/sd-daemon.h>
|
|
-#endif
|
|
-#include <assert.h>
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uip_arp.h"
|
|
-#include "uip_eth.h"
|
|
-
|
|
-#include "timer.h"
|
|
-
|
|
-#include "build_date.h"
|
|
-#include "config.h"
|
|
-#include "iscsid_ipc.h"
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_id.h"
|
|
-#include "nic_nl.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-#include "packet.h"
|
|
-
|
|
-#include "dhcpc.h"
|
|
-
|
|
-#include "iscsid_ipc.h"
|
|
-#include "brcm_iscsi.h"
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "main "
|
|
-
|
|
-static const char default_pid_filepath[] = "/run/iscsiuio.pid";
|
|
-
|
|
-/*******************************************************************************
|
|
- * Global Variables
|
|
- ******************************************************************************/
|
|
-static const struct option long_options[] = {
|
|
- {"foreground", no_argument, NULL, 'f'},
|
|
- {"debug", required_argument, NULL, 'd'},
|
|
- {"pid", required_argument, NULL, 'p'},
|
|
- {"version", no_argument, NULL, 'v'},
|
|
- {"help", no_argument, NULL, 'h'},
|
|
- {NULL, no_argument, NULL, 0}
|
|
-};
|
|
-
|
|
-struct options opt = {
|
|
- .debug = DEBUG_OFF,
|
|
-};
|
|
-
|
|
-int event_loop_stop;
|
|
-extern nic_t *nic_list;
|
|
-
|
|
-struct utsname cur_utsname;
|
|
-
|
|
-/**
|
|
- * cleanup() - This function is called when this program is to be closed
|
|
- * This function will clean up all the cnic uio interfaces and
|
|
- * flush/close the logger
|
|
- */
|
|
-static void cleanup()
|
|
-{
|
|
- iscsid_cleanup();
|
|
-
|
|
- nic_remove_all();
|
|
-
|
|
- unload_all_nic_libraries();
|
|
-
|
|
- LOG_INFO("Done waiting for cnic's/stacks to gracefully close");
|
|
-
|
|
- fini_logger(SHUTDOWN_LOGGER);
|
|
-}
|
|
-
|
|
-/**
|
|
- * signal_handle_thread() - This is the signal handling thread of this program
|
|
- * This is the only thread which will handle signals.
|
|
- * All signals are routed here and handled here to
|
|
- * provide consistant handling.
|
|
- */
|
|
-static pthread_t signal_thread;
|
|
-static void *signal_handle_thread(void *arg)
|
|
-{
|
|
- sigset_t set;
|
|
- int rc;
|
|
- int signal;
|
|
-
|
|
- sigfillset(&set);
|
|
-
|
|
- LOG_INFO("signal handling thread ready");
|
|
-
|
|
-signal_wait:
|
|
- rc = sigwait(&set, &signal);
|
|
-
|
|
- switch (signal) {
|
|
- case SIGINT:
|
|
- LOG_INFO("Caught SIGINT signal");
|
|
- break;
|
|
- case SIGUSR1:
|
|
- LOG_INFO("Caught SIGUSR1 signal, rotate log");
|
|
- fini_logger(SHUTDOWN_LOGGER);
|
|
- rc = init_logger(main_log.log_file);
|
|
- if (rc != 0)
|
|
- fprintf(stderr, "WARN: Could not initialize the logger in "
|
|
- "signal!\n");
|
|
- goto signal_wait;
|
|
- default:
|
|
- break;
|
|
- }
|
|
- event_loop_stop = 1;
|
|
-
|
|
- LOG_INFO("terminating...");
|
|
-
|
|
- cleanup();
|
|
- exit(EXIT_SUCCESS);
|
|
-}
|
|
-
|
|
-static void show_version()
|
|
-{
|
|
- printf("%s: Version '%s', Build Date: '%s'\n",
|
|
- APP_NAME, PACKAGE_VERSION, build_date);
|
|
-}
|
|
-
|
|
-static void main_usage()
|
|
-{
|
|
- show_version();
|
|
-
|
|
- printf("\nUsage: %s [OPTION]\n", APP_NAME);
|
|
- printf("iscsiuio daemon.\n"
|
|
- "-f, --foreground make the program run in the foreground\n"
|
|
- "-d, --debug debuglevel print debugging information\n"
|
|
- "-p, --pid pidfile use pid file (default %s).\n"
|
|
- "-h, --help display this help and exit\n"
|
|
- "-v, --version display version and exit\n",
|
|
- default_pid_filepath);
|
|
-}
|
|
-
|
|
-static void daemon_init()
|
|
-{
|
|
- int fd;
|
|
- int res;
|
|
-
|
|
- fd = open("/dev/null", O_RDWR);
|
|
- assert(fd >= 0);
|
|
-
|
|
- dup2(fd, 0);
|
|
- dup2(fd, 1);
|
|
- dup2(fd, 2);
|
|
- setsid();
|
|
- res = chdir("/");
|
|
- assert(res == 0);
|
|
- close(fd);
|
|
-}
|
|
-
|
|
-#define ISCSI_OOM_PATH_LEN 48
|
|
-
|
|
-int oom_adjust(void)
|
|
-{
|
|
- int fd;
|
|
- char path[ISCSI_OOM_PATH_LEN];
|
|
- struct stat statb;
|
|
-
|
|
- if (nice(-10) < 0)
|
|
- LOG_DEBUG("Could not increase process priority: %s",
|
|
- strerror(errno));
|
|
-
|
|
- snprintf(path, ISCSI_OOM_PATH_LEN, "/proc/%d/oom_score_adj", getpid());
|
|
- if (stat(path, &statb)) {
|
|
- /* older kernel so use old oom_adj file */
|
|
- snprintf(path, ISCSI_OOM_PATH_LEN, "/proc/%d/oom_adj",
|
|
- getpid());
|
|
- }
|
|
- fd = open(path, O_WRONLY);
|
|
- if (fd < 0)
|
|
- return -1;
|
|
- if (write(fd, "-16", 3) < 0) /* for 2.6.11 */
|
|
- LOG_DEBUG("Could not set oom score to -16: %s",
|
|
- strerror(errno));
|
|
- if (write(fd, "-17", 3) < 0) /* for Andrea's patch */
|
|
- LOG_DEBUG("Could not set oom score to -17: %s",
|
|
- strerror(errno));
|
|
- close(fd);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-/*******************************************************************************
|
|
- * Main routine
|
|
- ******************************************************************************/
|
|
-int main(int argc, char *argv[])
|
|
-{
|
|
- int rc;
|
|
- sigset_t set;
|
|
- const char *pid_file = default_pid_filepath;
|
|
- int fd;
|
|
- int foreground = 0;
|
|
- pid_t pid;
|
|
- pthread_attr_t attr;
|
|
- int pipefds[2];
|
|
-
|
|
- /* Record the start time for the user space daemon */
|
|
- opt.start_time = time(NULL);
|
|
-
|
|
- /* parse the parameters */
|
|
- while (1) {
|
|
- int c, option_index;
|
|
-
|
|
- c = getopt_long(argc, argv, "fd:p:vh",
|
|
- long_options, &option_index);
|
|
-
|
|
- if (c == -1)
|
|
- break;
|
|
-
|
|
- switch (c) {
|
|
-
|
|
- case 'f':
|
|
- foreground = 1;
|
|
- break;
|
|
-
|
|
- /* Enable debugging mode */
|
|
- case 'd':
|
|
- main_log.level = atoi(optarg);
|
|
- opt.debug = DEBUG_ON;
|
|
- break;
|
|
- case 'p':
|
|
- pid_file = optarg;
|
|
- break;
|
|
- case 'v':
|
|
- show_version();
|
|
- exit(EXIT_SUCCESS);
|
|
- case 'h':
|
|
- default:
|
|
- main_usage();
|
|
- exit(EXIT_SUCCESS);
|
|
- }
|
|
- }
|
|
-
|
|
- if (main_log.enabled == LOGGER_ENABLED) {
|
|
- /* initialize the logger */
|
|
- rc = init_logger(main_log.log_file);
|
|
- if (rc != 0 && opt.debug == DEBUG_ON)
|
|
- fprintf(stderr, "WARN: Could not initialize the logger\n");
|
|
- }
|
|
-
|
|
- LOG_INFO("Started iSCSI uio stack: Ver " PACKAGE_VERSION);
|
|
- LOG_INFO("Build date: %s", build_date);
|
|
-
|
|
- if (opt.debug == DEBUG_ON)
|
|
- LOG_INFO("Debug mode enabled");
|
|
-
|
|
- event_loop_stop = 0;
|
|
- nic_list = NULL;
|
|
-
|
|
- /* Determine the current kernel version */
|
|
- memset(&cur_utsname, 0, sizeof(cur_utsname));
|
|
-
|
|
- rc = uname(&cur_utsname);
|
|
- if (rc == 0) {
|
|
- LOG_INFO("Running on sysname: '%s', release: '%s', "
|
|
- "version '%s' machine: '%s'",
|
|
- cur_utsname.sysname, cur_utsname.release,
|
|
- cur_utsname.version, cur_utsname.machine);
|
|
- } else
|
|
- LOG_WARN("Could not determine kernel version");
|
|
-
|
|
- /* Initialze the iscsid listener */
|
|
- rc = iscsid_init();
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- if (!foreground) {
|
|
- char buf[64];
|
|
- ssize_t written_bytes;
|
|
-
|
|
- fd = open(pid_file, O_WRONLY | O_CREAT, 0644);
|
|
- if (fd < 0) {
|
|
- fprintf(stderr, "ERR: Unable to create pid file: %s\n",
|
|
- pid_file);
|
|
- exit(1);
|
|
- }
|
|
-
|
|
- if (pipe(pipefds) < 0) {
|
|
- fprintf(stderr, "ERR: Unable to create a PIPE: %s\n",
|
|
- strerror(errno));
|
|
- exit(1);
|
|
- }
|
|
-
|
|
- pid = fork();
|
|
- if (pid < 0) {
|
|
- fprintf(stderr, "ERR: Starting daemon failed\n");
|
|
- exit(1);
|
|
- } else if (pid) {
|
|
- char msgbuf[4];
|
|
- int res;
|
|
-
|
|
- /* parent: wait for child msg then exit */
|
|
- close(pipefds[1]); /* close unused end */
|
|
- res = read(pipefds[0], msgbuf, sizeof(msgbuf));
|
|
- assert(res > 0);
|
|
- exit(0);
|
|
- }
|
|
-
|
|
- /* the child */
|
|
- rc = chdir("/");
|
|
- if (rc == -1)
|
|
- fprintf(stderr, "WARN: Unable to chdir(\") [%s]\n", strerror(errno));
|
|
-
|
|
- if (lockf(fd, F_TLOCK, 0) < 0) {
|
|
- fprintf(stderr, "ERR: Unable to lock pid file: %s [%s]\n",
|
|
- pid_file, strerror(errno));
|
|
- exit(1);
|
|
- }
|
|
-
|
|
- rc = ftruncate(fd, 0);
|
|
- if (rc == -1)
|
|
- fprintf(stderr, "WARN: ftruncate(%d, 0) failed [%s]\n",
|
|
- fd, strerror(errno));
|
|
-
|
|
- sprintf(buf, "%d\n", getpid());
|
|
- written_bytes = write(fd, buf, strlen(buf));
|
|
- if (written_bytes == -1) {
|
|
- fprintf(stderr, "ERR: Could not write pid file [%s]\n",
|
|
- strerror(errno));
|
|
- exit(1);
|
|
- }
|
|
- close(fd);
|
|
-
|
|
- daemon_init();
|
|
- }
|
|
-
|
|
- /* Load the NIC libraries */
|
|
- rc = load_all_nic_libraries();
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- brcm_iscsi_init();
|
|
-
|
|
- /* ensure we don't see any signals */
|
|
- sigemptyset(&set);
|
|
- sigaddset(&set, SIGINT);
|
|
- sigaddset(&set, SIGQUIT);
|
|
- sigaddset(&set, SIGTERM);
|
|
- sigaddset(&set, SIGUSR1);
|
|
- rc = pthread_sigmask(SIG_SETMASK, &set, NULL);
|
|
-
|
|
- /* Spin off the signal handling thread */
|
|
- pthread_attr_init(&attr);
|
|
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
- rc = pthread_create(&signal_thread, &attr, signal_handle_thread, NULL);
|
|
- if (rc != 0)
|
|
- LOG_ERR("Could not create signal handling thread");
|
|
-
|
|
- /* Using sysfs to discover iSCSI hosts */
|
|
- nic_discover_iscsi_hosts();
|
|
-
|
|
- /* oom-killer will not kill us at the night... */
|
|
- if (oom_adjust())
|
|
- LOG_DEBUG("Can not adjust oom-killer's pardon");
|
|
-
|
|
- /* we don't want our active sessions to be paged out... */
|
|
- if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
|
- LOG_ERR("failed to mlockall, exiting...");
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* Start the iscsid listener */
|
|
- rc = iscsid_start();
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- if (!foreground) {
|
|
- int res;
|
|
-
|
|
- /* signal parent they can go away now */
|
|
- close(pipefds[0]); /* close unused end */
|
|
- res = write(pipefds[1], "ok\n", 3);
|
|
- assert(res > 0);
|
|
- close(pipefds[1]);
|
|
- }
|
|
-
|
|
-#ifndef NO_SYSTEMD
|
|
- sd_notify(0, "READY=1\n"
|
|
- "STATUS=Ready to process requests\n");
|
|
-#endif
|
|
-
|
|
- /* NetLink connection to listen to NETLINK_ISCSI private messages */
|
|
- if (nic_nl_open() != 0)
|
|
- goto error;
|
|
-
|
|
-error:
|
|
- cleanup();
|
|
- exit(EXIT_FAILURE);
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic.c b/iscsiuio/src/unix/nic.c
|
|
deleted file mode 100644
|
|
index f449935..0000000
|
|
--- a/iscsiuio/src/unix/nic.c
|
|
+++ /dev/null
|
|
@@ -1,1548 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic.c - Generic NIC management/utility functions
|
|
- *
|
|
- */
|
|
-#include <dlfcn.h>
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <signal.h>
|
|
-#include <string.h>
|
|
-#include <time.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/time.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <netinet/in.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-#include "dhcpc.h"
|
|
-#include "ipv6_ndpc.h"
|
|
-
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uip_arp.h"
|
|
-#include "uip_eth.h"
|
|
-#include "uip-neighbor.h"
|
|
-
|
|
-#include "bnx2.h"
|
|
-#include "bnx2x.h"
|
|
-#include "qedi.h"
|
|
-#include "ipv6.h"
|
|
-
|
|
-/******************************************************************************
|
|
- * Constants
|
|
- *****************************************************************************/
|
|
-#define PFX "nic "
|
|
-#define PCI_ANY_ID (~0)
|
|
-
|
|
-/******************************************************************************
|
|
- * Global variables
|
|
- *****************************************************************************/
|
|
-/* Used to store a list of NIC libraries */
|
|
-pthread_mutex_t nic_lib_list_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
-nic_lib_handle_t *nic_lib_list;
|
|
-
|
|
-/* Used to store a list of active cnic devices */
|
|
-pthread_mutex_t nic_list_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
-nic_t *nic_list;
|
|
-
|
|
-/******************************************************************************
|
|
- * Functions to handle NIC libraries
|
|
- *****************************************************************************/
|
|
-/**
|
|
- * alloc_nic_library_handle() - Used to allocate a NIC library handle
|
|
- * @return NULL if memory couldn't be allocated, pointer to the handle
|
|
- * to the NIC library handle
|
|
- */
|
|
-static nic_lib_handle_t *alloc_nic_library_handle()
|
|
-{
|
|
- nic_lib_handle_t *handle;
|
|
-
|
|
- handle = malloc(sizeof(*handle));
|
|
- if (handle == NULL) {
|
|
- LOG_ERR("Could not allocate memory for library handle");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- memset(handle, 0, sizeof(*handle));
|
|
- handle->ops = NULL;
|
|
-
|
|
- pthread_mutex_init(&handle->mutex, NULL);
|
|
-
|
|
- return handle;
|
|
-}
|
|
-
|
|
-static void free_nic_library_handle(nic_lib_handle_t *handle)
|
|
-{
|
|
- free(handle);
|
|
-}
|
|
-
|
|
-/**
|
|
- * load_nic_library() - This function is used to load a NIC library
|
|
- * @param handle - This is the library handle to load
|
|
- * @return 0 = Success; <0 = failure
|
|
- */
|
|
-static int load_nic_library(nic_lib_handle_t *handle)
|
|
-{
|
|
- int rc;
|
|
- char *library_name;
|
|
- size_t library_name_size;
|
|
- char *library_version;
|
|
- size_t library_version_size;
|
|
- char *build_date_str;
|
|
- size_t build_date_str_size;
|
|
-
|
|
- pthread_mutex_lock(&handle->mutex);
|
|
-
|
|
- /* Validate the NIC ops table ensure that all the fields are not NULL */
|
|
- if ((handle->ops->open) == NULL ||
|
|
- (handle->ops->close) == NULL ||
|
|
- (handle->ops->read) == NULL ||
|
|
- (handle->ops->write) == NULL ||
|
|
- (handle->ops->clear_tx_intr == NULL)) {
|
|
- LOG_ERR("Invalid NIC ops table: open: 0x%x, close: 0x%x,"
|
|
- "read: 0x%x, write: 0x%x clear_tx_intr: 0x%x "
|
|
- "lib_ops: 0x%x",
|
|
- handle->ops->open, handle->ops->close,
|
|
- handle->ops->read, handle->ops->write,
|
|
- handle->ops->clear_tx_intr, handle->ops->lib_ops);
|
|
- rc = -EINVAL;
|
|
- handle->ops = NULL;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* Validate the NIC library ops table to ensure that all the proper
|
|
- * fields are filled */
|
|
- if ((handle->ops->lib_ops.get_library_name == NULL) ||
|
|
- (handle->ops->lib_ops.get_library_version == NULL) ||
|
|
- (handle->ops->lib_ops.get_build_date == NULL) ||
|
|
- (handle->ops->lib_ops.get_transport_name == NULL)) {
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- (*handle->ops->lib_ops.get_library_name) (&library_name,
|
|
- &library_name_size);
|
|
- (*handle->ops->lib_ops.get_library_version) (&library_version,
|
|
- &library_version_size);
|
|
- (*handle->ops->lib_ops.get_build_date) (&build_date_str,
|
|
- &build_date_str_size);
|
|
-
|
|
- LOG_DEBUG("Loaded nic library '%s' Version: '%s' build on %s'",
|
|
- library_name, library_version, build_date_str);
|
|
-
|
|
- pthread_mutex_unlock(&handle->mutex);
|
|
-
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- pthread_mutex_unlock(&handle->mutex);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static struct nic_ops *(*nic_get_ops[]) () = {
|
|
-bnx2_get_ops, bnx2x_get_ops, qedi_get_ops};
|
|
-
|
|
-int load_all_nic_libraries()
|
|
-{
|
|
- int rc, i = 0;
|
|
- nic_lib_handle_t *handle;
|
|
-
|
|
- for (i = 0; i < sizeof(nic_get_ops) / sizeof(nic_get_ops[0]); i++) {
|
|
- /* Add the CNIC library */
|
|
- handle = alloc_nic_library_handle();
|
|
- if (handle == NULL) {
|
|
- LOG_ERR("Could not allocate memory for CNIC nic lib");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- handle->ops = (*nic_get_ops[i]) ();
|
|
-
|
|
- rc = load_nic_library(handle);
|
|
- if (rc != 0) {
|
|
- free_nic_library_handle(handle);
|
|
- return rc;
|
|
- }
|
|
- /* Add the CNIC library to the list of library handles */
|
|
- pthread_mutex_lock(&nic_lib_list_mutex);
|
|
-
|
|
- /* Add this library to the list of nic libraries we
|
|
- * know about */
|
|
- if (nic_lib_list == NULL) {
|
|
- nic_lib_list = handle;
|
|
- } else {
|
|
- nic_lib_handle_t *current = nic_lib_list;
|
|
-
|
|
- while (current->next != NULL)
|
|
- current = current->next;
|
|
-
|
|
- current->next = handle;
|
|
- }
|
|
- pthread_mutex_unlock(&nic_lib_list_mutex);
|
|
-
|
|
- LOG_DEBUG("Added '%s' nic library", handle->ops->description);
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int unload_all_nic_libraries()
|
|
-{
|
|
- nic_lib_handle_t *current, *next;
|
|
-
|
|
- pthread_mutex_lock(&nic_lib_list_mutex);
|
|
- current = nic_lib_list;
|
|
-
|
|
- while (current != NULL) {
|
|
- next = current->next;
|
|
- free_nic_library_handle(current);
|
|
-
|
|
- current = next;
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic_lib_list_mutex);
|
|
-
|
|
- nic_lib_list = NULL;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-NIC_LIBRARY_EXIST_T does_nic_uio_name_exist(char *name,
|
|
- nic_lib_handle_t **handle)
|
|
-{
|
|
- NIC_LIBRARY_EXIST_T rc;
|
|
- nic_lib_handle_t *current;
|
|
-
|
|
- pthread_mutex_lock(&nic_lib_list_mutex);
|
|
- current = nic_lib_list;
|
|
-
|
|
- while (current != NULL) {
|
|
- char *uio_name;
|
|
- size_t uio_name_size;
|
|
-
|
|
- (*current->ops->lib_ops.get_uio_name) (&uio_name,
|
|
- &uio_name_size);
|
|
-
|
|
- if (strncmp(name, uio_name, uio_name_size) == 0) {
|
|
- if (handle)
|
|
- *handle = current;
|
|
-
|
|
- rc = NIC_LIBRARY_EXSITS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- current = current->next;
|
|
- }
|
|
-
|
|
- rc = NIC_LIBRARY_DOESNT_EXIST;
|
|
-
|
|
-done:
|
|
- pthread_mutex_unlock(&nic_lib_list_mutex);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-NIC_LIBRARY_EXIST_T does_nic_library_exist(char *name,
|
|
- nic_lib_handle_t **handle)
|
|
-{
|
|
- NIC_LIBRARY_EXIST_T rc;
|
|
- nic_lib_handle_t *current;
|
|
-
|
|
- pthread_mutex_lock(&nic_lib_list_mutex);
|
|
- current = nic_lib_list;
|
|
-
|
|
- while (current != NULL) {
|
|
- char *library_name;
|
|
- size_t library_name_size;
|
|
-
|
|
- (*current->ops->lib_ops.get_library_name) (&library_name,
|
|
- &library_name_size);
|
|
-
|
|
- if (strncmp(name, library_name, library_name_size) == 0) {
|
|
- if (handle)
|
|
- *handle = current;
|
|
-
|
|
- rc = NIC_LIBRARY_EXSITS;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- current = current->next;
|
|
- }
|
|
-
|
|
- rc = NIC_LIBRARY_DOESNT_EXIST;
|
|
-
|
|
-done:
|
|
- pthread_mutex_unlock(&nic_lib_list_mutex);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * find_nic_lib_using_pci_id() - Find the proper NIC library using the
|
|
- * PCI ID's
|
|
- * @param vendor - PCI vendor ID to search on
|
|
- * @param device - PCI device ID to search on
|
|
- * @param subvendor - PCI subvendor ID to search on
|
|
- * @param subdevice - PCI subdevice ID to search on
|
|
- * @param handle - This function will return the nic lib handle if found
|
|
- * @return 0 if found, <0 not found
|
|
- */
|
|
-int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
|
|
- uint32_t subvendor, uint32_t subdevice,
|
|
- nic_lib_handle_t **handle,
|
|
- struct pci_device_id **pci_entry)
|
|
-{
|
|
- int rc;
|
|
- nic_lib_handle_t *current;
|
|
-
|
|
- pthread_mutex_lock(&nic_lib_list_mutex);
|
|
- current = nic_lib_list;
|
|
-
|
|
- while (current != NULL) {
|
|
- struct pci_device_id *pci_table;
|
|
- uint32_t entries;
|
|
- int i;
|
|
-
|
|
- if (current->ops->lib_ops.get_pci_table != NULL) {
|
|
- current->ops->lib_ops.get_pci_table(&pci_table,
|
|
- &entries);
|
|
- } else {
|
|
- current = current->next;
|
|
- continue;
|
|
- }
|
|
- /* Sanity check the the pci table coming from the
|
|
- * hardware library */
|
|
- if (entries > MAX_PCI_DEVICE_ENTRIES) {
|
|
- LOG_WARN(PFX "Too many pci_table entries(%d) skipping",
|
|
- entries);
|
|
- continue;
|
|
- }
|
|
-
|
|
- for (i = 0; i < entries; i++) {
|
|
- LOG_DEBUG(PFX "Checking against: "
|
|
- "vendor: 0x%x device:0x%x "
|
|
- "subvendor:0x%x subdevice:0x%x",
|
|
- pci_table[i].vendor, pci_table[i].device,
|
|
- pci_table[i].subvendor,
|
|
- pci_table[i].subdevice);
|
|
-
|
|
- if ((pci_table[i].vendor == vendor) &&
|
|
- (pci_table[i].device == device) &&
|
|
- (pci_table[i].subvendor == PCI_ANY_ID ||
|
|
- pci_table[i].subvendor == subvendor) &&
|
|
- (pci_table[i].subdevice == PCI_ANY_ID ||
|
|
- pci_table[i].subdevice == subdevice)) {
|
|
- *handle = current;
|
|
- *pci_entry = &pci_table[i];
|
|
- rc = 0;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- current = current->next;
|
|
- }
|
|
- rc = -EINVAL;
|
|
-
|
|
-done:
|
|
- pthread_mutex_unlock(&nic_lib_list_mutex);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_init() - This will properly initialize a struct cnic_uio device
|
|
- * @return NULL is there is a failure and pointer to an allocated/initialized
|
|
- * struct cnic_uio on success
|
|
- */
|
|
-nic_t *nic_init()
|
|
-{
|
|
- nic_t *nic;
|
|
-
|
|
- nic = malloc(sizeof(*nic));
|
|
- if (nic == NULL) {
|
|
- LOG_ERR("Couldn't malloc space for nic");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- memset(nic, 0, sizeof(*nic));
|
|
- nic->uio_minor = -1;
|
|
- nic->fd = INVALID_FD;
|
|
- nic->host_no = INVALID_HOST_NO;
|
|
- nic->next = NULL;
|
|
- nic->thread = INVALID_THREAD;
|
|
- nic->enable_thread = INVALID_THREAD;
|
|
- nic->flags |= NIC_DISABLED;
|
|
- nic->state = NIC_STOPPED;
|
|
- nic->free_packet_queue = NULL;
|
|
- nic->tx_packet_queue = NULL;
|
|
- nic->nic_library = NULL;
|
|
- nic->pci_id = NULL;
|
|
- nic->page_size = getpagesize();
|
|
-
|
|
- /* nic_mutex is used to protect nic ops */
|
|
- pthread_mutex_init(&nic->nic_mutex, NULL);
|
|
- pthread_mutex_init(&nic->xmit_mutex, NULL);
|
|
- pthread_mutex_init(&nic->free_packet_queue_mutex, NULL);
|
|
-
|
|
- pthread_cond_init(&nic->enable_wait_cond, NULL);
|
|
- pthread_cond_init(&nic->enable_done_cond, NULL);
|
|
- pthread_cond_init(&nic->nic_loop_started_cond, NULL);
|
|
- pthread_cond_init(&nic->disable_wait_cond, NULL);
|
|
-
|
|
- nic->rx_poll_usec = DEFAULT_RX_POLL_USEC;
|
|
-
|
|
- pthread_mutex_init(&nic->nl_process_mutex, NULL);
|
|
- pthread_cond_init(&nic->nl_process_if_down_cond, NULL);
|
|
- pthread_cond_init(&nic->nl_process_cond, NULL);
|
|
- nic->nl_process_thread = INVALID_THREAD;
|
|
- nic->nl_process_if_down = 0;
|
|
- nic->nl_process_head = 0;
|
|
- nic->nl_process_tail = 0;
|
|
- memset(&nic->nl_process_ring, 0, sizeof(nic->nl_process_ring));
|
|
-
|
|
- nic->ping_thread = INVALID_THREAD;
|
|
-
|
|
- return nic;
|
|
-}
|
|
-
|
|
-void nic_add(nic_t *nic)
|
|
-{
|
|
- /* Add this device to our list of nics */
|
|
- if (nic_list == NULL) {
|
|
- nic_list = nic;
|
|
- } else {
|
|
- nic_t *current = nic_list;
|
|
-
|
|
- while (current->next != NULL)
|
|
- current = current->next;
|
|
-
|
|
- current->next = nic;
|
|
- }
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_remove() - Used to remove the NIC for the nic list
|
|
- * @param nic - the nic to remove
|
|
- */
|
|
-int nic_remove(nic_t *nic)
|
|
-{
|
|
- int rc;
|
|
- nic_t *prev, *current;
|
|
- struct stat file_stat;
|
|
- nic_interface_t *nic_iface, *next_nic_iface, *vlan_iface;
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- /* Check if the file node exists before closing */
|
|
- if (nic->uio_device_name) {
|
|
- rc = stat(nic->uio_device_name, &file_stat);
|
|
- if ((rc == 0) && (nic->ops))
|
|
- nic->ops->close(nic, 0);
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- nic->state = NIC_EXIT;
|
|
-
|
|
- if (nic->enable_thread != INVALID_THREAD) {
|
|
- LOG_DEBUG(PFX "%s: Canceling nic enable thread", nic->log_name);
|
|
-
|
|
- rc = pthread_cancel(nic->enable_thread);
|
|
- if (rc != 0)
|
|
- LOG_DEBUG(PFX "%s: Couldn't send cancel to nic enable "
|
|
- "thread", nic->log_name);
|
|
-
|
|
- nic->enable_thread = INVALID_THREAD;
|
|
- LOG_DEBUG(PFX "%s: nic enable thread cleaned", nic->log_name);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: NIC enable thread already canceled",
|
|
- nic->log_name);
|
|
- }
|
|
-
|
|
- if (nic->thread != INVALID_THREAD) {
|
|
- LOG_DEBUG(PFX "%s: Canceling nic thread", nic->log_name);
|
|
-
|
|
- rc = pthread_cancel(nic->thread);
|
|
- if (rc != 0)
|
|
- LOG_DEBUG(PFX "%s: Couldn't send cancel to nic",
|
|
- nic->log_name);
|
|
-
|
|
- nic->thread = INVALID_THREAD;
|
|
- LOG_DEBUG(PFX "%s: nic thread cleaned", nic->log_name);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: NIC thread already canceled", nic->log_name);
|
|
- }
|
|
-
|
|
- if (nic->nl_process_thread != INVALID_THREAD) {
|
|
- LOG_DEBUG(PFX "%s: Canceling nic nl thread", nic->log_name);
|
|
-
|
|
- rc = pthread_cancel(nic->nl_process_thread);
|
|
- if (rc != 0)
|
|
- LOG_DEBUG(PFX "%s: Couldn't send cancel to nic nl "
|
|
- "thread", nic->log_name);
|
|
-
|
|
- nic->nl_process_thread = INVALID_THREAD;
|
|
- LOG_DEBUG(PFX "%s: nic nl thread cleaned", nic->log_name);
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: NIC nl thread already canceled",
|
|
- nic->log_name);
|
|
- }
|
|
-
|
|
- current = prev = nic_list;
|
|
- while (current != NULL) {
|
|
- if (current == nic)
|
|
- break;
|
|
-
|
|
- prev = current;
|
|
- current = current->next;
|
|
- }
|
|
-
|
|
- if (current != NULL) {
|
|
- if (current == nic_list)
|
|
- nic_list = current->next;
|
|
- else
|
|
- prev->next = current->next;
|
|
-
|
|
- /* Before freeing the nic, must free all the associated
|
|
- nic_iface */
|
|
- nic_iface = current->nic_iface;
|
|
- while (nic_iface != NULL) {
|
|
- vlan_iface = nic_iface->vlan_next;
|
|
- while (vlan_iface != NULL) {
|
|
- next_nic_iface = vlan_iface->vlan_next;
|
|
- free(vlan_iface);
|
|
- vlan_iface = next_nic_iface;
|
|
- }
|
|
- next_nic_iface = nic_iface->next;
|
|
- free(nic_iface);
|
|
- nic_iface = next_nic_iface;
|
|
- }
|
|
- free(nic);
|
|
- } else {
|
|
- LOG_ERR(PFX "%s: Couldn't find nic to remove", nic->log_name);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_close() - Used to indicate to a NIC that it should close
|
|
- * Must be called with nic->nic_mutex
|
|
- * @param nic - the nic to close
|
|
- * @param graceful - ALLOW_GRACEFUL_SHUTDOWN will check the nic state
|
|
- * before proceeding to close()
|
|
- * FORCE_SHUTDOWN will force the nic to close()
|
|
- * reguardless of the state
|
|
- * @param clean - this will free the proper strings assoicated
|
|
- * with the NIC
|
|
- *
|
|
- */
|
|
-void nic_close(nic_t *nic, NIC_SHUTDOWN_T graceful, int clean)
|
|
-{
|
|
- int rc;
|
|
- nic_interface_t *nic_iface, *vlan_iface;
|
|
- struct stat file_stat;
|
|
-
|
|
- /* The NIC could be configured by the uIP config file
|
|
- * but not assoicated with a hardware library just yet
|
|
- * we will need to check for this */
|
|
- if (nic->ops == NULL) {
|
|
- LOG_WARN(PFX "%s: when closing nic->ops == NULL",
|
|
- nic->log_name);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* Check if the file node exists */
|
|
- rc = stat(nic->uio_device_name, &file_stat);
|
|
- if ((rc == 0) && (nic->ops))
|
|
- rc = (*nic->ops->close) (nic, graceful);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not close nic", nic->log_name);
|
|
- } else {
|
|
- nic->state = NIC_STOPPED;
|
|
- nic->flags &= ~NIC_ENABLED;
|
|
- nic->flags |= NIC_DISABLED;
|
|
- }
|
|
-
|
|
- nic_iface = nic->nic_iface;
|
|
- while (nic_iface != NULL) {
|
|
- if (!((nic_iface->flags & NIC_IFACE_PERSIST) ==
|
|
- NIC_IFACE_PERSIST)) {
|
|
- uip_reset(&nic_iface->ustack);
|
|
- vlan_iface = nic_iface->vlan_next;
|
|
- while (vlan_iface != NULL) {
|
|
- uip_reset(&vlan_iface->ustack);
|
|
- vlan_iface = vlan_iface->vlan_next;
|
|
- }
|
|
- }
|
|
- nic_iface = nic_iface->next;
|
|
- }
|
|
-
|
|
- /* The NIC must be destroyed and init'ed once again,
|
|
- * POSIX defines that the mutex will be undefined it
|
|
- * init'ed twice without a destroy */
|
|
- pthread_mutex_destroy(&nic->xmit_mutex);
|
|
- pthread_mutex_init(&nic->xmit_mutex, NULL);
|
|
-
|
|
- if (clean & FREE_CONFIG_NAME) {
|
|
- /* Free any named strings we might be holding onto */
|
|
- if (nic->flags & NIC_CONFIG_NAME_MALLOC) {
|
|
- free(nic->config_device_name);
|
|
- nic->flags &= ~NIC_CONFIG_NAME_MALLOC;
|
|
- }
|
|
- nic->config_device_name = NULL;
|
|
- }
|
|
-
|
|
- if (clean & FREE_UIO_NAME) {
|
|
- if (nic->flags & NIC_UIO_NAME_MALLOC) {
|
|
- free(nic->uio_device_name);
|
|
- nic->uio_device_name = NULL;
|
|
-
|
|
- nic->flags &= ~NIC_UIO_NAME_MALLOC;
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_ERR(PFX "%s: nic closed", nic->log_name);
|
|
-error:
|
|
- return;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_iface_init() - This function is used to add an interface to the
|
|
- * structure cnic_uio
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-nic_interface_t *nic_iface_init()
|
|
-{
|
|
- nic_interface_t *nic_iface = malloc(sizeof(*nic_iface));
|
|
- if (nic_iface == NULL) {
|
|
- LOG_ERR("Could not allocate space for nic iface");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- memset(nic_iface, 0, sizeof(*nic_iface));
|
|
- nic_iface->next = NULL;
|
|
- nic_iface->vlan_next = NULL;
|
|
- nic_iface->iface_num = IFACE_NUM_INVALID;
|
|
- nic_iface->request_type = IP_CONFIG_OFF;
|
|
-
|
|
- return nic_iface;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_add_nic_iface() - This function is used to add an interface to the
|
|
- * nic structure
|
|
- * Called with nic_mutex held
|
|
- * @param nic - struct nic device to add the interface to
|
|
- * @param nic_iface - network interface used to add to the nic
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
|
|
-{
|
|
- nic_interface_t *current, *prev;
|
|
-
|
|
- /* Make sure it doesn't already exist */
|
|
- current = nic_find_nic_iface(nic, nic_iface->protocol,
|
|
- nic_iface->vlan_id, nic_iface->iface_num,
|
|
- nic_iface->request_type);
|
|
- if (current) {
|
|
- LOG_DEBUG(PFX "%s: nic interface for VLAN: %d, protocol: %d"
|
|
- " already exist", nic->log_name, nic_iface->vlan_id,
|
|
- nic_iface->protocol);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- prev = NULL;
|
|
- current = nic->nic_iface;
|
|
- while (current != NULL) {
|
|
- if (current->protocol == nic_iface->protocol) {
|
|
- /* Replace parent */
|
|
- nic_iface->vlan_next = current;
|
|
- nic_iface->next = current->next;
|
|
- current->next = NULL;
|
|
- if (prev)
|
|
- prev->next = nic_iface;
|
|
- else
|
|
- nic->nic_iface = nic_iface;
|
|
- goto done;
|
|
- }
|
|
- prev = current;
|
|
- current = current->next;
|
|
- }
|
|
- nic_iface->next = nic->nic_iface;
|
|
- nic->nic_iface = nic_iface;
|
|
-done:
|
|
- /* Set nic_interface common fields */
|
|
- nic_iface->parent = nic;
|
|
- memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
|
|
- nic->num_of_nic_iface++;
|
|
-
|
|
- LOG_INFO(PFX "%s: Added nic interface for VLAN: %d, protocol: %d",
|
|
- nic->log_name, nic_iface->vlan_id, nic_iface->protocol);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/******************************************************************************
|
|
- * Routine to process interrupts from the NIC device
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * nic_process_intr() - Routine used to process interrupts from the hardware
|
|
- * @param nic - NIC hardware to process the interrupt on
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int nic_process_intr(nic_t *nic, int discard_check)
|
|
-{
|
|
- fd_set fdset;
|
|
- int ret;
|
|
- int count;
|
|
- struct timeval tv;
|
|
-
|
|
- /* Simple sanity checks */
|
|
- if (discard_check != 1 && nic->state != NIC_RUNNING) {
|
|
- LOG_ERR(PFX "%s: Couldn't process interrupt NIC not running",
|
|
- nic->log_name);
|
|
- return -EBUSY;
|
|
- }
|
|
-
|
|
- if (discard_check != 1 && nic->fd == INVALID_FD) {
|
|
- LOG_ERR(PFX "%s: NIC fd not valid", nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- FD_ZERO(&fdset);
|
|
- FD_SET(nic->fd, &fdset);
|
|
-
|
|
- tv.tv_sec = 0;
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (nic->flags & NIC_LONG_SLEEP)
|
|
- tv.tv_usec = 1000;
|
|
- else
|
|
- tv.tv_usec = nic->rx_poll_usec;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- /* Wait for an interrupt to come in or timeout */
|
|
- ret = select(nic->fd + 1, &fdset, NULL, NULL, &tv);
|
|
- switch (ret) {
|
|
- case 1:
|
|
- /* Usually there should only be one file descriptor ready
|
|
- * to read */
|
|
- break;
|
|
- case 0:
|
|
- return ret;
|
|
- case -1:
|
|
- LOG_ERR(PFX "%s: error waiting for interrupt: %s",
|
|
- nic->log_name, strerror(errno));
|
|
- return 0;
|
|
- default:
|
|
- LOG_ERR(PFX "%s: unknown number of FD's, ignoring: %d ret",
|
|
- nic->log_name, ret);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- ret = read(nic->fd, &count, sizeof(count));
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (ret > 0) {
|
|
- nic->stats.interrupts++;
|
|
- LOG_PACKET(PFX "%s: interrupt count: %d prev: %d",
|
|
- nic->log_name, count, nic->intr_count);
|
|
-
|
|
- if (count == nic->intr_count) {
|
|
- LOG_PACKET(PFX "%s: got interrupt but count still the "
|
|
- "same", nic->log_name, count);
|
|
- }
|
|
-
|
|
- /* Check if we missed an interrupt. With UIO,
|
|
- * the count should be incremental */
|
|
- if (count != nic->intr_count + 1) {
|
|
- nic->stats.missed_interrupts++;
|
|
- LOG_PACKET(PFX "%s: Missed interrupt! on %d not %d",
|
|
- nic->log_name, count, nic->intr_count);
|
|
- }
|
|
-
|
|
- nic->intr_count = count;
|
|
-
|
|
- if (strcmp(nic->ops->description, "qedi")) {
|
|
- LOG_DEBUG(PFX "%s: host:%d - calling clear_tx_intr from process_intr",
|
|
- nic->log_name, nic->host_no);
|
|
- (*nic->ops->clear_tx_intr) (nic);
|
|
- }
|
|
-
|
|
- ret = 1;
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void prepare_ipv4_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, packet_t *pkt)
|
|
-{
|
|
- u16_t ipaddr[2];
|
|
- arp_table_query_t arp_query;
|
|
- dest_ipv4_addr_t dest_ipv4_addr;
|
|
- struct arp_entry *tabptr;
|
|
- int queue_rc;
|
|
- int vlan_id = 0;
|
|
-
|
|
- /* If the rx vlan tag is not stripped and vlan is present in the pkt,
|
|
- manual stripping is required because tx is using hw vlan tag! */
|
|
- if (pkt->network_layer == pkt->data_link_layer +
|
|
- sizeof(struct uip_vlan_eth_hdr)) {
|
|
- /* VLAN is detected in the pkt buf */
|
|
- memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
|
|
- pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
|
|
- }
|
|
- dest_ipv4_addr = uip_determine_dest_ipv4_addr(ustack, ipaddr);
|
|
- if (dest_ipv4_addr == LOCAL_BROADCAST) {
|
|
- uip_build_eth_header(ustack, ipaddr, NULL, pkt, vlan_id);
|
|
- return;
|
|
- }
|
|
-
|
|
- arp_query = is_in_arp_table(ipaddr, &tabptr);
|
|
-
|
|
- switch (arp_query) {
|
|
- case IS_IN_ARP_TABLE:
|
|
- uip_build_eth_header(ustack,
|
|
- ipaddr, tabptr, pkt, vlan_id);
|
|
- break;
|
|
- case NOT_IN_ARP_TABLE:
|
|
- queue_rc = nic_queue_tx_packet(nic, nic_iface, pkt);
|
|
- if (queue_rc) {
|
|
- LOG_ERR("could not queue TX packet: %d", queue_rc);
|
|
- } else {
|
|
- uip_build_arp_request(ustack, ipaddr);
|
|
- }
|
|
- break;
|
|
- default:
|
|
- LOG_ERR("Unknown arp state");
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-void prepare_ipv6_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, packet_t *pkt)
|
|
-{
|
|
- struct uip_eth_hdr *eth;
|
|
- struct uip_vlan_eth_hdr *eth_vlan;
|
|
- int vlan_id = 0;
|
|
-
|
|
- if (pkt->network_layer == pkt->data_link_layer +
|
|
- sizeof(struct uip_vlan_eth_hdr)) {
|
|
- /* VLAN is detected in the pkt buf */
|
|
- memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
|
|
- pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
|
|
- }
|
|
- eth = (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
- eth_vlan = (struct uip_vlan_eth_hdr *)ustack->data_link_layer;
|
|
- if (vlan_id == 0) {
|
|
- eth->type = htons(UIP_ETHTYPE_IPv6);
|
|
- } else {
|
|
- eth_vlan->tpid = htons(UIP_ETHTYPE_8021Q);
|
|
- eth_vlan->vid = htons(vlan_id);
|
|
- eth_vlan->type = htons(UIP_ETHTYPE_IPv6);
|
|
- }
|
|
-}
|
|
-
|
|
-void prepare_ustack(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, struct packet *pkt)
|
|
-{
|
|
- struct ether_header *eth = NULL;
|
|
- ustack->uip_buf = pkt->buf;
|
|
- ustack->uip_len = pkt->buf_size;
|
|
-
|
|
- pkt->nic = nic;
|
|
- pkt->nic_iface = nic_iface;
|
|
-
|
|
- ustack->data_link_layer = pkt->buf;
|
|
- /* Adjust the network layer pointer depending if
|
|
- * there is a VLAN tag or not, or if the hardware
|
|
- * has stripped out the
|
|
- * VLAN tag */
|
|
- ustack->network_layer = ustack->data_link_layer +
|
|
- sizeof(struct uip_eth_hdr);
|
|
- /* Init buffer to be IPv6 */
|
|
- if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
|
|
- nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
|
|
- eth = (struct ether_header *)ustack->data_link_layer;
|
|
- eth->ether_type = htons(UIP_ETHTYPE_IPv6);
|
|
- }
|
|
-}
|
|
-
|
|
-int do_timers_per_nic_iface(nic_t *nic, nic_interface_t *nic_iface,
|
|
- struct timer *arp_timer)
|
|
-{
|
|
- packet_t *pkt;
|
|
- struct uip_stack *ustack = &nic_iface->ustack;
|
|
- int i;
|
|
-
|
|
- pkt = get_next_free_packet(nic);
|
|
- if (pkt == NULL)
|
|
- return -EIO;
|
|
-
|
|
- if (nic_iface->protocol == AF_INET) {
|
|
- for (i = 0; i < UIP_UDP_CONNS; i++) {
|
|
- prepare_ustack(nic, nic_iface, ustack, pkt);
|
|
-
|
|
- uip_udp_periodic(ustack, i);
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len is
|
|
- * set to a value > 0. */
|
|
- if (ustack->uip_len > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
-
|
|
- prepare_ipv4_packet(nic, nic_iface, ustack,
|
|
- pkt);
|
|
-
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- ustack->uip_len = 0;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- /* Added periodic poll for IPv6 NDP engine */
|
|
- if (ustack->ndpc != NULL) { /* If engine is active */
|
|
- prepare_ustack(nic, nic_iface, ustack, pkt);
|
|
-
|
|
- uip_ndp_periodic(ustack);
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len is
|
|
- * set to a value > 0. */
|
|
- if (ustack->uip_len > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
- prepare_ipv6_packet(nic, nic_iface, ustack,
|
|
- pkt);
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- ustack->uip_len = 0;
|
|
- }
|
|
- }
|
|
- }
|
|
- /* Call the ARP timer function every 10 seconds. */
|
|
- if (timer_expired(arp_timer)) {
|
|
- timer_reset(arp_timer);
|
|
- uip_arp_timer();
|
|
- }
|
|
- put_packet_in_free_queue(pkt, nic);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int check_timers(nic_t *nic,
|
|
- struct timer *periodic_timer, struct timer *arp_timer)
|
|
-{
|
|
- if (timer_expired(periodic_timer)) {
|
|
- nic_interface_t *nic_iface, *vlan_iface;
|
|
-
|
|
- timer_reset(periodic_timer);
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic_iface = nic->nic_iface;
|
|
- while (nic_iface != NULL) {
|
|
- do_timers_per_nic_iface(nic, nic_iface, arp_timer);
|
|
- vlan_iface = nic_iface->vlan_next;
|
|
- while (vlan_iface != NULL) {
|
|
- do_timers_per_nic_iface(nic, vlan_iface,
|
|
- arp_timer);
|
|
- vlan_iface = vlan_iface->vlan_next;
|
|
- }
|
|
- nic_iface = nic_iface->next;
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int process_packets(nic_t *nic,
|
|
- struct timer *periodic_timer,
|
|
- struct timer *arp_timer, nic_interface_t *nic_iface)
|
|
-{
|
|
- int rc;
|
|
- packet_t *pkt;
|
|
-
|
|
- pkt = get_next_free_packet(nic);
|
|
- if (pkt == NULL) {
|
|
- LOG_DEBUG(PFX "%s: Couldn't get buffer for processing packet",
|
|
- nic->log_name);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- rc = (*nic->ops->read) (nic, pkt);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- if ((rc != 0) && (pkt->buf_size > 0)) {
|
|
- uint16_t type = 0;
|
|
- int af_type = 0;
|
|
- struct uip_stack *ustack;
|
|
- uint16_t vlan_id;
|
|
-
|
|
- pkt->data_link_layer = pkt->buf;
|
|
-
|
|
- vlan_id = pkt->vlan_tag & 0xFFF;
|
|
- if ((vlan_id == 0) ||
|
|
- (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
|
|
- struct uip_eth_hdr *hdr = ETH_BUF(pkt->buf);
|
|
- type = ntohs(hdr->type);
|
|
- pkt->network_layer = pkt->data_link_layer +
|
|
- sizeof(struct uip_eth_hdr);
|
|
- } else {
|
|
- struct uip_vlan_eth_hdr *hdr = VLAN_ETH_BUF(pkt->buf);
|
|
- type = ntohs(hdr->type);
|
|
- pkt->network_layer = pkt->data_link_layer +
|
|
- sizeof(struct uip_vlan_eth_hdr);
|
|
- }
|
|
-
|
|
- switch (type) {
|
|
- case UIP_ETHTYPE_IPv6:
|
|
- af_type = AF_INET6;
|
|
- break;
|
|
- case UIP_ETHTYPE_IPv4:
|
|
- case UIP_ETHTYPE_ARP:
|
|
- af_type = AF_INET;
|
|
- LOG_DEBUG(PFX "%s: ARP or IPv4 vlan:0x%x ethertype:0x%x",
|
|
- nic->log_name, vlan_id, type);
|
|
- break;
|
|
- default:
|
|
- LOG_DEBUG(PFX "%s: Ignoring vlan:0x%x ethertype:0x%x",
|
|
- nic->log_name, vlan_id, type);
|
|
- goto done;
|
|
- }
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- /* check if we have the given VLAN interface */
|
|
- if (nic_iface != NULL) {
|
|
- if (vlan_id != nic_iface->vlan_id) {
|
|
- /* Matching nic_iface not found, drop */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- rc = EINVAL; /* Return the +error code */
|
|
- goto done;
|
|
- }
|
|
- goto nic_iface_present;
|
|
- }
|
|
-
|
|
- /* Best effort to find the correct instance
|
|
- Input: protocol and vlan_tag */
|
|
- nic_iface = nic_find_nic_iface(nic, af_type, vlan_id,
|
|
- IFACE_NUM_INVALID,
|
|
- IP_CONFIG_OFF);
|
|
- if (nic_iface == NULL) {
|
|
- /* Matching nic_iface not found */
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_DEBUG(PFX "%s: Couldn't find interface for "
|
|
- "VLAN: %d af_type %d",
|
|
- nic->log_name, vlan_id, af_type);
|
|
- rc = EINVAL; /* Return the +error code */
|
|
- goto done;
|
|
- }
|
|
-nic_iface_present:
|
|
- pkt->nic_iface = nic_iface;
|
|
- LOG_DEBUG(PFX "%s: found nic iface, type=0x%x, bufsize=%d",
|
|
- nic->log_name, type, pkt->buf_size);
|
|
-
|
|
- ustack = &nic_iface->ustack;
|
|
-
|
|
- ustack->uip_buf = pkt->buf;
|
|
- ustack->uip_len = pkt->buf_size;
|
|
- ustack->data_link_layer = pkt->buf;
|
|
-
|
|
- /* Adjust the network layer pointer depending if there is a
|
|
- * VLAN tag or not, or if the hardware has stripped out the
|
|
- * VLAN tag */
|
|
- if ((vlan_id == 0) ||
|
|
- (NIC_VLAN_STRIP_ENABLED & nic->flags))
|
|
- ustack->network_layer = ustack->data_link_layer +
|
|
- sizeof(struct uip_eth_hdr);
|
|
- else
|
|
- ustack->network_layer = ustack->data_link_layer +
|
|
- sizeof(struct uip_vlan_eth_hdr);
|
|
-
|
|
- /* determine how we should process this packet based on the
|
|
- * ethernet type */
|
|
- switch (type) {
|
|
- case UIP_ETHTYPE_IPv6:
|
|
- uip_input(ustack);
|
|
- if (ustack->uip_len > 0) {
|
|
- /* The pkt generated has already consulted
|
|
- the IPv6 ARP table */
|
|
- pkt->buf_size = ustack->uip_len;
|
|
- prepare_ipv6_packet(nic, nic_iface,
|
|
- ustack, pkt);
|
|
-
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- }
|
|
- break;
|
|
- case UIP_ETHTYPE_IPv4:
|
|
- uip_arp_ipin(ustack, pkt);
|
|
- uip_input(ustack);
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len is
|
|
- * set to a value > 0. */
|
|
- if (ustack->uip_len > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
- prepare_ipv4_packet(nic, nic_iface,
|
|
- ustack, pkt);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: write called after arp_ipin, uip_len=%d",
|
|
- nic->log_name, ustack->uip_len);
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- }
|
|
-
|
|
- break;
|
|
- case UIP_ETHTYPE_ARP:
|
|
- uip_arp_arpin(nic_iface, ustack, pkt);
|
|
-
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len
|
|
- * is set to a value > 0. */
|
|
- if (pkt->buf_size > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
- LOG_DEBUG(PFX "%s: write called after arp_arpin, bufsize=%d",
|
|
- nic->log_name, pkt->buf_size);
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- }
|
|
- break;
|
|
- }
|
|
- ustack->uip_len = 0;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- }
|
|
-
|
|
-done:
|
|
- put_packet_in_free_queue(pkt, nic);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int process_dhcp_loop(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct timer *periodic_timer,
|
|
- struct timer *arp_timer)
|
|
-{
|
|
- struct dhcpc_state *s;
|
|
- struct ndpc_state *n;
|
|
- int rc;
|
|
- struct timeval start_time;
|
|
- struct timeval current_time;
|
|
- struct timeval wait_time;
|
|
- struct timeval total_time;
|
|
-
|
|
- /* 10s loop time to wait for DHCP */
|
|
- switch (nic_iface->ustack.ip_config) {
|
|
- case IPV4_CONFIG_DHCP:
|
|
- wait_time.tv_sec = 10;
|
|
- break;
|
|
- case IPV6_CONFIG_DHCP:
|
|
- wait_time.tv_sec = 15;
|
|
- break;
|
|
- case IPV6_CONFIG_STATIC:
|
|
- wait_time.tv_sec = 4;
|
|
- break;
|
|
- default:
|
|
- wait_time.tv_sec = 2;
|
|
- }
|
|
- wait_time.tv_usec = 0;
|
|
-
|
|
- s = nic_iface->ustack.dhcpc;
|
|
- n = nic_iface->ustack.ndpc;
|
|
-
|
|
- if (gettimeofday(&start_time, NULL)) {
|
|
- LOG_ERR(PFX "%s: Couldn't get time of day to start DHCP timer",
|
|
- nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- timeradd(&start_time, &wait_time, &total_time);
|
|
-
|
|
- periodic_timer->start = periodic_timer->start -
|
|
- periodic_timer->interval;
|
|
-
|
|
- while ((event_loop_stop == 0) &&
|
|
- (nic->flags & NIC_ENABLED) && !(nic->flags & NIC_GOING_DOWN)) {
|
|
-
|
|
- if (nic_iface->ustack.ip_config == IPV4_CONFIG_DHCP) {
|
|
- if (s->state == STATE_CONFIG_RECEIVED)
|
|
- break;
|
|
- }
|
|
- if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
|
|
- nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
|
|
- if (n->state == NDPC_STATE_BACKGROUND_LOOP)
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Check the periodic and ARP timer */
|
|
- check_timers(nic, periodic_timer, arp_timer);
|
|
-
|
|
- rc = nic_process_intr(nic, 1);
|
|
-
|
|
- while ((rc > 0) && (!(nic->flags & NIC_GOING_DOWN))) {
|
|
- rc = process_packets(nic,
|
|
- periodic_timer,
|
|
- arp_timer, nic_iface);
|
|
- }
|
|
-
|
|
- if (gettimeofday(¤t_time, NULL)) {
|
|
- LOG_ERR(PFX "%s: Couldn't get current time for "
|
|
- "DHCP start", nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- if (timercmp(&total_time, ¤t_time, <)) {
|
|
- LOG_ERR(PFX "%s: timeout waiting for DHCP/NDP",
|
|
- nic->log_name);
|
|
- if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
|
|
- nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC)
|
|
- n->retry_count = IPV6_MAX_ROUTER_SOL_RETRY;
|
|
- return -EIO;
|
|
- }
|
|
- }
|
|
-
|
|
- if (nic->flags & NIC_GOING_DOWN)
|
|
- return -EIO;
|
|
- else if (nic->flags & NIC_DISABLED)
|
|
- return -EINVAL;
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Called with nic_mutex locked */
|
|
-static int do_acquisition(nic_t *nic, nic_interface_t *nic_iface,
|
|
- struct timer *periodic_timer, struct timer *arp_timer)
|
|
-{
|
|
- struct in_addr addr;
|
|
- struct in6_addr addr6;
|
|
- char buf[INET6_ADDRSTRLEN];
|
|
- int rc = -1;
|
|
-
|
|
- /* New acquisition */
|
|
- uip_init(&nic_iface->ustack, nic->flags & NIC_IPv6_ENABLED);
|
|
- memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
|
|
-
|
|
- LOG_INFO(PFX "%s: Initialized ip stack: VLAN: %d",
|
|
- nic->log_name, nic_iface->vlan_id);
|
|
-
|
|
- LOG_INFO(PFX "%s: mac: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
- nic->log_name,
|
|
- nic_iface->mac_addr[0],
|
|
- nic_iface->mac_addr[1],
|
|
- nic_iface->mac_addr[2],
|
|
- nic_iface->mac_addr[3],
|
|
- nic_iface->mac_addr[4],
|
|
- nic_iface->mac_addr[5]);
|
|
-
|
|
- switch (nic_iface->ustack.ip_config) {
|
|
- case IPV4_CONFIG_STATIC:
|
|
- memcpy(&addr.s_addr, nic_iface->ustack.hostaddr,
|
|
- sizeof(addr.s_addr));
|
|
-
|
|
- LOG_INFO(PFX "%s: Using IP address: %s",
|
|
- nic->log_name, inet_ntoa(addr));
|
|
-
|
|
- memcpy(&addr.s_addr, nic_iface->ustack.netmask,
|
|
- sizeof(addr.s_addr));
|
|
-
|
|
- LOG_INFO(PFX "%s: Using netmask: %s",
|
|
- nic->log_name, inet_ntoa(addr));
|
|
-
|
|
- set_uip_stack(&nic_iface->ustack,
|
|
- NULL, NULL, NULL,
|
|
- nic_iface->mac_addr);
|
|
- break;
|
|
-
|
|
- case IPV4_CONFIG_DHCP:
|
|
- set_uip_stack(&nic_iface->ustack,
|
|
- NULL, NULL, NULL,
|
|
- nic_iface->mac_addr);
|
|
- if (dhcpc_init(nic, &nic_iface->ustack,
|
|
- nic_iface->mac_addr, ETH_ALEN)) {
|
|
- if (nic_iface->ustack.dhcpc) {
|
|
- LOG_DEBUG(PFX "%s: DHCPv4 engine already "
|
|
- "initialized!", nic->log_name);
|
|
- goto skip;
|
|
- } else {
|
|
- LOG_DEBUG(PFX "%s: DHCPv4 engine failed "
|
|
- "initialization!", nic->log_name);
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
|
|
- arp_timer);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- if (rc) {
|
|
- LOG_ERR(PFX "%s: DHCP failed", nic->log_name);
|
|
- /* For DHCPv4 failure, the ustack must be cleaned so
|
|
- it can re-acquire on the next iscsid request */
|
|
- uip_reset(&nic_iface->ustack);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (nic->flags & NIC_DISABLED) {
|
|
- /* Break out of this loop */
|
|
- break;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: Initialized dhcp client", nic->log_name);
|
|
- break;
|
|
-
|
|
- case IPV6_CONFIG_DHCP:
|
|
- case IPV6_CONFIG_STATIC:
|
|
- if (ndpc_init(nic, &nic_iface->ustack, nic_iface->mac_addr,
|
|
- ETH_ALEN)) {
|
|
- LOG_DEBUG(PFX "%s: IPv6 engine already initialized!",
|
|
- nic->log_name);
|
|
- goto skip;
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
|
|
- arp_timer);
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (rc) {
|
|
- /* Don't reset and allow to use RA and LL */
|
|
- LOG_ERR(PFX "%s: IPv6 DHCP/NDP failed", nic->log_name);
|
|
- }
|
|
- if (nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
|
|
- memcpy(&addr6.s6_addr, nic_iface->ustack.hostaddr6,
|
|
- sizeof(addr6.s6_addr));
|
|
- inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
|
|
- LOG_INFO(PFX "%s: hostaddr IP: %s", nic->log_name, buf);
|
|
- memcpy(&addr6.s6_addr, nic_iface->ustack.netmask6,
|
|
- sizeof(addr6.s6_addr));
|
|
- inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
|
|
- LOG_INFO(PFX "%s: netmask IP: %s", nic->log_name, buf);
|
|
- }
|
|
- break;
|
|
-
|
|
- default:
|
|
- LOG_INFO(PFX "%s: ipconfig = %d?", nic->log_name,
|
|
- nic_iface->ustack.ip_config);
|
|
- }
|
|
-skip:
|
|
- /* Mark acquisition done for this nic iface */
|
|
- nic_iface->flags &= ~NIC_IFACE_ACQUIRE;
|
|
-
|
|
- LOG_INFO(PFX "%s: enabled vlan %d protocol: %d", nic->log_name,
|
|
- nic_iface->vlan_id, nic_iface->protocol);
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- return -EIO;
|
|
-}
|
|
-
|
|
-
|
|
-void *nic_loop(void *arg)
|
|
-{
|
|
- nic_t *nic = (nic_t *) arg;
|
|
- int rc = -1;
|
|
- sigset_t set;
|
|
- struct timer periodic_timer, arp_timer;
|
|
-
|
|
- sigfillset(&set);
|
|
- rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
|
|
- if (rc != 0) {
|
|
- /* TODO: determine if we need to exit this thread if we fail
|
|
- * to set the signal mask */
|
|
- LOG_ERR(PFX "%s: Couldn't set signal mask", nic->log_name);
|
|
- }
|
|
-
|
|
- /* Signal the device to enable itself */
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- pthread_cond_signal(&nic->nic_loop_started_cond);
|
|
-
|
|
- /* nic_mutex must be locked */
|
|
- while ((event_loop_stop == 0) &&
|
|
- !(nic->flags & NIC_EXIT_MAIN_LOOP) &&
|
|
- !(nic->flags & NIC_GOING_DOWN)) {
|
|
- nic_interface_t *nic_iface, *vlan_iface;
|
|
-
|
|
- if (nic->flags & NIC_DISABLED) {
|
|
- LOG_DEBUG(PFX "%s: Waiting to be enabled",
|
|
- nic->log_name);
|
|
-
|
|
- /* Wait for the device to be enabled */
|
|
- /* nic_mutex is already locked */
|
|
- pthread_cond_wait(&nic->enable_wait_cond,
|
|
- &nic->nic_mutex);
|
|
-
|
|
- if (nic->state == NIC_EXIT) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- pthread_exit(NULL);
|
|
- }
|
|
- LOG_DEBUG(PFX "%s: is now enabled", nic->log_name);
|
|
- }
|
|
- /* initialize the device to send/rec data */
|
|
- rc = (*nic->ops->open) (nic);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not initialize CNIC UIO device",
|
|
- nic->log_name);
|
|
-
|
|
- if (rc == -ENOTSUP)
|
|
- nic->flags |= NIC_EXIT_MAIN_LOOP;
|
|
- else
|
|
- nic->flags &= ~NIC_ENABLED;
|
|
-
|
|
- /* Signal that the device enable is done */
|
|
- pthread_cond_broadcast(&nic->enable_done_cond);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- goto dev_close;
|
|
- }
|
|
- nic_set_all_nic_iface_mac_to_parent(nic);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- rc = alloc_free_queue(nic, 5);
|
|
- if (rc != 5) {
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s: Allocated %d packets "
|
|
- "instead of %d", nic->log_name, rc, 5);
|
|
- } else {
|
|
- LOG_ERR(PFX "%s: No packets allocated "
|
|
- "instead of %d", nic->log_name, 5);
|
|
- /* Signal that the device enable is done */
|
|
- pthread_cond_broadcast(&nic->enable_done_cond);
|
|
- goto dev_close;
|
|
- }
|
|
- }
|
|
- /* Indication for the nic_disable routine that the nic
|
|
- has started running */
|
|
- nic->state = NIC_STARTED_RUNNING;
|
|
-
|
|
- /* Initialize the system clocks */
|
|
- timer_set(&periodic_timer, CLOCK_SECOND / 2);
|
|
- timer_set(&arp_timer, CLOCK_SECOND * 10);
|
|
-
|
|
- /* Prepare the stack for each of the VLAN interfaces */
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- /* If DHCP fails, exit loop and restart the engine */
|
|
- nic_iface = nic->nic_iface;
|
|
- while (nic_iface != NULL) {
|
|
- if (nic_iface->flags & NIC_IFACE_ACQUIRE) {
|
|
- do_acquisition(nic, nic_iface,
|
|
- &periodic_timer,
|
|
- &arp_timer);
|
|
- }
|
|
- vlan_iface = nic_iface->vlan_next;
|
|
- while (vlan_iface != NULL) {
|
|
- if (vlan_iface->flags & NIC_IFACE_ACQUIRE) {
|
|
- do_acquisition(nic, vlan_iface,
|
|
- &periodic_timer,
|
|
- &arp_timer);
|
|
- }
|
|
- vlan_iface = vlan_iface->next;
|
|
- }
|
|
- nic_iface = nic_iface->next;
|
|
- }
|
|
- if (nic->flags & NIC_DISABLED) {
|
|
- LOG_WARN(PFX "%s: nic was disabled during nic loop, "
|
|
- "closing flag 0x%x",
|
|
- nic->log_name, nic->flags);
|
|
- /* Signal that the device enable is done */
|
|
- pthread_cond_broadcast(&nic->enable_done_cond);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- goto dev_close_free;
|
|
- }
|
|
-
|
|
- /* This is when we start the processing of packets */
|
|
- nic->start_time = time(NULL);
|
|
- nic->state = NIC_RUNNING;
|
|
-
|
|
- nic->flags &= ~NIC_ENABLED_PENDING;
|
|
-
|
|
- /* Signal that the device enable is done */
|
|
- pthread_cond_broadcast(&nic->enable_done_cond);
|
|
-
|
|
- LOG_INFO(PFX "%s: entering main nic loop", nic->log_name);
|
|
-
|
|
- while ((nic->state == NIC_RUNNING) &&
|
|
- (event_loop_stop == 0) &&
|
|
- !(nic->flags & NIC_GOING_DOWN)) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- /* Check the periodic and ARP timer */
|
|
- check_timers(nic, &periodic_timer, &arp_timer);
|
|
- rc = nic_process_intr(nic, 0);
|
|
- while ((rc > 0) &&
|
|
- (nic->state == NIC_RUNNING) &&
|
|
- !(nic->flags & NIC_GOING_DOWN)) {
|
|
- rc = process_packets(nic,
|
|
- &periodic_timer,
|
|
- &arp_timer, NULL);
|
|
- }
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: exited main processing loop", nic->log_name);
|
|
-
|
|
-dev_close_free:
|
|
- free_free_queue(nic);
|
|
-dev_close:
|
|
-
|
|
- if (nic->flags & NIC_GOING_DOWN) {
|
|
- nic_close(nic, 1, FREE_NO_STRINGS);
|
|
-
|
|
- nic->flags &= ~NIC_GOING_DOWN;
|
|
- } else {
|
|
- pthread_mutex_destroy(&nic->xmit_mutex);
|
|
- pthread_mutex_init(&nic->xmit_mutex, NULL);
|
|
- }
|
|
- nic->pending_count = 0;
|
|
-
|
|
- if (!(nic->flags & NIC_EXIT_MAIN_LOOP)) {
|
|
- /* Signal we are done closing CNIC/UIO device */
|
|
- pthread_cond_broadcast(&nic->disable_wait_cond);
|
|
- }
|
|
- }
|
|
- /* clean up the nic flags */
|
|
- nic->flags &= ~NIC_ENABLED_PENDING;
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- LOG_INFO(PFX "%s: nic loop thread exited", nic->log_name);
|
|
-
|
|
- nic->thread = INVALID_THREAD;
|
|
-
|
|
- pthread_exit(NULL);
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic.h b/iscsiuio/src/unix/nic.h
|
|
deleted file mode 100644
|
|
index 2c41e6e..0000000
|
|
--- a/iscsiuio/src/unix/nic.h
|
|
+++ /dev/null
|
|
@@ -1,407 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic.h - NIC header file
|
|
- *
|
|
- */
|
|
-
|
|
-#include <errno.h>
|
|
-
|
|
-#ifndef __NIC_H__
|
|
-#define __NIC_H__
|
|
-
|
|
-#include <stdint.h>
|
|
-#include <netinet/if_ether.h>
|
|
-#include <net/if.h>
|
|
-#include <linux/limits.h>
|
|
-#include <stdlib.h>
|
|
-#include <pthread.h>
|
|
-
|
|
-#include "nic_nl.h"
|
|
-#include "packet.h"
|
|
-#include "uip.h"
|
|
-#include "timer.h"
|
|
-
|
|
-#include "iscsi_if.h"
|
|
-
|
|
-/* Foward declarations */
|
|
-struct nic_ops;
|
|
-struct nic_lib_handle;
|
|
-struct packet;
|
|
-struct nic_op;
|
|
-
|
|
-extern pthread_mutex_t nic_lib_list_mutex;
|
|
-extern struct nic_lib_handle *nic_lib_list;
|
|
-
|
|
-/* Used to store a list of active cnic devices */
|
|
-extern pthread_mutex_t nic_list_mutex;
|
|
-extern struct nic *nic_list;
|
|
-
|
|
-extern void *nl_process_handle_thread(void *arg);
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define MAX_PCI_DEVICE_ENTRIES 64 /* Maxium number of pci_device_id
|
|
- entries a hw library may contain */
|
|
-
|
|
-#define FREE_CONFIG_NAME 0x0001
|
|
-#define FREE_UIO_NAME 0x0002
|
|
-#define FREE_ALL_STRINGS (FREE_CONFIG_NAME | FREE_UIO_NAME)
|
|
-#define FREE_NO_STRINGS 0x0000
|
|
-
|
|
-/******************************************************************************
|
|
- * Enumerations
|
|
- ******************************************************************************/
|
|
-typedef enum {
|
|
- ALLOW_GRACEFUL_SHUTDOWN = 1,
|
|
- FORCE_SHUTDOWN = 2,
|
|
-} NIC_SHUTDOWN_T;
|
|
-
|
|
-/*******************************************************************************
|
|
- * Structure used to hold PCI vendor, device, subvendor and subdevice ID's
|
|
- ******************************************************************************/
|
|
-struct pci_device_id {
|
|
- const uint32_t vendor, device; /* Vendor and device ID or PCI_ANY_ID */
|
|
- const uint32_t subvendor, subdevice; /* Subsystem ID's/PCI_ANY_ID */
|
|
- const char *device_name; /* Data private to the driver */
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * NIC statistics structure
|
|
- ******************************************************************************/
|
|
-struct nic_stats {
|
|
- uint64_t interrupts;
|
|
- uint64_t missed_interrupts;
|
|
-
|
|
- struct {
|
|
- uint64_t packets;
|
|
- uint64_t bytes;
|
|
- } tx;
|
|
-
|
|
- struct {
|
|
- uint64_t packets;
|
|
- uint64_t bytes;
|
|
- } rx;
|
|
-};
|
|
-
|
|
-/******************************************************************************
|
|
- * NIC interface structure
|
|
- ******************************************************************************/
|
|
-typedef struct nic_interface {
|
|
- struct nic_interface *vlan_next;
|
|
- struct nic_interface *next;
|
|
- struct nic *parent;
|
|
-
|
|
- uint16_t protocol;
|
|
- uint16_t flags;
|
|
-#define NIC_IFACE_PERSIST (1<<0)
|
|
-#define NIC_IFACE_ACQUIRE (1<<1)
|
|
-#define NIC_IFACE_PATHREQ_WAIT1 (1<<2)
|
|
-#define NIC_IFACE_PATHREQ_WAIT2 (1<<3)
|
|
-#define NIC_IFACE_PATHREQ_WAIT (NIC_IFACE_PATHREQ_WAIT1 | \
|
|
- NIC_IFACE_PATHREQ_WAIT2)
|
|
- uint8_t mac_addr[ETH_ALEN];
|
|
- uint8_t vlan_priority;
|
|
- uint16_t vlan_id;
|
|
-#define NO_VLAN 0x8000
|
|
-
|
|
- uint16_t mtu;
|
|
- time_t start_time;
|
|
-
|
|
- struct uip_stack ustack;
|
|
-
|
|
-#define IFACE_NUM_PRESENT (1<<0)
|
|
-#define IFACE_NUM_INVALID -1
|
|
- int iface_num;
|
|
- int request_type;
|
|
-} nic_interface_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * NIC lib operations structure
|
|
- ******************************************************************************/
|
|
-struct nic_lib_ops {
|
|
- /* Used to get the NIC library name */
|
|
- void (*get_library_name) (char **library_name,
|
|
- size_t *library_name_size);
|
|
-
|
|
- /* Used to get to the PCI table supported by the NIC library */
|
|
- void (*get_pci_table) (struct pci_device_id **table,
|
|
- uint32_t *entries);
|
|
-
|
|
- /* Used to get the version of this NIC library */
|
|
- void (*get_library_version) (char **version_string,
|
|
- size_t *version_string_size);
|
|
-
|
|
- /* Used to get the NIC library build date */
|
|
- void (*get_build_date) (char **build_date_string,
|
|
- size_t *build_date_string_size);
|
|
-
|
|
- /* Used to get the transport name assoicated with this library */
|
|
- void (*get_transport_name) (char **transport_name,
|
|
- size_t *transport_name_size);
|
|
-
|
|
- /* Used to get the uio name assoicated with this library */
|
|
- void (*get_uio_name) (char **uio_name, size_t *uio_name_size);
|
|
-
|
|
-};
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC op table definition
|
|
- ******************************************************************************/
|
|
-typedef struct nic_ops {
|
|
- struct nic_lib_ops lib_ops;
|
|
-
|
|
- char *description;
|
|
- int (*open) (struct nic *);
|
|
- int (*close) (struct nic *, NIC_SHUTDOWN_T);
|
|
- int (*read) (struct nic *, struct packet *);
|
|
- int (*write) (struct nic *, nic_interface_t *, struct packet *);
|
|
- void *(*get_tx_pkt) (struct nic *);
|
|
- void (*start_xmit) (struct nic *, size_t, u16_t vlan_id);
|
|
- int (*clear_tx_intr) (struct nic *);
|
|
- int (*handle_iscsi_path_req) (struct nic *,
|
|
- int,
|
|
- struct iscsi_uevent *ev,
|
|
- struct iscsi_path *path,
|
|
- nic_interface_t *nic_iface);
|
|
-} net_ops_t;
|
|
-
|
|
-typedef struct nic_lib_handle {
|
|
- struct nic_lib_handle *next;
|
|
-
|
|
- pthread_mutex_t mutex;
|
|
- struct nic_ops *ops;
|
|
-} nic_lib_handle_t;
|
|
-
|
|
-typedef struct nic {
|
|
- struct nic *next;
|
|
-
|
|
- uint32_t flags;
|
|
-#define NIC_UNITIALIZED 0x0001
|
|
-#define NIC_INITIALIZED 0x0002
|
|
-#define NIC_ENABLED 0x0004
|
|
-#define NIC_DISABLED 0x0008
|
|
-#define NIC_IPv6_ENABLED 0x0010
|
|
-#define NIC_ADDED_MULICAST 0x0020
|
|
-#define NIC_LONG_SLEEP 0x0040
|
|
-#define NIC_PATHREQ_WAIT 0x0080
|
|
-
|
|
-#define NIC_VLAN_STRIP_ENABLED 0x0100
|
|
-#define NIC_MSIX_ENABLED 0x0200
|
|
-#define NIC_TX_HAS_SENT 0x0400
|
|
-#define NIC_ENABLED_PENDING 0x0800
|
|
-
|
|
-#define NIC_UIO_NAME_MALLOC 0x1000
|
|
-#define NIC_CONFIG_NAME_MALLOC 0x2000
|
|
-#define NIC_EXIT_MAIN_LOOP 0x4000
|
|
-#define NIC_GOING_DOWN 0x8000
|
|
-#define NIC_RESET_UIP 0x10000
|
|
-
|
|
- uint16_t state;
|
|
-#define NIC_STOPPED 0x0001
|
|
-#define NIC_STARTED_RUNNING 0x0002
|
|
-#define NIC_RUNNING 0x0004
|
|
-#define NIC_EXIT 0x0010
|
|
-
|
|
- int fd; /* Holds the file descriptor to UIO */
|
|
- uint16_t uio_minor; /* Holds the UIO minor number */
|
|
-
|
|
- uint32_t host_no; /* Holds the associated host number */
|
|
-
|
|
- char *library_name; /* Name of the library to assoicate with */
|
|
- char *log_name; /* Human friendly name used in the log
|
|
- file */
|
|
- char *config_device_name; /* Name read from the XML configuration
|
|
- file */
|
|
- char eth_device_name[IFNAMSIZ]; /* Network interface name */
|
|
- char *uio_device_name; /* UIO device name */
|
|
-
|
|
- uint32_t intr_count; /* Total UIO interrupt count */
|
|
-
|
|
- int page_size;
|
|
-
|
|
- /* Held for nic ops manipulation */
|
|
- pthread_mutex_t nic_mutex;
|
|
-
|
|
- /* iSCSI ring ethernet MAC address */
|
|
- __u8 mac_addr[ETH_ALEN];
|
|
-
|
|
- /* Used to manage the network interfaces of this device */
|
|
- __u32 num_of_nic_iface;
|
|
- nic_interface_t *nic_iface;
|
|
-
|
|
- /* Wait for the device to be enabled */
|
|
- pthread_cond_t enable_wait_cond;
|
|
-
|
|
- /* Wait for the device to be finished enabled */
|
|
- pthread_cond_t enable_done_cond;
|
|
-
|
|
- /* Wait for the nic loop to start */
|
|
- pthread_cond_t nic_loop_started_cond;
|
|
-
|
|
- /* Wait for the device to be disabled */
|
|
- pthread_cond_t disable_wait_cond;
|
|
-
|
|
- /* Held when transmitting */
|
|
- pthread_mutex_t xmit_mutex;
|
|
-
|
|
- /* The thread this device is running on */
|
|
- pthread_t thread;
|
|
-
|
|
- /* The thread used to enable the device */
|
|
- pthread_t enable_thread;
|
|
-
|
|
- /* Statistical Information on this device */
|
|
- time_t start_time;
|
|
- struct nic_stats stats;
|
|
-
|
|
- /* Number of retrys from iscsid */
|
|
- uint32_t pending_count;
|
|
- uint32_t pathreq_pending_count;
|
|
-
|
|
-#define DEFAULT_RX_POLL_USEC 100 /* usec */
|
|
- /* options enabled by the user */
|
|
- uint32_t rx_poll_usec;
|
|
-
|
|
- /* Used to hold hardware specific data */
|
|
- void *priv;
|
|
-
|
|
- /* Used to hold the TX packets that are needed to be sent */
|
|
- struct packet *tx_packet_queue;
|
|
-
|
|
- /* Mutex to protect the list of free packets */
|
|
- pthread_mutex_t free_packet_queue_mutex;
|
|
-
|
|
- /* Used to hold the free packets that are needed to be sent */
|
|
- struct packet *free_packet_queue;
|
|
-
|
|
- /* Points to the NIC library */
|
|
- nic_lib_handle_t *nic_library;
|
|
-
|
|
- /* Points to the PCI table entry */
|
|
- struct pci_device_id *pci_id;
|
|
-
|
|
- /* Used to process the interrupt */
|
|
- int (*process_intr) (struct nic *nic);
|
|
-
|
|
- struct nic_ops *ops;
|
|
-
|
|
- /* NL processing parameters */
|
|
- pthread_t nl_process_thread;
|
|
- pthread_cond_t nl_process_cond;
|
|
- pthread_cond_t nl_process_if_down_cond;
|
|
- pthread_mutex_t nl_process_mutex;
|
|
- int nl_process_if_down;
|
|
- int nl_process_head;
|
|
- int nl_process_tail;
|
|
-#define NIC_NL_PROCESS_MAX_RING_SIZE 128
|
|
-#define NIC_NL_PROCESS_LAST_ENTRY (NIC_NL_PROCESS_MAX_RING_SIZE - 1)
|
|
-#define NIC_NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NIC_NL_PROCESS_MAX_RING_SIZE)
|
|
- void *nl_process_ring[NIC_NL_PROCESS_MAX_RING_SIZE];
|
|
-
|
|
- /* The thread used to perform ping */
|
|
- pthread_t ping_thread;
|
|
- uint64_t transport_handle;
|
|
-} nic_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * Function Prototypes
|
|
- *****************************************************************************/
|
|
-int load_all_nic_libraries();
|
|
-
|
|
-nic_t *nic_init();
|
|
-void nic_add(nic_t *nic);
|
|
-int nic_remove(nic_t *nic);
|
|
-
|
|
-int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
|
|
-int nic_process_intr(nic_t *nic, int discard_check);
|
|
-
|
|
-nic_interface_t *nic_iface_init();
|
|
-
|
|
-typedef enum {
|
|
- NIC_LIBRARY_EXSITS = 1,
|
|
- NIC_LIBRARY_DOESNT_EXIST = 2,
|
|
-} NIC_LIBRARY_EXIST_T;
|
|
-
|
|
-NIC_LIBRARY_EXIST_T does_nic_uio_name_exist(char *name,
|
|
- nic_lib_handle_t **handle);
|
|
-NIC_LIBRARY_EXIST_T does_nic_library_exist(char *name,
|
|
- nic_lib_handle_t **handle);
|
|
-
|
|
-/*******************************************************************************
|
|
- * Packet management utility functions
|
|
- ******************************************************************************/
|
|
-struct packet *get_next_tx_packet(nic_t *nic);
|
|
-struct packet *get_next_free_packet(nic_t *nic);
|
|
-void put_packet_in_tx_queue(struct packet *pkt, nic_t *nic);
|
|
-void put_packet_in_free_queue(struct packet *pkt, nic_t *nic);
|
|
-
|
|
-int unload_all_nic_libraries();
|
|
-void nic_close(nic_t *nic, NIC_SHUTDOWN_T graceful, int clean);
|
|
-
|
|
-/* Use this function to fill in minor number and uio, and eth names */
|
|
-int nic_fill_name(nic_t *nic);
|
|
-
|
|
-int enable_multicast(nic_t *nic);
|
|
-int disable_multicast(nic_t *nic);
|
|
-
|
|
-void nic_set_all_nic_iface_mac_to_parent(nic_t *nic);
|
|
-int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
|
|
- uint32_t subvendor, uint32_t subdevice,
|
|
- nic_lib_handle_t **handle,
|
|
- struct pci_device_id **pci_entry);
|
|
-
|
|
-void *nic_loop(void *arg);
|
|
-
|
|
-int nic_packet_capture(struct nic *, struct packet *pkt);
|
|
-
|
|
-int process_packets(nic_t *nic,
|
|
- struct timer *periodic_timer,
|
|
- struct timer *arp_timer, nic_interface_t *nic_iface);
|
|
-
|
|
-void prepare_ustack(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, struct packet *pkt);
|
|
-
|
|
-void prepare_ipv4_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, struct packet *pkt);
|
|
-
|
|
-void prepare_ipv6_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- struct uip_stack *ustack, struct packet *pkt);
|
|
-
|
|
-#endif /* __NIC_H__ */
|
|
diff --git a/iscsiuio/src/unix/nic_id.c b/iscsiuio/src/unix/nic_id.c
|
|
deleted file mode 100644
|
|
index 6da0a38..0000000
|
|
--- a/iscsiuio/src/unix/nic_id.c
|
|
+++ /dev/null
|
|
@@ -1,364 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_id.c - Using sysfs to determine the PCI vendor, device, subvendor and
|
|
- * subdevice ID's
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <stdio.h>
|
|
-#include <stdlib.h>
|
|
-#include <string.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/socket.h>
|
|
-
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-
|
|
-#define PFX "nic_id "
|
|
-
|
|
-/*******************************************************************************
|
|
- * Sysfs constant strings used to get PCI vendor, and device ID's
|
|
- ******************************************************************************/
|
|
-const char uio_vendor_id_template[] = "/sys/class/uio/uio%d/device/vendor";
|
|
-const char uio_subvendor_id_template[] =
|
|
- "/sys/class/uio/uio%d/device/subsystem_vendor";
|
|
-const char uio_device_id_template[] = "/sys/class/uio/uio%d/device/device";
|
|
-const char uio_subdevice_id_template[] =
|
|
- "/sys/class/uio/uio%d/device/subsystem_device";
|
|
-const char uio_device_symlink_template[] = "/sys/class/uio/uio%d/device";
|
|
-
|
|
-/**
|
|
- * get_id() - Utility function to read hex values from sysfs
|
|
- * @param nic - NIC device to use
|
|
- * @param sysfs_template - sysfs path template to use
|
|
- * @param sysfs_template_size - sysfs path template size in bytes
|
|
- * @parm id - this is the value returned from the sysfs entry
|
|
- * @return 0 on success <0 on failure
|
|
- */
|
|
-static int get_id(nic_t *nic,
|
|
- const char *sysfs_template,
|
|
- const size_t sysfs_template_size, uint32_t *id)
|
|
-{
|
|
- int rc = 0;
|
|
- FILE *fp;
|
|
- size_t chars_read;
|
|
- char buf[7];
|
|
- char *path;
|
|
- size_t path_size;
|
|
-
|
|
- path_size = sysfs_template_size + 4;
|
|
- path = malloc(path_size);
|
|
- if (path == NULL) {
|
|
- LOG_ERR("Could not allocate memory for %s", sysfs_template);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- snprintf(path, path_size, sysfs_template, nic->uio_minor);
|
|
-
|
|
- fp = fopen(path, "r");
|
|
- if (fp == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not open path: %s [%s]",
|
|
- nic->log_name, path, strerror(errno));
|
|
- rc = -EIO;
|
|
- goto error_fopen;
|
|
- }
|
|
-
|
|
- chars_read = fread(buf, sizeof(buf), 1, fp);
|
|
- if (chars_read != 1) {
|
|
- LOG_ERR(PFX "%s: Could not read from: %s [%s]",
|
|
- nic->log_name, path, strerror(ferror(fp)));
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- chars_read = sscanf(buf, "%x", id);
|
|
- if (chars_read != 1) {
|
|
- LOG_ERR(PFX "%s: Could interpret value: %s from: %s [%s]",
|
|
- nic->log_name, buf, path, strerror(errno));
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
-error:
|
|
- fclose(fp);
|
|
-
|
|
-error_fopen:
|
|
- free(path);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int get_vendor(nic_t *nic, uint32_t *id)
|
|
-{
|
|
- return get_id(nic,
|
|
- uio_vendor_id_template, sizeof(uio_vendor_id_template),
|
|
- id);
|
|
-}
|
|
-
|
|
-static int get_subvendor(nic_t *nic, uint32_t *id)
|
|
-{
|
|
- return get_id(nic,
|
|
- uio_subvendor_id_template,
|
|
- sizeof(uio_subvendor_id_template), id);
|
|
-}
|
|
-
|
|
-static int get_device(nic_t *nic, uint32_t *id)
|
|
-{
|
|
- return get_id(nic,
|
|
- uio_device_id_template,
|
|
- sizeof(uio_device_id_template), id);
|
|
-}
|
|
-
|
|
-static int get_subdevice(nic_t *nic, uint32_t *id)
|
|
-{
|
|
- return get_id(nic,
|
|
- uio_subdevice_id_template,
|
|
- sizeof(uio_subdevice_id_template), id);
|
|
-}
|
|
-
|
|
-int get_bus_slot_func_num(nic_t *nic,
|
|
- uint32_t *bus, uint32_t *slot, uint32_t *func)
|
|
-{
|
|
- size_t size;
|
|
- char *path, *tok, *tok2;
|
|
- int path_tokens, i;
|
|
- size_t path_size;
|
|
- char *read_pci_bus_slot_func_str;
|
|
- char pci_bus_slot_func_str[32];
|
|
- int rc;
|
|
- char *saveptr;
|
|
-
|
|
- path_size = sizeof(uio_device_symlink_template) + 4;
|
|
- path = malloc(path_size);
|
|
- if (path == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate path memory for %s",
|
|
- nic->log_name, uio_device_symlink_template);
|
|
- rc = -ENOMEM;
|
|
- goto error_alloc_path;
|
|
- }
|
|
-
|
|
- read_pci_bus_slot_func_str = malloc(128);
|
|
- if (read_pci_bus_slot_func_str == NULL) {
|
|
- LOG_ERR(PFX "%s: Could not allocate read pci bus memory for %s",
|
|
- nic->log_name, uio_device_symlink_template);
|
|
- rc = -ENOMEM;
|
|
- goto error_alloc_read_pci_bus;
|
|
- }
|
|
-
|
|
- snprintf(path, path_size, uio_device_symlink_template, nic->uio_minor);
|
|
-
|
|
- size = readlink(path, read_pci_bus_slot_func_str, 128);
|
|
- if (size == -1) {
|
|
- LOG_ERR(PFX "%s: Error with %s: %s",
|
|
- nic->log_name, path, strerror(errno));
|
|
- rc = errno;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (size > ((128) - 1)) {
|
|
- read_pci_bus_slot_func_str[128 - 1] = '\0';
|
|
- LOG_ERR(PFX "%s: not enough space (%d) for reading PCI "
|
|
- "slot:bus.func %s: %s",
|
|
- nic->log_name, size, path, strerror(errno));
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* readlink() doesn't NULL terminate the string */
|
|
- read_pci_bus_slot_func_str[size] = '\0';
|
|
-
|
|
- path_tokens = 0;
|
|
- tok = strtok_r(read_pci_bus_slot_func_str, "/", &saveptr);
|
|
- while (tok != NULL) {
|
|
- path_tokens++;
|
|
- tok = strtok_r(NULL, "/", &saveptr);
|
|
- }
|
|
-
|
|
- size = readlink(path, read_pci_bus_slot_func_str, 128);
|
|
- if (size == -1) {
|
|
- LOG_ERR(PFX "%s: Error with %s: %s",
|
|
- nic->log_name, path, strerror(errno));
|
|
- rc = errno;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (size > ((128) - 1)) {
|
|
- read_pci_bus_slot_func_str[128 - 1] = '\0';
|
|
- LOG_ERR(PFX "%s: not enough space for reading PCI "
|
|
- "slot:bus.func %s: %s",
|
|
- nic->log_name, path, strerror(errno));
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* readlink() doesn't NULL terminate the string */
|
|
- read_pci_bus_slot_func_str[size] = '\0';
|
|
-
|
|
- tok = strtok_r(read_pci_bus_slot_func_str, "/", &saveptr);
|
|
- for (i = 0; i < path_tokens - 1; i++)
|
|
- tok = strtok_r(NULL, "/", &saveptr);
|
|
- strcpy(pci_bus_slot_func_str, tok);
|
|
-
|
|
- tok = strtok_r(pci_bus_slot_func_str, ":", &saveptr);
|
|
- if (tok == NULL) {
|
|
- LOG_ERR(PFX "%s: Error with slot string: %s",
|
|
- nic->log_name, pci_bus_slot_func_str);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- tok = strtok_r(NULL, ":", &saveptr);
|
|
- if (tok == NULL) {
|
|
- LOG_ERR(PFX "%s: Error parsing slot: %s",
|
|
- nic->log_name, pci_bus_slot_func_str);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- sscanf(tok, "%x", bus);
|
|
-
|
|
- /* Need to extract the next token "xx.x" */
|
|
- tok = strtok_r(NULL, ":", &saveptr);
|
|
- if (tok == NULL) {
|
|
- LOG_ERR(PFX "%s: Error extracing bus.func: %s",
|
|
- nic->log_name, pci_bus_slot_func_str);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- tok2 = strtok_r(tok, ".", &saveptr);
|
|
- if (tok2 == NULL) {
|
|
- LOG_ERR(PFX "%s: Error parsing bus: %s",
|
|
- nic->log_name, pci_bus_slot_func_str);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- sscanf(tok2, "%x", slot);
|
|
-
|
|
- tok2 = strtok_r(NULL, ".", &saveptr);
|
|
- if (tok2 == NULL) {
|
|
- LOG_ERR(PFX "%s: Error parsing func: %s",
|
|
- nic->log_name, pci_bus_slot_func_str);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- sscanf(tok2, "%x", func);
|
|
- LOG_INFO(PFX "%s: is found at %02x:%02x.%02x", nic->log_name,
|
|
- *bus, *slot, *func);
|
|
- rc = 0;
|
|
-error:
|
|
- free(read_pci_bus_slot_func_str);
|
|
-error_alloc_read_pci_bus:
|
|
- free(path);
|
|
-error_alloc_path:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * find_set_nic_lib() - Match the NIC library to the NIC
|
|
- * @param nic - NIC device to determine which NIC library to use
|
|
- * @return 0 on success <0 on failure
|
|
- */
|
|
-int find_set_nic_lib(nic_t *nic)
|
|
-{
|
|
- uint32_t vendor;
|
|
- uint32_t subvendor;
|
|
- uint32_t device;
|
|
- uint32_t subdevice;
|
|
-
|
|
- uint32_t pci_bus;
|
|
- uint32_t pci_slot;
|
|
- uint32_t pci_func;
|
|
- int rc = 0;
|
|
-
|
|
- nic_lib_handle_t *handle;
|
|
- struct pci_device_id *pci_entry;
|
|
- size_t name_size;
|
|
-
|
|
- rc = get_vendor(nic, &vendor);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not get vendor id [0x%x]",
|
|
- nic->log_name, rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = get_subvendor(nic, &subvendor);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not get subvendor id [0x%x]",
|
|
- nic->log_name, rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = get_device(nic, &device);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not get device id [0x%x]",
|
|
- nic->log_name, rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- rc = get_subdevice(nic, &subdevice);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Could not get subdevice id [0x%x]",
|
|
- nic->log_name, rc);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- get_bus_slot_func_num(nic, &pci_bus, &pci_slot, &pci_func);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: Looking for device vendor: "
|
|
- "0x%x subvendor: 0x%x device: 0x%x subdevice: 0x%x",
|
|
- nic->log_name, vendor, subvendor, device, subdevice);
|
|
-
|
|
- rc = find_nic_lib_using_pci_id(vendor, device, subvendor, subdevice,
|
|
- &handle, &pci_entry);
|
|
-
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s: Couldn't find proper NIC library",
|
|
- nic->log_name);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- nic->nic_library = handle;
|
|
- nic->pci_id = pci_entry;
|
|
-
|
|
- /* Prepare the NIC library op table */
|
|
- nic->ops = handle->ops;
|
|
- (*nic->ops->lib_ops.get_library_name) (&nic->library_name, &name_size);
|
|
-
|
|
- return 0;
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic_id.h b/iscsiuio/src/unix/nic_id.h
|
|
deleted file mode 100644
|
|
index 340580f..0000000
|
|
--- a/iscsiuio/src/unix/nic_id.h
|
|
+++ /dev/null
|
|
@@ -1,47 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_id.h - NIC uIP NetLink user space stack
|
|
- *
|
|
- */
|
|
-#ifndef __NIC_ID_H__
|
|
-#define __NIC_ID_H__
|
|
-
|
|
-int find_set_nic_lib(nic_t *nic);
|
|
-
|
|
-int get_bus_slot_func_num(nic_t *nic,
|
|
- uint32_t *bus, uint32_t *slot, uint32_t *func);
|
|
-
|
|
-#endif /* __NIC_ID_H__ */
|
|
diff --git a/iscsiuio/src/unix/nic_nl.c b/iscsiuio/src/unix/nic_nl.c
|
|
deleted file mode 100644
|
|
index dee462e..0000000
|
|
--- a/iscsiuio/src/unix/nic_nl.c
|
|
+++ /dev/null
|
|
@@ -1,680 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_nl.c - NIC uIP NetLink user space stack
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <signal.h>
|
|
-#include <stdio.h>
|
|
-#include <stdlib.h>
|
|
-#include <string.h>
|
|
-#include <unistd.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <linux/limits.h>
|
|
-#include <netinet/if_ether.h>
|
|
-#include <netinet/in.h>
|
|
-#include <linux/netlink.h>
|
|
-#include <iscsi_if.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <poll.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/user.h>
|
|
-#include <sys/socket.h>
|
|
-
|
|
-#include "uip_arp.h"
|
|
-#include "logger.h"
|
|
-#include "options.h"
|
|
-
|
|
-#include "nic.h"
|
|
-#include "nic_nl.h"
|
|
-#include "nic_utils.h"
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "NIC_NL "
|
|
-
|
|
-static u8_t nlm_sendbuf[NLM_BUF_DEFAULT_MAX];
|
|
-
|
|
-static struct sockaddr_nl src_addr;
|
|
-
|
|
-static const struct sockaddr_nl dest_addr = {
|
|
- .nl_family = AF_NETLINK,
|
|
- .nl_pid = 0, /* kernel */
|
|
- .nl_groups = 0, /* unicast */
|
|
-};
|
|
-
|
|
-#define POLL_NL 0
|
|
-#define POLL_MAX 1
|
|
-
|
|
-/* Netlink */
|
|
-int nl_sock = INVALID_FD;
|
|
-
|
|
-static int nl_read(int ctrl_fd, char *data, int size, int flags)
|
|
-{
|
|
- int rc;
|
|
- struct iovec iov;
|
|
- struct msghdr msg;
|
|
-
|
|
- iov.iov_base = data;
|
|
- iov.iov_len = size;
|
|
-
|
|
- memset(&src_addr, 0, sizeof(src_addr));
|
|
- src_addr.nl_family = AF_NETLINK;
|
|
- src_addr.nl_pid = getpid();
|
|
- src_addr.nl_groups = 1;
|
|
-
|
|
- memset(&msg, 0, sizeof(msg));
|
|
- msg.msg_name = (void *)&src_addr;
|
|
- msg.msg_namelen = sizeof(src_addr);
|
|
- msg.msg_iov = &iov;
|
|
- msg.msg_iovlen = 1;
|
|
-
|
|
- rc = recvmsg(ctrl_fd, &msg, flags);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int
|
|
-kwritev(int fd, enum iscsi_uevent_e type, struct iovec *iovp, int count)
|
|
-{
|
|
- int i, rc;
|
|
- struct nlmsghdr *nlh;
|
|
- struct msghdr msg;
|
|
- struct iovec iov;
|
|
- int datalen = 0;
|
|
-
|
|
- for (i = 0; i < count; i++)
|
|
- datalen += iovp[i].iov_len;
|
|
-
|
|
- nlh = (struct nlmsghdr *)nlm_sendbuf;
|
|
- memset(nlh, 0, NLMSG_SPACE(datalen));
|
|
-
|
|
- nlh->nlmsg_len = NLMSG_SPACE(datalen);
|
|
- nlh->nlmsg_pid = getpid();
|
|
- nlh->nlmsg_flags = 0;
|
|
- nlh->nlmsg_type = type;
|
|
-
|
|
- datalen = 0;
|
|
- for (i = 0; i < count; i++) {
|
|
- memcpy(NLMSG_DATA(nlh) + datalen, iovp[i].iov_base,
|
|
- iovp[i].iov_len);
|
|
- datalen += iovp[i].iov_len;
|
|
- }
|
|
- iov.iov_base = (void *)nlh;
|
|
- iov.iov_len = nlh->nlmsg_len;
|
|
-
|
|
- memset(&msg, 0, sizeof(msg));
|
|
- msg.msg_name = (void *)&dest_addr;
|
|
- msg.msg_namelen = sizeof(dest_addr);
|
|
- msg.msg_iov = &iov;
|
|
- msg.msg_iovlen = 1;
|
|
-
|
|
- do {
|
|
- rc = sendmsg(fd, &msg, 0);
|
|
- if (rc == -ENOMEM) {
|
|
- LOG_ERR(PFX "sendmsg: alloc_skb() failed");
|
|
- sleep(1);
|
|
- } else if (rc < 0) {
|
|
- LOG_ERR(PFX "sendmsg: bug?: on %d %s[0x%x]",
|
|
- fd, strerror(errno), errno);
|
|
- sleep(1);
|
|
- }
|
|
- } while ((rc < 0) && (event_loop_stop == 0));
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*
|
|
- * __kipc_call() should never block. Therefore
|
|
- * Netlink's xmit logic is serialized. This means we do not allocate on
|
|
- * xmit path. Instead we reuse nlm_sendbuf buffer.
|
|
- *
|
|
- * Transport must assure non-blocking operations for:
|
|
- *
|
|
- * - session_create()
|
|
- * - conn_create()
|
|
- * - conn_bind()
|
|
- * _ set_param()
|
|
- * - conn_start()
|
|
- * - conn_stop()
|
|
- *
|
|
- * Its OK to block for cleanup for short period of time in operatations for:
|
|
- *
|
|
- * - conn_destroy()
|
|
- * - session_destroy()
|
|
- *
|
|
- * FIXME: interface needs to be extended to allow longer blocking on
|
|
- * cleanup. (Dima)
|
|
- */
|
|
-int __kipc_call(int fd, void *iov_base, int iov_len)
|
|
-{
|
|
- int rc;
|
|
- struct iovec iov;
|
|
- struct iscsi_uevent *ev = iov_base;
|
|
- enum iscsi_uevent_e type = ev->type;
|
|
-
|
|
- /* Sanity check */
|
|
- if (iov_base == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- iov.iov_base = iov_base;
|
|
- iov.iov_len = iov_len;
|
|
-
|
|
- rc = kwritev(fd, type, &iov, 1);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int pull_from_nl(char **buf)
|
|
-{
|
|
- int rc;
|
|
- size_t ev_size, payload_size, alloc_size;
|
|
- char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
|
|
- struct nlmsghdr *nlh;
|
|
- char *data = NULL;
|
|
- struct iscsi_uevent *ev;
|
|
-
|
|
- /* Take a quick peek at what how much uIP will need to read */
|
|
- rc = nl_read(nl_sock, nlm_ev,
|
|
- NLMSG_SPACE(sizeof(struct iscsi_uevent)),
|
|
- MSG_PEEK | MSG_WAITALL);
|
|
- if (rc <= 0) {
|
|
- LOG_ERR("can not read nlm_ev, error %s[%d]",
|
|
- strerror(errno), rc);
|
|
- if (rc == 0)
|
|
- return -EIO;
|
|
- else
|
|
- return errno;
|
|
- }
|
|
- nlh = (struct nlmsghdr *)nlm_ev;
|
|
-
|
|
- if (unlikely(nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsghdr)))) {
|
|
- LOG_ERR(PFX "Invalid nlh->nlmsg_len length: "
|
|
- "nlh->nlmsg_len(%d) < "
|
|
- "NLMSG_ALIGN(sizeof(struct nlmsghdr))(%d)",
|
|
- nlh->nlmsg_len, NLMSG_ALIGN(sizeof(struct nlmsghdr)));
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- ev = (struct iscsi_uevent *)NLMSG_DATA(nlh);
|
|
- if (ev->type == ISCSI_KEVENT_PATH_REQ) {
|
|
- ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
|
|
- payload_size = ev_size - sizeof(struct iscsi_uevent);
|
|
- if (payload_size < sizeof(struct iscsi_path))
|
|
- alloc_size = nlh->nlmsg_len + (payload_size -
|
|
- sizeof(struct iscsi_path));
|
|
- else
|
|
- alloc_size = nlh->nlmsg_len;
|
|
- } else {
|
|
- alloc_size = nlh->nlmsg_len;
|
|
- }
|
|
- data = (char *)malloc(alloc_size);
|
|
- if (unlikely(data == NULL)) {
|
|
- LOG_ERR(PFX "Couldn't allocate %d bytes for Netlink "
|
|
- "iSCSI message", alloc_size);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- memset(data, 0, alloc_size);
|
|
- rc = nl_read(nl_sock, data, (int)nlh->nlmsg_len, MSG_WAITALL);
|
|
- if (rc <= 0) {
|
|
- LOG_ERR("can not read nlm_ev, error %s[%d]",
|
|
- strerror(errno), rc);
|
|
- if (rc == 0)
|
|
- rc = -EIO;
|
|
- else
|
|
- rc = errno;
|
|
-
|
|
- goto error;
|
|
- }
|
|
- *buf = data;
|
|
- return 0;
|
|
-error:
|
|
- if (data != NULL)
|
|
- free(data);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static const struct timespec ctldev_sleep_req = {
|
|
- .tv_sec = 0,
|
|
- .tv_nsec = 250000000,
|
|
-};
|
|
-
|
|
-static int ctldev_handle(char *data, nic_t *nic)
|
|
-{
|
|
- int rc = 0;
|
|
- struct iscsi_uevent *ev;
|
|
- uint8_t *payload;
|
|
- struct iscsi_path *path;
|
|
- char *msg_type_str;
|
|
- int i;
|
|
- nic_interface_t *nic_iface = NULL;
|
|
-
|
|
- ev = (struct iscsi_uevent *)NLMSG_DATA(data);
|
|
- switch (ev->type) {
|
|
- case ISCSI_KEVENT_PATH_REQ:
|
|
- msg_type_str = "path_req";
|
|
- break;
|
|
- default:
|
|
- /* We don't care about other iSCSI Netlink messages */
|
|
- LOG_DEBUG(PFX "Received ev->type: 0x%x", ev->type);
|
|
- rc = 0;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* This is a message that drivers should be interested in */
|
|
- LOG_INFO(PFX "%s: Processing '%s'", nic->log_name, msg_type_str);
|
|
-
|
|
- payload = (uint8_t *) ((uint8_t *) ev) + sizeof(*ev);
|
|
- path = (struct iscsi_path *)payload;
|
|
-
|
|
- if (ev->type == ISCSI_KEVENT_PATH_REQ) {
|
|
- struct timespec sleep_rem;
|
|
- nic_interface_t *vlan_iface;
|
|
- uint16_t ip_type;
|
|
- int iface_num, vlan_id;
|
|
-
|
|
- if (path->ip_addr_len == 4)
|
|
- ip_type = AF_INET;
|
|
- else if (path->ip_addr_len == 16)
|
|
- ip_type = AF_INET6;
|
|
- else
|
|
- ip_type = 0;
|
|
-#ifdef REQ_PATH_IFACE_NUM
|
|
- /* Find the nic_iface to use */
|
|
- iface_num = ev->r.req_path.iface_num ?
|
|
- ev->r.req_path.iface_num : IFACE_NUM_INVALID;
|
|
-#else
|
|
- iface_num = IFACE_NUM_INVALID;
|
|
-#endif
|
|
- vlan_id = path->vlan_id ? path->vlan_id : NO_VLAN;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: PATH_REQ with iface_num %d VLAN %d",
|
|
- nic->log_name, iface_num, vlan_id);
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic_iface = nic_find_nic_iface(nic, ip_type, vlan_id,
|
|
- iface_num, IP_CONFIG_OFF);
|
|
- if (nic_iface == NULL) {
|
|
- nic_iface = nic_find_nic_iface(nic, ip_type,
|
|
- NO_VLAN,
|
|
- IFACE_NUM_INVALID,
|
|
- IP_CONFIG_OFF);
|
|
- if (nic_iface == NULL) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_ERR(PFX "%s: Couldn't find nic iface parent"
|
|
- " vlan: %d ip_type: %d "
|
|
- "ip_addr_len: %d to clone",
|
|
- nic->log_name, path->vlan_id, ip_type,
|
|
- path->ip_addr_len);
|
|
- goto error;
|
|
- }
|
|
- if (nic_iface->iface_num != IFACE_NUM_INVALID) {
|
|
- /* New VLAN support:
|
|
- Use the nic_iface found from the top
|
|
- of the protocol family and ignore
|
|
- the VLAN id from the path_req */
|
|
- if (!(nic_iface->iface_num == 0 &&
|
|
- nic_iface->vlan_id == 0 &&
|
|
- path->vlan_id)) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- goto nic_iface_done;
|
|
- }
|
|
- /* If iface_num == 0 and vlan_id == 0 but
|
|
- the vlan_id from path_req is > 0,
|
|
- then fallthru to the legacy support since
|
|
- this is most likely from an older iscsid
|
|
- (RHEL6.2/6.3 but has iface_num support)
|
|
- */
|
|
- }
|
|
- /* Legacy VLAN support:
|
|
- This newly created nic_iface must inherit the
|
|
- network parameters from the parent nic_iface
|
|
- */
|
|
- LOG_DEBUG(PFX "%s: Created the nic_iface for vlan: %d "
|
|
- "ip_type: %d", nic->log_name, path->vlan_id,
|
|
- ip_type);
|
|
- vlan_iface = nic_iface_init();
|
|
- if (vlan_iface == NULL) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_ERR(PFX "%s: Couldn't allocate "
|
|
- "space for vlan: %d ip_type: "
|
|
- "%d", nic->log_name, path->vlan_id,
|
|
- ip_type);
|
|
- goto error;
|
|
- }
|
|
- vlan_iface->protocol = ip_type;
|
|
- vlan_iface->vlan_id = path->vlan_id;
|
|
- nic_add_nic_iface(nic, vlan_iface);
|
|
-
|
|
- vlan_iface->ustack.ip_config =
|
|
- nic_iface->ustack.ip_config;
|
|
- memcpy(vlan_iface->ustack.hostaddr,
|
|
- nic_iface->ustack.hostaddr,
|
|
- sizeof(nic_iface->ustack.hostaddr));
|
|
- memcpy(vlan_iface->ustack.netmask,
|
|
- nic_iface->ustack.netmask,
|
|
- sizeof(nic_iface->ustack.netmask));
|
|
- memcpy(vlan_iface->ustack.netmask6,
|
|
- nic_iface->ustack.netmask6,
|
|
- sizeof(nic_iface->ustack.netmask6));
|
|
- memcpy(vlan_iface->ustack.hostaddr6,
|
|
- nic_iface->ustack.hostaddr6,
|
|
- sizeof(nic_iface->ustack.hostaddr6));
|
|
-
|
|
- /* Persist so when nic_close won't call uip_reset
|
|
- to nullify nic_iface->ustack */
|
|
- persist_all_nic_iface(nic);
|
|
-
|
|
- nic_iface = vlan_iface;
|
|
- nic_iface->flags |= NIC_IFACE_ACQUIRE;
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- /* nic_disable but not going down */
|
|
- nic_disable(nic, 0);
|
|
- } else {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- }
|
|
-nic_iface_done:
|
|
- /* Force enable the NIC */
|
|
- if (nic->state == NIC_STOPPED)
|
|
- nic_enable(nic);
|
|
-
|
|
- /* Ensure that the NIC is RUNNING */
|
|
- rc = -EIO;
|
|
- for (i = 0; i < 10; i++) {
|
|
- if (nic->state == NIC_RUNNING) {
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
-
|
|
- nanosleep(&ctldev_sleep_req, &sleep_rem);
|
|
- }
|
|
-
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s[vlan: %d protocol: %d]: not running, "
|
|
- "cmd: 0x%x nic state: 0x%x flags: 0x%x",
|
|
- nic->log_name,
|
|
- nic_iface->vlan_id, nic_iface->protocol,
|
|
- ev->type, nic->state, nic->flags);
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- if (nic->ops) {
|
|
- switch (ev->type) {
|
|
- case ISCSI_KEVENT_PATH_REQ:
|
|
- /* pass the request up to the user space
|
|
- * library driver */
|
|
- nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT2;
|
|
- nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT1;
|
|
- if (nic->ops->handle_iscsi_path_req)
|
|
- nic->ops->handle_iscsi_path_req(nic,
|
|
- nl_sock, ev,
|
|
- path,
|
|
- nic_iface);
|
|
- nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- nic->flags &= ~NIC_PATHREQ_WAIT;
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_INFO(PFX "%s: 'path_req' operation finished",
|
|
- nic->log_name);
|
|
-
|
|
- rc = 0;
|
|
- break;
|
|
- default:
|
|
- rc = -EAGAIN;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
-error:
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/* NIC specific nl processing thread */
|
|
-void *nl_process_handle_thread(void *arg)
|
|
-{
|
|
- int rc;
|
|
- nic_t *nic = (nic_t *)arg;
|
|
-
|
|
- if (nic == NULL)
|
|
- goto error;
|
|
-
|
|
- while (!event_loop_stop) {
|
|
- char *data = NULL;
|
|
-
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- rc = pthread_cond_wait(&nic->nl_process_cond,
|
|
- &nic->nl_process_mutex);
|
|
- if (rc != 0) {
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
- LOG_ERR("Fatal error in NL processing thread "
|
|
- "during wait[%s]", strerror(rc));
|
|
- break;
|
|
- }
|
|
-
|
|
- data = nic->nl_process_ring[nic->nl_process_head];
|
|
- nic->nl_process_ring[nic->nl_process_head] = NULL;
|
|
- nic->nl_process_tail =
|
|
- NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_tail);
|
|
-
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
-
|
|
- if (data) {
|
|
- ctldev_handle(data, nic);
|
|
- free(data);
|
|
- }
|
|
- }
|
|
-error:
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static void flush_nic_nl_process_ring(nic_t *nic)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < NIC_NL_PROCESS_MAX_RING_SIZE; i++) {
|
|
- if (nic->nl_process_ring[i] != NULL) {
|
|
- free(nic->nl_process_ring[i]);
|
|
- nic->nl_process_ring[i] = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- nic->nl_process_head = 0;
|
|
- nic->nl_process_tail = 0;
|
|
-
|
|
- LOG_DEBUG(PFX "%s: Flushed NIC NL ring", nic->log_name);
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_nl_open() - This is called when opening/creating the Netlink listening
|
|
- * thread
|
|
- * @param dev - CNIC UIO device to create a NetLink listener on
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int nic_nl_open()
|
|
-{
|
|
- int rc = 0;
|
|
- char *msg_type_str;
|
|
-
|
|
- /* Prepare the thread to issue the ARP's */
|
|
- nl_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
|
|
- if (nl_sock < 0) {
|
|
- LOG_ERR(PFX "can not create NETLINK_ISCSI socket [%s]",
|
|
- strerror(errno));
|
|
- rc = -ENOMEM;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- memset(&src_addr, 0, sizeof(src_addr));
|
|
- src_addr.nl_family = AF_NETLINK;
|
|
- src_addr.nl_pid = getpid();
|
|
- src_addr.nl_groups = ISCSI_NL_GRP_UIP;
|
|
-
|
|
- while ((!event_loop_stop)) {
|
|
- rc = bind(nl_sock,
|
|
- (struct sockaddr *)&src_addr, sizeof(src_addr));
|
|
- if (rc == 0)
|
|
- break;
|
|
-
|
|
- LOG_ERR(PFX "waiting binding to NETLINK_ISCSI socket");
|
|
-
|
|
- sleep(1);
|
|
- }
|
|
-
|
|
- if (event_loop_stop) {
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "Netlink to CNIC on pid %d is ready", src_addr.nl_pid);
|
|
-
|
|
- while (!event_loop_stop) {
|
|
- struct iscsi_uevent *ev;
|
|
- char *buf = NULL;
|
|
- uint32_t host_no;
|
|
- nic_t *nic;
|
|
-
|
|
- rc = pull_from_nl(&buf);
|
|
- if (rc != 0)
|
|
- continue;
|
|
-
|
|
- /* Try to abort ARP'ing if a if_down was received */
|
|
- ev = (struct iscsi_uevent *)NLMSG_DATA(buf);
|
|
- switch (ev->type) {
|
|
- case ISCSI_KEVENT_IF_DOWN:
|
|
- host_no = ev->r.notify_if_down.host_no;
|
|
- msg_type_str = "if_down";
|
|
- break;
|
|
- case ISCSI_KEVENT_PATH_REQ:
|
|
- host_no = ev->r.req_path.host_no;
|
|
- msg_type_str = "path_req";
|
|
- break;
|
|
- default:
|
|
- /* We don't care about other iSCSI Netlink messages */
|
|
- continue;
|
|
- }
|
|
- LOG_INFO(PFX "Received %s for host %d", msg_type_str, host_no);
|
|
-
|
|
- /* Make sure the nic list doesn't get yanked */
|
|
- pthread_mutex_lock(&nic_list_mutex);
|
|
-
|
|
- rc = from_host_no_find_associated_eth_device(host_no, &nic);
|
|
- if (rc != 0) {
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
- LOG_ERR(PFX "Dropping msg, couldn't find nic with host "
|
|
- "no: %d", host_no);
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Found the nic */
|
|
- if (nic->nl_process_thread == INVALID_THREAD) {
|
|
- /* If thread is not valid, just drop it */
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
- LOG_ERR(PFX "Dropping msg, nic nl process thread "
|
|
- "not ready for host no: %d", host_no);
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (ev->type == ISCSI_KEVENT_IF_DOWN) {
|
|
- char eth_device_name[IFNAMSIZ];
|
|
-
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- nic->nl_process_if_down = 1;
|
|
- flush_nic_nl_process_ring(nic);
|
|
- pthread_cond_broadcast(&nic->nl_process_if_down_cond);
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
-
|
|
- memcpy(eth_device_name, nic->eth_device_name,
|
|
- sizeof(eth_device_name));
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- nic->flags &= ~NIC_PATHREQ_WAIT;
|
|
- nic->flags |= NIC_EXIT_MAIN_LOOP;
|
|
- pthread_cond_broadcast(&nic->enable_done_cond);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- nic->nl_process_if_down = 0;
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
-
|
|
- nic_disable(nic, 1);
|
|
-
|
|
- nic_remove(nic);
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
- LOG_INFO(PFX "%s: 'if_down' operation finished",
|
|
- eth_device_name);
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Place msg into the nic specific queue */
|
|
- pthread_mutex_lock(&nic->nl_process_mutex);
|
|
- if ((nic->nl_process_head + 1 == nic->nl_process_tail) ||
|
|
- (nic->nl_process_tail == 0 &&
|
|
- nic->nl_process_head == NIC_NL_PROCESS_LAST_ENTRY)) {
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
- LOG_WARN(PFX "%s: No space on Netlink ring",
|
|
- nic->log_name);
|
|
- continue;
|
|
- }
|
|
-
|
|
- nic->nl_process_ring[nic->nl_process_head] = buf;
|
|
- nic->nl_process_head =
|
|
- NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_head);
|
|
- pthread_cond_signal(&nic->nl_process_cond);
|
|
-
|
|
- pthread_mutex_unlock(&nic->nl_process_mutex);
|
|
-
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
- LOG_DEBUG(PFX "Pulled nl event");
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "Netlink thread exit'ing");
|
|
- rc = 0;
|
|
-
|
|
-error:
|
|
- return rc;
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic_nl.h b/iscsiuio/src/unix/nic_nl.h
|
|
deleted file mode 100644
|
|
index c68d81c..0000000
|
|
--- a/iscsiuio/src/unix/nic_nl.h
|
|
+++ /dev/null
|
|
@@ -1,54 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_nl.h - NIC uIP NetLink user space stack
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __NIC_NL_H__
|
|
-#define __NIC_NL_H__
|
|
-
|
|
-#include <pthread.h>
|
|
-
|
|
-int nic_nl_open();
|
|
-void nic_nl_close();
|
|
-
|
|
-int __kipc_call(int fd, void *iov_base, int iov_len);
|
|
-
|
|
-extern pthread_cond_t nl_process_if_down_cond;
|
|
-extern pthread_mutex_t nl_process_mutex;
|
|
-extern int nl_process_if_down;
|
|
-
|
|
-#endif /* __NIC_NL_H__ */
|
|
diff --git a/iscsiuio/src/unix/nic_utils.c b/iscsiuio/src/unix/nic_utils.c
|
|
deleted file mode 100644
|
|
index ec4535d..0000000
|
|
--- a/iscsiuio/src/unix/nic_utils.c
|
|
+++ /dev/null
|
|
@@ -1,1813 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_util.c - shared NIC utility functions
|
|
- *
|
|
- */
|
|
-#include <dirent.h>
|
|
-#include <errno.h>
|
|
-#include <fcntl.h>
|
|
-#define _GNU_SOURCE
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-#include <time.h>
|
|
-#include <unistd.h>
|
|
-#include <arpa/inet.h>
|
|
-#include <linux/sockios.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/time.h>
|
|
-
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_id.h"
|
|
-#include "nic_vlan.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-
|
|
-#define PFX "nic_utils "
|
|
-
|
|
-/******************************************************************************
|
|
- * String constants
|
|
- *****************************************************************************/
|
|
-static const char nic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
|
|
-static const char cnic_sysfs_uio_event_template[] =
|
|
- "/sys/class/uio/uio%d/event";
|
|
-static const char base_uio_sysfs_name[] = "/sys/class/uio/";
|
|
-static const char uio_name[] = "uio";
|
|
-
|
|
-static const char uio_base_dir[] = "/dev/uio";
|
|
-static const char uio_udev_path_template[] = "/dev/uio%hd";
|
|
-static const char uio_uevent_path_template[] = "/sys/class/uio/uio%d/uevent";
|
|
-
|
|
-static const char base_iscsi_host_name[] = "/sys/class/iscsi_host/";
|
|
-static const char host_template[] = "host%d";
|
|
-static const char iscsi_host_path_netdev_template[] =
|
|
- "/sys/class/iscsi_host/host%d/netdev";
|
|
-static const char cnic_uio_sysfs_resc_template[] =
|
|
- "/sys/class/uio/uio%i/device/resource%i";
|
|
-static const char iscsi_transport_handle_template[] =
|
|
- "/sys/class/iscsi_transport/%s/handle";
|
|
-static const char host_pfx[] = "host";
|
|
-
|
|
-/**
|
|
- * manually_trigger_uio_event() - If the uio file node doesn't exist then
|
|
- * try to retrigger udev to create the file
|
|
- * node by touch the uevent file in sysfs
|
|
- * @param nic - the nic to trigger on
|
|
- * @param uio_minor - UIO the minor number to use
|
|
- * @return 0 on success
|
|
- */
|
|
-int manually_trigger_uio_event(nic_t *nic, int uio_minor)
|
|
-{
|
|
- int fd;
|
|
- char uio_uevent_path[sizeof(uio_uevent_path_template) + 10];
|
|
- char enable_str[] = "online";
|
|
- int rc;
|
|
- size_t bytes_wrote;
|
|
-
|
|
- rc = sprintf(uio_uevent_path, uio_uevent_path_template, uio_minor);
|
|
- if (rc < 0) {
|
|
- LOG_ERR(PFX "%s: Could not build uio uevent path",
|
|
- nic->log_name);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: triggering UIO uevent path: %s",
|
|
- nic->log_name, uio_uevent_path);
|
|
-
|
|
- fd = open(uio_uevent_path, O_WRONLY);
|
|
- if (fd == -1) {
|
|
- LOG_ERR(PFX "%s: Could not open uio uevent path: %s [%s]",
|
|
- nic->log_name, uio_uevent_path, strerror(errno));
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- bytes_wrote = write(fd, enable_str, sizeof(enable_str));
|
|
- if (bytes_wrote != sizeof(enable_str)) {
|
|
- LOG_ERR(PFX "%s: Could write to uio uevent path: %s [%s]",
|
|
- nic->log_name, uio_uevent_path, strerror(errno));
|
|
- rc = -EIO;
|
|
- } else
|
|
- rc = 0;
|
|
-
|
|
- close(fd);
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int wait_for_file_node_timed(nic_t *nic, char *filepath, int seconds)
|
|
-{
|
|
- struct timeval start_time;
|
|
- struct timeval wait_time;
|
|
- struct timeval total_time;
|
|
- struct timespec sleep_req, sleep_rem;
|
|
-
|
|
- sleep_req.tv_sec = 0;
|
|
- sleep_req.tv_nsec = 250000000;
|
|
-
|
|
- wait_time.tv_sec = seconds;
|
|
- wait_time.tv_usec = 0;
|
|
-
|
|
- if (gettimeofday(&start_time, NULL)) {
|
|
- LOG_ERR(PFX "%s: Couldn't gettimeofday() during watch file: %s"
|
|
- "[%s]", nic->log_name, filepath, strerror(errno));
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- timeradd(&start_time, &wait_time, &total_time);
|
|
-
|
|
- while (1) {
|
|
- struct timeval current_time;
|
|
- struct stat file_stat;
|
|
-
|
|
- /* Check if the file node exists */
|
|
- if (stat(filepath, &file_stat) == 0)
|
|
- return 0;
|
|
-
|
|
- if (gettimeofday(¤t_time, NULL)) {
|
|
- LOG_ERR(PFX "%s: Couldn't get current time for "
|
|
- "watching file: %s [%s]",
|
|
- nic->log_name, filepath, strerror(errno));
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- /* Timeout has excceded return -ETIME */
|
|
- if (timercmp(&total_time, ¤t_time, <)) {
|
|
- LOG_ERR(PFX "%s: timeout waiting %d secs for file: %s",
|
|
- nic->log_name, seconds, filepath);
|
|
- return -ETIME;
|
|
- }
|
|
-
|
|
- nanosleep(&sleep_req, &sleep_rem);
|
|
- }
|
|
-}
|
|
-
|
|
-/******************************************************************************
|
|
- * Autodiscovery of iscsi_hosts
|
|
- *****************************************************************************/
|
|
-static int filter_host_name(const struct dirent *entry)
|
|
-{
|
|
- if ((memcmp(entry->d_name, "host", 4) == 0))
|
|
- return 1;
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int nic_discover_iscsi_hosts()
|
|
-{
|
|
- struct dirent **files;
|
|
- int count;
|
|
- int i;
|
|
- int rc;
|
|
-
|
|
- count = scandir(base_iscsi_host_name, &files, filter_host_name,
|
|
- alphasort);
|
|
-
|
|
- switch (count) {
|
|
- case 0:
|
|
- /* Currently there are no iSCSI hosts */
|
|
- rc = 0;
|
|
- break;
|
|
-
|
|
- case -1:
|
|
- LOG_WARN(PFX "Error when scanning path: %s[%s]",
|
|
- base_iscsi_host_name, strerror(errno));
|
|
- rc = -EINVAL;
|
|
- break;
|
|
-
|
|
- default:
|
|
- /* There are iSCSI hosts */
|
|
- pthread_mutex_lock(&nic_list_mutex);
|
|
- for (i = 0; i < count; i++) {
|
|
- int host_no;
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(iscsi_host_path_netdev_template) +
|
|
- 8];
|
|
- rc = sscanf(files[i]->d_name, host_template, &host_no);
|
|
- nic_t *nic;
|
|
-
|
|
- LOG_INFO(PFX "Found host[%d]: %s",
|
|
- host_no, files[i]->d_name);
|
|
-
|
|
- /* Build the path to determine netdev name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- iscsi_host_path_netdev_template, host_no);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- continue;
|
|
-
|
|
- rc = from_host_no_find_associated_eth_device(host_no,
|
|
- &nic);
|
|
- if (rc != 0) {
|
|
- /* Normalize the string */
|
|
- if (raw[raw_size - 1] == '\n')
|
|
- raw[raw_size - 1] = '\0';
|
|
-
|
|
- nic = nic_init();
|
|
- if (nic == NULL) {
|
|
- LOG_ERR(PFX "Couldn't allocate "
|
|
- "space for NIC %s "
|
|
- "during scan", raw);
|
|
-
|
|
- free(raw);
|
|
- rc = -ENOMEM;
|
|
- break;
|
|
- }
|
|
-
|
|
- strncpy(nic->eth_device_name, raw, raw_size);
|
|
- nic->config_device_name = nic->eth_device_name;
|
|
- nic->log_name = nic->eth_device_name;
|
|
- nic->host_no = host_no;
|
|
-
|
|
- if (nic_fill_name(nic) != 0) {
|
|
- free(nic);
|
|
- free(raw);
|
|
- rc = -EIO;
|
|
- continue;
|
|
- }
|
|
-
|
|
- nic_add(nic);
|
|
-
|
|
- LOG_INFO(PFX "NIC not found creating an "
|
|
- "instance for host_no: %d %s",
|
|
- host_no, nic->eth_device_name);
|
|
- } else
|
|
- LOG_INFO(PFX "%s: NIC found host_no: %d",
|
|
- nic->log_name, host_no);
|
|
-
|
|
- free(raw);
|
|
- }
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
- /* Cleanup the scandir() call */
|
|
- for (i = 0; i < count; i++)
|
|
- free(files[i]);
|
|
- free(files);
|
|
-
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/******************************************************************************
|
|
- * Enable/Disable Multicast on physical interface
|
|
- *****************************************************************************/
|
|
-static int nic_util_enable_disable_multicast(nic_t *nic, uint32_t cmd)
|
|
-{
|
|
- int rc = 0;
|
|
- struct uip_eth_addr multicast_addr;
|
|
- int fd;
|
|
- struct ifreq ifr;
|
|
-
|
|
- /* adding ethernet multicast address for IPv6 */
|
|
- memcpy(&multicast_addr, nic->mac_addr, ETH_ALEN);
|
|
- multicast_addr.addr[0] = 0x33;
|
|
- multicast_addr.addr[1] = 0x33;
|
|
- multicast_addr.addr[2] = 0xff;
|
|
-
|
|
- /* Prepare the request */
|
|
- memset(&ifr, 0, sizeof(ifr));
|
|
- strncpy(ifr.ifr_name, nic->eth_device_name,
|
|
- sizeof(ifr.ifr_name));
|
|
- memcpy(ifr.ifr_hwaddr.sa_data, multicast_addr.addr, ETH_ALEN);
|
|
-
|
|
- fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
- if (fd < 0) {
|
|
- LOG_ERR(PFX "%s: Couldn't create socket to %s "
|
|
- "multicast address: %s",
|
|
- nic->log_name,
|
|
- cmd == SIOCADDMULTI ? "added" : "delete",
|
|
- strerror(errno));
|
|
- return errno;
|
|
- }
|
|
-
|
|
- rc = fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
- if (rc != 0) {
|
|
- LOG_WARN("%s: Couldn't set to ethtool IOCTL to "
|
|
- "non-blocking [%s]", nic->log_name, strerror(errno));
|
|
- }
|
|
-
|
|
- if (ioctl(fd, cmd, (char *)&ifr) != 0) {
|
|
- LOG_ERR("%s: Couldn't issue ioctl socket to %s "
|
|
- "multicast address: %s",
|
|
- nic->log_name,
|
|
- cmd == SIOCADDMULTI ? "add" : "delete",
|
|
- strerror(errno));
|
|
- rc = errno;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: %s address %02x:%02x:%02x:%02x:%02x:%02x "
|
|
- "to multicast list",
|
|
- nic->log_name,
|
|
- cmd == SIOCADDMULTI ? "Added" : "Deleted",
|
|
- multicast_addr.addr[0], multicast_addr.addr[1],
|
|
- multicast_addr.addr[2], multicast_addr.addr[3],
|
|
- multicast_addr.addr[4], multicast_addr.addr[5]);
|
|
-
|
|
- if (cmd == SIOCADDMULTI)
|
|
- nic->flags |= NIC_ADDED_MULICAST;
|
|
- else
|
|
- nic->flags &= ~NIC_ADDED_MULICAST;
|
|
-
|
|
-error:
|
|
- close(fd);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * enable_multicast() - This fuction is used to enable
|
|
- * the listening of multicast addresses for a given network interface
|
|
- * @param nic - NIC device to enable multicast on
|
|
- * @return 0 for success or <0 for failure
|
|
- */
|
|
-int enable_multicast(nic_t *nic)
|
|
-{
|
|
- return nic_util_enable_disable_multicast(nic, SIOCADDMULTI);
|
|
-}
|
|
-
|
|
-/**
|
|
- * disable_multicast() - This fuction is used to disable
|
|
- * the listening of multicast addresses for a given network interface
|
|
- * @param dev - NIC device to disable multicast on
|
|
- * @return 0 for success or <0 for failure
|
|
- */
|
|
-int disable_multicast(nic_t *nic)
|
|
-{
|
|
- return nic_util_enable_disable_multicast(nic, SIOCDELMULTI);
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Finding associated UIO/physical network interfaces
|
|
- ******************************************************************************/
|
|
-static int filter_net_name(const struct dirent *entry)
|
|
-{
|
|
- if ((memcmp(entry->d_name, "net:", 4) == 0))
|
|
- return 1;
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static char *extract_net_name(struct dirent **files)
|
|
-{
|
|
- return strstr(files[0]->d_name, ":");
|
|
-}
|
|
-
|
|
-static int filter_dot_out(const struct dirent *entry)
|
|
-{
|
|
- if ((memcmp(entry->d_name, ".", 1) == 0))
|
|
- return 0;
|
|
- else
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static char *extract_none(struct dirent **files)
|
|
-{
|
|
- return files[0]->d_name;
|
|
-}
|
|
-
|
|
-/**
|
|
- * from_host_no_find_nic() - Given the host number
|
|
- * this function will try to find the assoicated nic interface
|
|
- * Must be called with nic_list_mutex lock
|
|
- * @param host_no - minor number of the UIO device
|
|
- * @param nic - pointer to the NIC will set if successful
|
|
- * @return 0 on success, <0 on error
|
|
- */
|
|
-int from_host_no_find_associated_eth_device(int host_no, nic_t **nic)
|
|
-{
|
|
- nic_t *current_nic = nic_list;
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
-
|
|
- char temp_path[sizeof(iscsi_host_path_netdev_template) + 8];
|
|
- int rc = -EIO;
|
|
-
|
|
- /* Build the path to determine uio name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- iscsi_host_path_netdev_template, host_no);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n' && raw_size--)
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- rc = -EIO;
|
|
-
|
|
- current_nic = nic_list;
|
|
- while (current_nic != NULL) {
|
|
- if (strcmp(raw, current_nic->eth_device_name) == 0) {
|
|
- *nic = current_nic;
|
|
- rc = 0;
|
|
- break;
|
|
- }
|
|
-
|
|
- current_nic = current_nic->next;
|
|
- }
|
|
-
|
|
- free(raw);
|
|
-
|
|
-error:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC packet handling functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * from_uio_find_associated_eth_device() - Given the uio minor number
|
|
- * this function will try to find the assoicated phyisical network
|
|
- * interface
|
|
- * @param uio_minor - minor number of the UIO device
|
|
- * @param name - char buffer which will be filled if successful
|
|
- * @param name_size - size of the name buffer
|
|
- * @return >0 minor number <0 an error
|
|
- */
|
|
-static int from_uio_find_associated_eth_device(nic_t *nic,
|
|
- int uio_minor,
|
|
- char *name, size_t name_size)
|
|
-{
|
|
- char *path;
|
|
- int rc;
|
|
- int count;
|
|
- struct dirent **files;
|
|
- char *parsed_name;
|
|
- int i;
|
|
- int path_iterator;
|
|
- char *search_paths[] = { "/sys/class/uio/uio%i/device/",
|
|
- "/sys/class/uio/uio%i/device/net"
|
|
- };
|
|
- int path_to[] = { 5, 1 };
|
|
- int (*search_filters[]) (const struct dirent *) = {
|
|
- filter_net_name, filter_dot_out,};
|
|
- char *(*extract_name[]) (struct dirent **files) = {
|
|
- extract_net_name, extract_none,};
|
|
- int extract_name_offset[] = { 1, 0 };
|
|
-
|
|
- path = malloc(PATH_MAX);
|
|
- if (path == NULL) {
|
|
- LOG_ERR(PFX "Could not allocate memory for path");
|
|
- rc = -ENOMEM;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- for (path_iterator = 0;
|
|
- path_iterator < sizeof(search_paths) / sizeof(search_paths[0]);
|
|
- path_iterator++) {
|
|
- /* Build the path to determine uio name */
|
|
- rc = sprintf(path, search_paths[path_iterator], uio_minor);
|
|
-
|
|
- wait_for_file_node_timed(nic, path, path_to[path_iterator]);
|
|
-
|
|
- count = scandir(path, &files,
|
|
- search_filters[path_iterator], alphasort);
|
|
-
|
|
- switch (count) {
|
|
- case 1:
|
|
- parsed_name = (*extract_name[path_iterator]) (files);
|
|
- if (parsed_name == NULL) {
|
|
- LOG_WARN(PFX "Couldn't find delimiter in: %s",
|
|
- files[0]->d_name);
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- strncpy(name,
|
|
- parsed_name +
|
|
- extract_name_offset[path_iterator], name_size);
|
|
-
|
|
- free(files[0]);
|
|
- free(files);
|
|
-
|
|
- rc = 0;
|
|
- break;
|
|
-
|
|
- case 0:
|
|
- rc = -EINVAL;
|
|
- break;
|
|
-
|
|
- case -1:
|
|
- LOG_WARN(PFX "Error when scanning path: %s[%s]",
|
|
- path, strerror(errno));
|
|
- rc = -EINVAL;
|
|
- break;
|
|
-
|
|
- default:
|
|
- LOG_WARN(PFX
|
|
- "Too many entries when looking for device: %s",
|
|
- path);
|
|
-
|
|
- /* Cleanup the scandir() call */
|
|
- for (i = 0; i < count; i++)
|
|
- free(files[i]);
|
|
- free(files);
|
|
-
|
|
- rc = -EINVAL;
|
|
- break;
|
|
- }
|
|
-
|
|
- if (rc == 0)
|
|
- break;
|
|
- }
|
|
-
|
|
-error:
|
|
- free(path);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * from_uio_find_associated_host() - Given the uio minor number
|
|
- * this function will try to find the assoicated iscsi host
|
|
- * @param uio_minor - minor number of the UIO device
|
|
- * @param name - char buffer which will be filled if successful
|
|
- * @param name_size - size of the name buffer
|
|
- * @return >0 minor number <0 an error
|
|
- */
|
|
-static int from_uio_find_associated_host(nic_t *nic, int uio_minor,
|
|
- char *name, size_t name_size)
|
|
-{
|
|
- char *path;
|
|
- int rc;
|
|
- int count;
|
|
- struct dirent **files;
|
|
- char *parsed_name;
|
|
- int i;
|
|
- int path_iterator;
|
|
- char *search_paths[] = { "/sys/class/uio/uio%i/device/" };
|
|
- int path_to[] = { 5, 1 };
|
|
- int (*search_filters[]) (const struct dirent *) = { filter_host_name, };
|
|
- char *(*extract_name[]) (struct dirent **files) = { extract_none, };
|
|
- int extract_name_offset[] = { 0 };
|
|
-
|
|
- path = malloc(PATH_MAX);
|
|
- if (!path) {
|
|
- LOG_ERR(PFX "Could not allocate memory for path");
|
|
- rc = -ENOMEM;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- for (path_iterator = 0;
|
|
- path_iterator < sizeof(search_paths) / sizeof(search_paths[0]);
|
|
- path_iterator++) {
|
|
- /* Build the path to determine uio name */
|
|
- rc = sprintf(path, search_paths[path_iterator], uio_minor);
|
|
-
|
|
- wait_for_file_node_timed(nic, path, path_to[path_iterator]);
|
|
-
|
|
- count = scandir(path, &files,
|
|
- search_filters[path_iterator], alphasort);
|
|
-
|
|
- switch (count) {
|
|
- case 1: {
|
|
- char *parsed_src;
|
|
- size_t parsed_size;
|
|
-
|
|
- parsed_name = (*extract_name[path_iterator]) (files);
|
|
- if (!parsed_name) {
|
|
- LOG_WARN(PFX "Couldn't find delimiter in: %s",
|
|
- files[0]->d_name);
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- parsed_src = parsed_name + extract_name_offset[path_iterator];
|
|
- parsed_size = strlen(parsed_src);
|
|
- if (parsed_size >= name_size) {
|
|
- LOG_WARN(PFX "uio device name too long: %s (max %d)",
|
|
- parsed_src, (int)name_size - 1);
|
|
- rc = -EINVAL;
|
|
- } else {
|
|
- strncpy(name, parsed_src, name_size);
|
|
- rc = 0;
|
|
- }
|
|
-
|
|
- free(files[0]);
|
|
- free(files);
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- case 0:
|
|
- rc = -EINVAL;
|
|
- break;
|
|
-
|
|
- case -1:
|
|
- LOG_WARN(PFX "Error when scanning path: %s[%s]",
|
|
- path, strerror(errno));
|
|
- rc = -EINVAL;
|
|
- break;
|
|
-
|
|
- default:
|
|
- LOG_WARN(PFX
|
|
- "Too many entries when looking for device: %s",
|
|
- path);
|
|
-
|
|
- /* Cleanup the scandir() call */
|
|
- for (i = 0; i < count; i++)
|
|
- free(files[i]);
|
|
- free(files);
|
|
-
|
|
- rc = -EINVAL;
|
|
- break;
|
|
- }
|
|
-
|
|
- if (rc == 0)
|
|
- break;
|
|
- }
|
|
-
|
|
-error:
|
|
- free(path);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * filter_uio_name() - This is the callback used by scandir when looking for
|
|
- * the number of uio entries
|
|
- */
|
|
-static int filter_uio_name(const struct dirent *entry)
|
|
-{
|
|
- /* Only return if the name of the file begins with 'uio' */
|
|
- if ((memcmp(entry->d_name, uio_name, sizeof(uio_name) - 1) == 0))
|
|
- return 1;
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * from_netdev_name_find_nic() - This is used to find the NIC device given
|
|
- * the netdev name
|
|
- * @param interface_name - name of the interface to search on
|
|
- * @param nic - pointer of the pointer to the NIC
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int from_netdev_name_find_nic(char *interface_name, nic_t **nic)
|
|
-{
|
|
- nic_t *current_nic;
|
|
-
|
|
- current_nic = nic_list;
|
|
- while (current_nic != NULL) {
|
|
- if (strcmp(interface_name, current_nic->eth_device_name) == 0)
|
|
- break;
|
|
-
|
|
- current_nic = current_nic->next;
|
|
- }
|
|
-
|
|
- if (current_nic == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- *nic = current_nic;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * from_phys_name_find_assoicated_uio_device() - This is used to find the
|
|
- * uio minor
|
|
- * when given a network interface name
|
|
- * @param interface_name - network interface name to search for
|
|
- * @return >0 minor number <0 an error
|
|
- */
|
|
-int from_phys_name_find_assoicated_uio_device(nic_t *nic)
|
|
-{
|
|
- char *path = NULL;
|
|
- int count;
|
|
- struct dirent **files;
|
|
- int i;
|
|
- int rc;
|
|
- char *interface_name = nic->config_device_name;
|
|
-
|
|
- if (interface_name == NULL)
|
|
- interface_name = nic->eth_device_name;
|
|
-
|
|
- /* Wait at least 10 seconds for uio sysfs entries to appear */
|
|
- rc = wait_for_file_node_timed(nic, (char *)base_uio_sysfs_name, 10);
|
|
- if (rc != 0)
|
|
- return rc;
|
|
-
|
|
- count = scandir(base_uio_sysfs_name,
|
|
- &files, filter_uio_name, alphasort);
|
|
-
|
|
- switch (count) {
|
|
- case 0:
|
|
- LOG_WARN(PFX "Couldn't find %s to determine uio minor",
|
|
- interface_name);
|
|
- return -EINVAL;
|
|
-
|
|
- case -1:
|
|
- LOG_WARN(PFX "Error when scanning for %s in path: %s [%s]",
|
|
- interface_name, base_uio_sysfs_name, strerror(errno));
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- path = malloc(PATH_MAX);
|
|
- if (path == NULL) {
|
|
- LOG_ERR(PFX "Could not allocate memory for path");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- /* Run through the contents of the filtered files to see if the
|
|
- * network interface name matches that of the uio device */
|
|
- for (i = 0; i < count; i++) {
|
|
- int uio_minor;
|
|
- char eth_name[IFNAMSIZ];
|
|
-
|
|
- rc = sscanf(files[i]->d_name, "uio%d", &uio_minor);
|
|
- if (rc != 1) {
|
|
- LOG_WARN("Could not parse: %s", files[i]->d_name);
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (!memcmp(host_pfx, nic->config_device_name,
|
|
- strlen(host_pfx))) {
|
|
- rc = from_uio_find_associated_host(nic, uio_minor,
|
|
- eth_name,
|
|
- sizeof(eth_name));
|
|
- } else {
|
|
- rc = from_uio_find_associated_eth_device(nic, uio_minor,
|
|
- eth_name,
|
|
- sizeof(eth_name));
|
|
- }
|
|
- if (rc != 0) {
|
|
- LOG_WARN("uio minor: %d not valid [%D]", uio_minor, rc);
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (strncmp(eth_name, interface_name, sizeof(eth_name)) == 0) {
|
|
- memcpy(nic->eth_device_name,
|
|
- eth_name, sizeof(nic->eth_device_name));
|
|
-
|
|
- LOG_INFO(PFX "%s associated with uio%d",
|
|
- nic->eth_device_name, uio_minor);
|
|
-
|
|
- rc = uio_minor;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_WARN("Could not find assoicate uio device with %s", interface_name);
|
|
-
|
|
- rc = -EINVAL;
|
|
-done:
|
|
- if (path != NULL)
|
|
- free(path);
|
|
-
|
|
- for (i = 0; i < count; i++)
|
|
- free(files[i]);
|
|
- free(files);
|
|
-
|
|
- return rc;
|
|
-
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_verify_uio_sysfs_name() - Using the name entry in sysfs it will try to
|
|
- * match the NIC library name
|
|
- * @param nic - The NIC hardware to check
|
|
- *
|
|
- */
|
|
-int nic_verify_uio_sysfs_name(nic_t *nic)
|
|
-{
|
|
- char *raw = NULL, *raw_tmp;
|
|
- uint32_t raw_size = 0;
|
|
- char temp_path[sizeof(nic_uio_sysfs_name_tempate) + 8];
|
|
- int rc = 0;
|
|
- nic_lib_handle_t *handle = NULL;
|
|
- size_t name_size;
|
|
-
|
|
-
|
|
- /* Build the path to determine uio name */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- nic_uio_sysfs_name_tempate, nic->uio_minor);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- /* sanitize name string by replacing newline with null termination */
|
|
- raw_tmp = raw;
|
|
- while (*raw_tmp != '\n' && raw_size--)
|
|
- raw_tmp++;
|
|
- *raw_tmp = '\0';
|
|
-
|
|
- /* If the nic library is not set then check if there is a library
|
|
- * which matches the uio sysfs name */
|
|
- if (nic->nic_library == NULL) {
|
|
- NIC_LIBRARY_EXIST_T exist;
|
|
-
|
|
- exist = does_nic_uio_name_exist(raw, &handle);
|
|
- if (exist == NIC_LIBRARY_DOESNT_EXIST) {
|
|
- LOG_ERR(PFX "%s: could not find library for uio name: %s",
|
|
- nic->log_name, raw);
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* fill the lib info */
|
|
- nic->nic_library = handle;
|
|
- nic->ops = handle->ops;
|
|
- (*nic->ops->lib_ops.get_library_name) (&nic->library_name,
|
|
- &name_size);
|
|
- } else {
|
|
- /* Get the uio sysfs name from the NIC library */
|
|
- (*nic->ops->lib_ops.get_uio_name) (&raw_tmp, &name_size);
|
|
-
|
|
- if (strncmp(raw, raw_tmp, name_size) != 0) {
|
|
- LOG_ERR(PFX "%s: uio names not equal: "
|
|
- "expecting %s got %s from %s",
|
|
- nic->log_name, raw, raw_tmp, temp_path);
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: Verified uio name %s with library %s",
|
|
- nic->log_name, raw, nic->library_name);
|
|
-
|
|
-error:
|
|
- if (raw)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_fill_name() - This will initialize all the hardware resources underneath
|
|
- * a struct cnic_uio device
|
|
- * @param nic - The nic device to attach the hardware with
|
|
- * @return 0 on success, on failure a errno will be returned
|
|
- */
|
|
-int nic_fill_name(nic_t *nic)
|
|
-{
|
|
- int rc;
|
|
-
|
|
- if ((nic->config_device_name != NULL) &&
|
|
- (memcmp(uio_base_dir, nic->config_device_name,
|
|
- sizeof(uio_base_dir) - 1) == 0)) {
|
|
- uint16_t uio_minor;
|
|
- char eth_name[sizeof(nic->eth_device_name)];
|
|
-
|
|
- wait_for_file_node_timed(nic, nic->config_device_name, 5);
|
|
-
|
|
- /* Determine the minor number for the UIO device */
|
|
- rc = sscanf(nic->config_device_name, uio_udev_path_template,
|
|
- &uio_minor);
|
|
- if (rc != 1) {
|
|
- LOG_WARN(PFX "%s: Could not parse for minor number",
|
|
- nic->uio_device_name);
|
|
- return -EINVAL;
|
|
- } else
|
|
- nic->uio_minor = uio_minor;
|
|
-
|
|
- nic->uio_device_name = nic->config_device_name;
|
|
-
|
|
- /* Determine the assoicated physical network interface */
|
|
- rc = from_uio_find_associated_eth_device(nic,
|
|
- nic->uio_minor,
|
|
- eth_name,
|
|
- sizeof(eth_name));
|
|
- if (rc != 0) {
|
|
- LOG_WARN(PFX "%s: Couldn't find associated eth device",
|
|
- nic->uio_device_name);
|
|
- } else {
|
|
- memcpy(nic->eth_device_name,
|
|
- eth_name, sizeof(eth_name));
|
|
- }
|
|
-
|
|
- LOG_INFO(PFX "%s: configured for uio device for %s",
|
|
- nic->log_name, nic->uio_device_name);
|
|
-
|
|
- } else {
|
|
- LOG_INFO(PFX "looking for uio device for %s",
|
|
- nic->config_device_name);
|
|
-
|
|
- rc = from_phys_name_find_assoicated_uio_device(nic);
|
|
- if (rc < 0) {
|
|
- LOG_ERR(PFX "Could not determine UIO name for %s",
|
|
- nic->config_device_name);
|
|
-
|
|
- return -rc;
|
|
- }
|
|
-
|
|
- nic->uio_minor = rc;
|
|
-
|
|
- if (nic->flags & NIC_UIO_NAME_MALLOC)
|
|
- free(nic->uio_device_name);
|
|
-
|
|
- nic->uio_device_name =
|
|
- malloc(sizeof(uio_udev_path_template) + 8);
|
|
- if (nic->uio_device_name == NULL) {
|
|
- LOG_INFO(PFX "%s: Couldn't malloc space for uio name",
|
|
- nic->log_name);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- snprintf(nic->uio_device_name,
|
|
- sizeof(uio_udev_path_template) + 8,
|
|
- uio_udev_path_template, nic->uio_minor);
|
|
-
|
|
- nic->flags |= NIC_UIO_NAME_MALLOC;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void cnic_get_sysfs_pci_resource_path(nic_t *nic, int resc_no,
|
|
- char *sys_path, size_t size)
|
|
-{
|
|
- /* Build the path to sysfs pci resource */
|
|
- snprintf(sys_path, size,
|
|
- cnic_uio_sysfs_resc_template, nic->uio_minor, resc_no);
|
|
-
|
|
-}
|
|
-
|
|
-void prepare_library(nic_t *nic)
|
|
-{
|
|
- int rc;
|
|
- NIC_LIBRARY_EXIST_T exist;
|
|
- nic_lib_handle_t *handle = NULL;
|
|
-
|
|
- nic_fill_name(nic);
|
|
-
|
|
- /* No assoicated library, we can skip it */
|
|
- if (nic->library_name != NULL) {
|
|
- /* Check that we have the proper NIC library loaded */
|
|
- exist = does_nic_library_exist(nic->library_name, &handle);
|
|
- if (exist == NIC_LIBRARY_DOESNT_EXIST) {
|
|
- LOG_ERR(PFX "NIC library doesn't exists: %s",
|
|
- nic->library_name);
|
|
- goto error;
|
|
- } else if (handle && (nic->nic_library == handle) &&
|
|
- (nic->ops == handle->ops)) {
|
|
- LOG_INFO("%s: Have NIC library '%s'",
|
|
- nic->log_name, nic->library_name);
|
|
- }
|
|
- }
|
|
-
|
|
- /* Verify the NIC library to use */
|
|
- rc = nic_verify_uio_sysfs_name(nic);
|
|
- if (rc != 0) {
|
|
- /* Determine the NIC library to use based on the PCI Id */
|
|
- rc = find_set_nic_lib(nic);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Couldn't find NIC library",
|
|
- nic->log_name);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- }
|
|
-
|
|
- LOG_INFO("%s: found NIC with library '%s'",
|
|
- nic->log_name, nic->library_name);
|
|
-error:
|
|
- return;
|
|
-}
|
|
-
|
|
-void prepare_nic_thread(nic_t *nic)
|
|
-{
|
|
- pthread_attr_t attr;
|
|
- int rc;
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- if (nic->thread == INVALID_THREAD) {
|
|
- struct timespec ts;
|
|
- struct timeval tp;
|
|
-
|
|
- LOG_INFO(PFX "%s: spinning up thread for nic", nic->log_name);
|
|
-
|
|
- /* Try to spin up the nic thread */
|
|
- pthread_attr_init(&attr);
|
|
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
- rc = pthread_create(&nic->thread, &attr, nic_loop, nic);
|
|
- if (rc != 0) {
|
|
- LOG_ERR(PFX "%s: Couldn't create thread for nic",
|
|
- nic->log_name);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- /* Convert from timeval to timespec */
|
|
- rc = gettimeofday(&tp, NULL);
|
|
- ts.tv_sec = tp.tv_sec;
|
|
- ts.tv_nsec = tp.tv_usec * 1000;
|
|
- ts.tv_sec += 5; /* TODO: hardcoded wait for 5 seconds */
|
|
-
|
|
- /* Wait for the nic loop thread to to running */
|
|
- rc = pthread_cond_timedwait(&nic->nic_loop_started_cond,
|
|
- &nic->nic_mutex, &ts);
|
|
-
|
|
- LOG_INFO("Created nic thread: %s", nic->log_name);
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
-error:
|
|
- return;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Functions used to enable/disable the NIC
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * nic_enable() - Function used to enable the NIC
|
|
- * @param nic - NIC to enable
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int nic_enable(nic_t *nic)
|
|
-{
|
|
- if (nic->flags & NIC_GOING_DOWN) {
|
|
- LOG_INFO(PFX "%s: NIC device is going down, "
|
|
- "flag: 0x%x state: 0x%x",
|
|
- nic->log_name, nic->flags, nic->state);
|
|
- return -EINVAL;
|
|
- }
|
|
- if (nic->state == NIC_STOPPED) {
|
|
- struct timespec ts;
|
|
- struct timeval tp;
|
|
- int rc;
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- /* Signal the device to enable itself */
|
|
- pthread_cond_broadcast(&nic->enable_wait_cond);
|
|
-
|
|
- nic->flags &= ~NIC_DISABLED;
|
|
- nic->flags |= NIC_ENABLED;
|
|
- nic->flags |= NIC_ENABLED_PENDING;
|
|
-
|
|
- /* Convert from timeval to timespec */
|
|
- rc = gettimeofday(&tp, NULL);
|
|
- ts.tv_sec = tp.tv_sec;
|
|
- ts.tv_nsec = tp.tv_usec * 1000;
|
|
- ts.tv_sec += 100;
|
|
-
|
|
- /* Wait for the device to be enabled */
|
|
- rc = pthread_cond_timedwait(&nic->enable_done_cond,
|
|
- &nic->nic_mutex, &ts);
|
|
- if (rc == 0 && nic->flags & NIC_ENABLED) {
|
|
- LOG_DEBUG(PFX "%s: device enabled", nic->log_name);
|
|
- } else {
|
|
- nic->flags &= ~NIC_ENABLED;
|
|
- nic->flags |= NIC_DISABLED;
|
|
- nic->flags &= ~NIC_ENABLED_PENDING;
|
|
-
|
|
- LOG_ERR(PFX "%s: waiting to finish nic_enable err: %s",
|
|
- nic->log_name, strerror(rc));
|
|
- }
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- return rc;
|
|
- } else {
|
|
- LOG_INFO(PFX "%s: device already enabled: "
|
|
- "flag: 0x%x state: 0x%x",
|
|
- nic->log_name, nic->flags, nic->state);
|
|
- return -EALREADY;
|
|
- }
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_disable() - Function used to disable the NIC
|
|
- * @param nic - NIC to disble
|
|
- * @return void
|
|
- */
|
|
-void nic_disable(nic_t *nic, int going_down)
|
|
-{
|
|
- if (nic->state == NIC_STARTED_RUNNING ||
|
|
- nic->state == NIC_RUNNING) {
|
|
- struct timespec ts;
|
|
- struct timeval tp;
|
|
- int rc;
|
|
-
|
|
- /* Wait for the device to be disabled */
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
-
|
|
- nic->flags &= ~NIC_ENABLED;
|
|
- nic->flags |= NIC_DISABLED;
|
|
- nic->flags &= ~NIC_STARTED_RUNNING;
|
|
- nic->state = NIC_STOPPED;
|
|
-
|
|
- if (going_down)
|
|
- nic->flags |= NIC_GOING_DOWN;
|
|
-
|
|
- /* Convert from timeval to timespec */
|
|
- rc = gettimeofday(&tp, NULL);
|
|
- if (rc) {
|
|
- LOG_ERR("gettimeofday failed, should never happen: %d\n", errno);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- return;
|
|
- }
|
|
-
|
|
- ts.tv_sec = tp.tv_sec;
|
|
- ts.tv_nsec = tp.tv_usec * 1000;
|
|
- ts.tv_sec += 5; /* TODO: hardcoded wait for 5 seconds */
|
|
-
|
|
- /* Wait for the device to be disabled */
|
|
- rc = pthread_cond_timedwait(&nic->disable_wait_cond,
|
|
- &nic->nic_mutex, &ts);
|
|
- if (rc) {
|
|
- LOG_ERR("cond_timedwait failed, should never happen: %d\n", errno);
|
|
- }
|
|
-
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- LOG_DEBUG(PFX "%s: device disabled", nic->log_name);
|
|
-
|
|
- } else {
|
|
- LOG_WARN(PFX "%s: device already disabled: "
|
|
- "flag: 0x%x state: 0x%x",
|
|
- nic->log_name, nic->flags, nic->state);
|
|
- }
|
|
-}
|
|
-
|
|
-void nic_close_all()
|
|
-{
|
|
- nic_t *nic;
|
|
-
|
|
- pthread_mutex_lock(&nic_list_mutex);
|
|
-
|
|
- /* Start the shutdown process */
|
|
- nic = nic_list;
|
|
- while (nic != NULL) {
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- nic_close(nic, 1, FREE_ALL_STRINGS);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- nic = nic->next;
|
|
- }
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
- LOG_INFO(PFX "All NICs closed");
|
|
-}
|
|
-
|
|
-void nic_remove_all()
|
|
-{
|
|
- nic_t *nic, *nic_next;
|
|
-
|
|
- pthread_mutex_lock(&nic_list_mutex);
|
|
-
|
|
- /* Start the shutdown process */
|
|
- nic = nic_list;
|
|
- while (nic != NULL) {
|
|
- nic_next = nic->next;
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- nic_close(nic, 1, FREE_ALL_STRINGS);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- nic_remove(nic);
|
|
- nic = nic_next;
|
|
- }
|
|
- pthread_mutex_unlock(&nic_list_mutex);
|
|
-
|
|
- LOG_INFO(PFX "All NICs removed");
|
|
-}
|
|
-
|
|
-
|
|
-/******************************************************************************
|
|
- * Routines to read initialized UIO values from sysfs
|
|
- *****************************************************************************/
|
|
-/**
|
|
- * determine_initial_uio_events() - This utility function will
|
|
- * determine the number of uio events that have occured on the
|
|
- * given device. This value is read from the UIO sysfs entry
|
|
- * @param dev - device to read from
|
|
- * @param num_of_event - number of UIO events
|
|
- * @return 0 is success, <0 failure
|
|
- */
|
|
-int detemine_initial_uio_events(nic_t *nic, uint32_t *num_of_events)
|
|
-{
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- ssize_t elements_read;
|
|
- char temp_path[sizeof(cnic_sysfs_uio_event_template) + 8];
|
|
- int rc;
|
|
-
|
|
- /* Capture RX buffer size */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- cnic_sysfs_uio_event_template, nic->uio_minor);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- elements_read = sscanf(raw, "%d", num_of_events);
|
|
- if (elements_read != 1) {
|
|
- LOG_ERR(PFX "%s: Couldn't parse UIO events size from %s",
|
|
- nic->log_name, temp_path);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = 0;
|
|
-error:
|
|
- if (raw)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int get_iscsi_transport_handle(nic_t *nic, uint64_t *handle)
|
|
-{
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- ssize_t elements_read;
|
|
- char temp_path[sizeof(iscsi_transport_handle_template) + 8];
|
|
- int rc;
|
|
-
|
|
- /* Capture RX buffer size */
|
|
- snprintf(temp_path, sizeof(temp_path),
|
|
- iscsi_transport_handle_template, nic->library_name);
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, temp_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- elements_read = sscanf(raw, "%" PRIu64, handle);
|
|
- if (elements_read != 1) {
|
|
- LOG_ERR(PFX "%s: Couldn't parse transport handle from %s",
|
|
- nic->log_name, temp_path);
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = 0;
|
|
-error:
|
|
- if (raw != NULL)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_set_all_nic_iface_mac_to_parent() - This is a utility function used to
|
|
- * intialize all the MAC addresses of the network interfaces for a given
|
|
- * CNIC UIO device
|
|
- * Call with nic mutex held
|
|
- * @param dev - CNIC UIO device to initialize
|
|
- */
|
|
-void nic_set_all_nic_iface_mac_to_parent(nic_t *nic)
|
|
-{
|
|
- nic_interface_t *current, *vlan_current;
|
|
-
|
|
- current = nic->nic_iface;
|
|
- while (current != NULL) {
|
|
- /* Set the initial MAC address of this interface to the parent
|
|
- * adapter */
|
|
- memcpy(current->mac_addr, nic->mac_addr, 6);
|
|
-
|
|
- vlan_current = current->vlan_next;
|
|
- while (vlan_current != NULL) {
|
|
- memcpy(vlan_current->mac_addr, nic->mac_addr, 6);
|
|
- vlan_current = vlan_current->vlan_next;
|
|
- }
|
|
- current = current->next;
|
|
- }
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC packet handling functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * nic_alloc_packet_buffer() - Used to allocate a packet buffer used to
|
|
- * send a TX packet later
|
|
- * @param nic - nic device to send the packet on
|
|
- * @param nic_iface - nic interface to send out on
|
|
- * @param buf - pointer to the buffer to send
|
|
- * @param buf_size - size in bytes of the buffer to send
|
|
- * @return pointer to the allocated packet buffer
|
|
- * NULL if memory could not be allocated
|
|
- */
|
|
-static packet_t *nic_alloc_packet_buffer(nic_t *nic,
|
|
- nic_interface_t *nic_iface,
|
|
- uint8_t *buf, size_t buf_size)
|
|
-{
|
|
- packet_t *pkt;
|
|
-
|
|
- pkt = malloc(sizeof(*pkt) + buf_size);
|
|
- if (pkt == NULL) {
|
|
- LOG_ERR(PFX "%s: Couldn't allocate space for packet buffer",
|
|
- nic->log_name);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- pkt->next = NULL;
|
|
- pkt->nic = nic;
|
|
- pkt->nic_iface = nic_iface;
|
|
- pkt->buf_size = buf_size;
|
|
- memcpy(pkt->buf, buf, buf_size);
|
|
-
|
|
- return pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_queue_tx_packet() - Used to queue a TX packet buffer to send later
|
|
- * @param nic - NIC device to send the packet on
|
|
- * @param nic_iface - NIC interface to send on the packet on
|
|
- * @param pkt - packet to queue
|
|
- * @return 0 if successful or <0 if unsuccessful
|
|
- */
|
|
-int nic_queue_tx_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface, packet_t *pkt)
|
|
-{
|
|
- packet_t *queued_pkt;
|
|
-
|
|
- queued_pkt = nic_alloc_packet_buffer(nic, nic_iface,
|
|
- pkt->buf, pkt->buf_size);
|
|
- if (queued_pkt == NULL) {
|
|
- LOG_ERR(PFX "%s: Couldn't allocate tx packet to queue",
|
|
- nic->log_name);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- if (nic->tx_packet_queue == NULL) {
|
|
- nic->tx_packet_queue = queued_pkt;
|
|
- } else {
|
|
- packet_t *current_pkt;
|
|
-
|
|
- current_pkt = nic->tx_packet_queue;
|
|
- while (current_pkt->next != NULL)
|
|
- current_pkt = current_pkt->next;
|
|
-
|
|
- current_pkt->next = queued_pkt;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "%s: tx packet queued", nic->log_name);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * nic_dequeue_tx_packet() - Used pop a TX packet buffer of the TX
|
|
- * @param dev - cnic_uio device to send the packet on
|
|
- * @param buf - pointer to the buffer to send
|
|
- * @param buf_size - size in bytes of the buffer to send
|
|
- * @return NULL if there are no more TX packet buffers to send
|
|
- * pointer to the packet buffer which is detached from the device
|
|
- */
|
|
-packet_t *nic_dequeue_tx_packet(nic_t *nic)
|
|
-{
|
|
- packet_t *pkt;
|
|
-
|
|
- pkt = nic->tx_packet_queue;
|
|
-
|
|
- /* There is a packet buffer to send, time to detach it from the
|
|
- * cnic_uio device */
|
|
- if (pkt != NULL) {
|
|
- nic->tx_packet_queue = pkt->next;
|
|
- pkt->next = NULL;
|
|
- }
|
|
-
|
|
- return pkt;
|
|
-}
|
|
-
|
|
-void nic_fill_ethernet_header(nic_interface_t *nic_iface,
|
|
- void *data,
|
|
- void *src_addr, void *dest_addr,
|
|
- int *pkt_size, void **start_addr,
|
|
- uint16_t ether_type)
|
|
-{
|
|
- struct ether_header *eth;
|
|
- uint16_t *vlan_hdr;
|
|
-
|
|
- eth = data;
|
|
-
|
|
- memcpy(eth->ether_shost, src_addr, ETH_ALEN);
|
|
- memcpy(eth->ether_dhost, dest_addr, ETH_ALEN);
|
|
-
|
|
- vlan_hdr = (uint16_t *) (eth + 1);
|
|
- eth->ether_type = htons(ether_type);
|
|
-
|
|
- *start_addr = vlan_hdr;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * NIC interface management utility functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * nic_find_nic_iface() - This function is used to find an interface
|
|
- * from the NIC
|
|
- * @param nic - NIC to look for network interfaces
|
|
- * @param vlan_id - VLAN id to look for
|
|
- * @param protocol - either AF_INET or AF_INET6
|
|
- * @param iface_num - iface num to use if present
|
|
- * @param request_type - IPV4/6 DHCP/STATIC
|
|
- * @return nic_iface - if found network interface with the given VLAN ID
|
|
- * if not found a NULL is returned
|
|
- */
|
|
-nic_interface_t *nic_find_nic_iface(nic_t *nic,
|
|
- uint16_t protocol,
|
|
- uint16_t vlan_id,
|
|
- int iface_num,
|
|
- int request_type)
|
|
-{
|
|
- nic_interface_t *current = nic->nic_iface;
|
|
- nic_interface_t *current_vlan = NULL;
|
|
-
|
|
- while (current != NULL) {
|
|
- LOG_DEBUG(PFX "%s: incoming protocol: %d, vlan_id:%d iface_num: %d, request_type: %d",
|
|
- nic->log_name, protocol, vlan_id, iface_num, request_type);
|
|
- LOG_DEBUG(PFX "%s: host:%d iface_num: 0x%x VLAN: %d protocol: %d",
|
|
- nic->log_name, nic->host_no, current->iface_num, current->vlan_id, current->protocol);
|
|
- if (current->protocol != protocol)
|
|
- goto next;
|
|
-
|
|
- /* Check for iface_num first */
|
|
- if (iface_num != IFACE_NUM_INVALID) {
|
|
- if (current->iface_num == iface_num) {
|
|
- /* Exception is when iface_num == 0, need to
|
|
- check for request_type also if !=
|
|
- IP_CONFIG_OFF */
|
|
- if (!iface_num && request_type !=
|
|
- IP_CONFIG_OFF) {
|
|
- if (current->request_type ==
|
|
- request_type)
|
|
- goto found;
|
|
- } else {
|
|
- goto found;
|
|
- }
|
|
- }
|
|
- } else if (vlan_id == NO_VLAN) {
|
|
- /* Just return the top of the family */
|
|
- goto found;
|
|
- } else {
|
|
- if ((current->vlan_id == vlan_id) &&
|
|
- ((request_type == IP_CONFIG_OFF) ||
|
|
- (current->request_type == request_type)))
|
|
- goto found;
|
|
- }
|
|
- /* vlan_next loop */
|
|
- current_vlan = current->vlan_next;
|
|
- while (current_vlan != NULL) {
|
|
- if (iface_num != IFACE_NUM_INVALID) {
|
|
- if (current_vlan->iface_num == iface_num) {
|
|
- if (!iface_num && request_type !=
|
|
- IP_CONFIG_OFF) {
|
|
- if (current_vlan->request_type
|
|
- == request_type)
|
|
- goto vlan_found;
|
|
- } else {
|
|
- goto vlan_found;
|
|
- }
|
|
- }
|
|
- }
|
|
- if ((current_vlan->vlan_id == vlan_id) &&
|
|
- ((request_type == IP_CONFIG_OFF) ||
|
|
- (current_vlan->request_type == request_type)))
|
|
- goto vlan_found;
|
|
-
|
|
- current_vlan = current_vlan->vlan_next;
|
|
- }
|
|
-next:
|
|
- current = current->next;
|
|
- }
|
|
-vlan_found:
|
|
- current = current_vlan;
|
|
-found:
|
|
- return current;
|
|
-}
|
|
-
|
|
-/* Called with nic mutex held */
|
|
-void persist_all_nic_iface(nic_t *nic)
|
|
-{
|
|
- nic_interface_t *current_vlan, *current;
|
|
-
|
|
- current = nic->nic_iface;
|
|
- while (current != NULL) {
|
|
- current->flags |= NIC_IFACE_PERSIST;
|
|
- current_vlan = current->vlan_next;
|
|
- while (current_vlan != NULL) {
|
|
- current_vlan->flags |= NIC_IFACE_PERSIST;
|
|
- current_vlan = current_vlan->vlan_next;
|
|
- }
|
|
- current = current->next;
|
|
- }
|
|
-}
|
|
-
|
|
-/* Sets the nic_iface to the front of the AF */
|
|
-void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
|
|
-{
|
|
- nic_interface_t *current, *prev;
|
|
- nic_interface_t *current_vlan, *prev_vlan;
|
|
-
|
|
- prev = NULL;
|
|
- current = nic->nic_iface;
|
|
- while (current != NULL) {
|
|
- if (current->protocol != nic_iface->protocol)
|
|
- goto next;
|
|
- /* If its already on top of the list, exit */
|
|
- if (current == nic_iface)
|
|
- goto done;
|
|
-
|
|
- prev_vlan = current;
|
|
- current_vlan = current->vlan_next;
|
|
-
|
|
- while (current_vlan != NULL) {
|
|
- if (current_vlan == nic_iface) {
|
|
- /* Found inside the vlan list */
|
|
- /* For vlan == 0, place on top of
|
|
- the AF list */
|
|
- prev_vlan->vlan_next =
|
|
- current_vlan->vlan_next;
|
|
- current_vlan->vlan_next = current;
|
|
- if (prev)
|
|
- prev->next = current_vlan;
|
|
- else
|
|
- nic->nic_iface = current_vlan;
|
|
- goto done;
|
|
- }
|
|
- prev_vlan = current_vlan;
|
|
- current_vlan = current_vlan->vlan_next;
|
|
- }
|
|
-next:
|
|
- prev = current;
|
|
- current = current->next;
|
|
- }
|
|
-done:
|
|
- return;
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Packet management utility functions
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * get_next_packet_in_queue() - This function will return the next packet in
|
|
- * the queue
|
|
- * @param queue - the queue to pull the packet from
|
|
- * @return the packet in the queue
|
|
- */
|
|
-static packet_t *get_next_packet_in_queue(packet_t **queue)
|
|
-{
|
|
- packet_t *pkt;
|
|
-
|
|
- if (*queue == NULL)
|
|
- return NULL;
|
|
-
|
|
- pkt = *queue;
|
|
- *queue = pkt->next;
|
|
-
|
|
- return pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * get_next_tx_packet() - This function will return the next packet in
|
|
- * the TX queue
|
|
- * @param nic - NIC to pull the TX packet from
|
|
- * @return the packet in hte queue
|
|
- */
|
|
-packet_t *get_next_tx_packet(nic_t *nic)
|
|
-{
|
|
- return get_next_packet_in_queue(&nic->tx_packet_queue);
|
|
-}
|
|
-
|
|
-/**
|
|
- * get_next_free_packet() - This function will return the next packet in
|
|
- * the free queue
|
|
- * @param nic - NIC to pull the RX packet from
|
|
- * @return the packet in hte queue
|
|
- */
|
|
-packet_t *get_next_free_packet(nic_t *nic)
|
|
-{
|
|
- packet_t *pkt;
|
|
- pthread_mutex_lock(&nic->free_packet_queue_mutex);
|
|
- pkt = get_next_packet_in_queue(&nic->free_packet_queue);
|
|
- pthread_mutex_unlock(&nic->free_packet_queue_mutex);
|
|
-
|
|
- if (pkt != NULL)
|
|
- reset_packet(pkt);
|
|
-
|
|
- return pkt;
|
|
-}
|
|
-
|
|
-/**
|
|
- * put_packet_in_queue() - This function will place the packet in the given
|
|
- * queue
|
|
- * @param pkt - the packet to place
|
|
- * @param queue - the queue to place the packet
|
|
- * @return the packet in the queue
|
|
- */
|
|
-static void put_packet_in_queue(packet_t *pkt, packet_t **queue)
|
|
-{
|
|
- if (*queue == NULL)
|
|
- *queue = pkt;
|
|
- else {
|
|
- pkt->next = *queue;
|
|
- *queue = pkt;
|
|
- }
|
|
-}
|
|
-
|
|
-/**
|
|
- * put_packet_in_tx_queue() - This function will place the packet in
|
|
- * the TX queue
|
|
- * @param pkt - packet to place
|
|
- * @param nic - NIC to pull the TX packet from
|
|
- * @return the packet in hte queue
|
|
- */
|
|
-void put_packet_in_tx_queue(packet_t *pkt, nic_t *nic)
|
|
-{
|
|
- return put_packet_in_queue(pkt, &nic->tx_packet_queue);
|
|
-}
|
|
-
|
|
-/**
|
|
- * put_packet_in_free_queue() - This function will place the packet in
|
|
- * the RX queue
|
|
- * @param pkt - packet to place
|
|
- * @param nic - NIC to pull the RX packet from
|
|
- * @return the packet in hte queue
|
|
- */
|
|
-void put_packet_in_free_queue(packet_t *pkt, nic_t *nic)
|
|
-{
|
|
- pthread_mutex_lock(&nic->free_packet_queue_mutex);
|
|
- put_packet_in_queue(pkt, &nic->free_packet_queue);
|
|
- pthread_mutex_unlock(&nic->free_packet_queue_mutex);
|
|
-}
|
|
-
|
|
-uint32_t calculate_default_netmask(uint32_t ip_addr)
|
|
-{
|
|
- uint32_t netmask;
|
|
-
|
|
- if (IN_CLASSA(ntohl(ip_addr)))
|
|
- netmask = htonl(IN_CLASSA_NET);
|
|
- else if (IN_CLASSB(ntohl(ip_addr)))
|
|
- netmask = htonl(IN_CLASSB_NET);
|
|
- else if (IN_CLASSC(ntohl(ip_addr)))
|
|
- netmask = htonl(IN_CLASSC_NET);
|
|
- else {
|
|
- LOG_ERR("Unable to guess netmask for address %x\n", &ip_addr);
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return netmask;
|
|
-}
|
|
-
|
|
-void dump_packet_to_log(struct nic_interface *iface,
|
|
- uint8_t *buf, uint16_t buf_len)
|
|
-{
|
|
-
|
|
- FILE *file;
|
|
- char str[80];
|
|
- int i, count;
|
|
-
|
|
- file = fmemopen(str, sizeof(str), "w+");
|
|
- if (file == NULL) {
|
|
- LOG_ERR(PFX "Could not create logging file stream for packet "
|
|
- "logging: [%d: %s]", errno, strerror(errno));
|
|
- return;
|
|
- }
|
|
-
|
|
- LOG_PACKET(PFX "%s: Start packet dump len: %d", iface->parent->log_name,
|
|
- buf_len);
|
|
-
|
|
- for (i = 0; i < buf_len; i++) {
|
|
- rewind(file);
|
|
- fprintf(file, "%03x: ", i);
|
|
-
|
|
- for (count = 0; (count < 8) && i < buf_len; count++, i++)
|
|
- fprintf(file, " %02x", buf[i]);
|
|
- fflush(file);
|
|
-
|
|
- LOG_PACKET(PFX "%s: %s", iface->parent->log_name, str);
|
|
- }
|
|
-
|
|
- LOG_PACKET(PFX "%s: end packet dump", iface->parent->log_name);
|
|
-
|
|
- fclose(file);
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * File Management
|
|
- ******************************************************************************/
|
|
- /**
|
|
- * determine_file_size_read() - when fstat doesn't work on filepath
|
|
- * within the /proc filesytem, we need to read/count the size of the file
|
|
- * until we hit a EOF
|
|
- * @parm filepath - path of the file in which to determine the filesize in
|
|
- * bytes
|
|
- * @return file size in bytes, <0 on failure
|
|
- */
|
|
-int determine_file_size_read(const char *filepath)
|
|
-{
|
|
- size_t total_size = 0;
|
|
- ssize_t size = 1;
|
|
- int fd;
|
|
- char buf[1024];
|
|
-
|
|
- fd = open(filepath, O_RDONLY);
|
|
- if (fd == -1) {
|
|
- LOG_ERR("Could not open file: %s [%s]",
|
|
- filepath, strerror(errno));
|
|
- return -1;
|
|
- }
|
|
-
|
|
- while (size > 0) {
|
|
- size = read(fd, buf, sizeof(buf));
|
|
-
|
|
- switch (size) {
|
|
- case 0:
|
|
- break;
|
|
- case -1:
|
|
- LOG_ERR("Error reading file: %s [%s]",
|
|
- filepath, strerror(errno));
|
|
- total_size = -1;
|
|
- break;
|
|
- default:
|
|
- total_size += size;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- close(fd);
|
|
-
|
|
- return total_size;
|
|
-}
|
|
-
|
|
-/**
|
|
- * capture_file() - Used to capture a file into a buffer
|
|
- * @param raw - This pointer will be set to the buffer which will hold the
|
|
- * file contents
|
|
- * @param raw_size - This is the size of the buffer returned
|
|
- * @param path - The file path to capture the data from
|
|
- * @return 0 is returned on success, <0 is returned on failure
|
|
- */
|
|
-int capture_file(char **raw, uint32_t *raw_size, const char *path)
|
|
-{
|
|
- FILE *fp;
|
|
- size_t read_size;
|
|
- int rc = 0;
|
|
- int file_size;
|
|
-
|
|
- file_size = determine_file_size_read(path);
|
|
- if (file_size < 0) {
|
|
- LOG_ERR("Could not determine size %s", path);
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- fp = fopen(path, "r");
|
|
- if (fp == NULL) {
|
|
- LOG_ERR("Could not open path %s [%s]", path, strerror(errno));
|
|
- return -EIO;
|
|
- }
|
|
-
|
|
- *raw = malloc(file_size);
|
|
- if (*raw == NULL) {
|
|
- LOG_ERR("Could not malloc space for capture %s", path);
|
|
- rc = -ENOMEM;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- read_size = fread(*raw, file_size, 1, fp);
|
|
- if (!read_size) {
|
|
- LOG_ERR("Could not read capture, path: %s len: %d [%s]",
|
|
- path, file_size, strerror(ferror(fp)));
|
|
- free(*raw);
|
|
- *raw = NULL;
|
|
- rc = errno;
|
|
- } else
|
|
- *raw_size = file_size;
|
|
-
|
|
-error:
|
|
- fclose(fp);
|
|
-
|
|
- LOG_INFO("Done capturing %s", path);
|
|
-
|
|
- return rc;
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic_utils.h b/iscsiuio/src/unix/nic_utils.h
|
|
deleted file mode 100644
|
|
index e4cf5c1..0000000
|
|
--- a/iscsiuio/src/unix/nic_utils.h
|
|
+++ /dev/null
|
|
@@ -1,104 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_util.h - NIC utility functions
|
|
- *
|
|
- */
|
|
-#ifndef __NIC_UTILS_H__
|
|
-#define __NIC_UTILS_H__
|
|
-
|
|
-#include "nic.h"
|
|
-
|
|
-/******************************************************************************
|
|
- * Function Prototype
|
|
- ******************************************************************************/
|
|
-int manually_trigger_uio_event(nic_t *nic, int uio_minor);
|
|
-
|
|
-int nic_discover_iscsi_hosts();
|
|
-
|
|
-int enable_mutlicast(nic_t *nic);
|
|
-int disable_mutlicast(nic_t *nic);
|
|
-
|
|
-int from_netdev_name_find_nic(char *interface_name, nic_t **nic);
|
|
-
|
|
-int from_host_no_find_associated_eth_device(int host_no, nic_t **nic);
|
|
-
|
|
-int from_phys_name_find_assoicated_uio_device(nic_t *nic);
|
|
-
|
|
-int nic_queue_tx_packet(nic_t *nic,
|
|
- nic_interface_t *nic_iface, packet_t *pkt);
|
|
-
|
|
-packet_t *nic_dequeue_tx_packet(nic_t *nic);
|
|
-
|
|
-void nic_fill_ethernet_header(nic_interface_t *nic_iface,
|
|
- void *data,
|
|
- void *src_addr, void *dest_addr,
|
|
- int *pkt_size, void **start_addr,
|
|
- uint16_t ether_type);
|
|
-
|
|
-struct nic_interface *nic_find_nic_iface(nic_t *nic, uint16_t protocol,
|
|
- uint16_t vlan_id, int iface_num,
|
|
- int request_type);
|
|
-void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
|
|
-
|
|
-void persist_all_nic_iface(nic_t *nic);
|
|
-
|
|
-int add_vlan_interfaces(nic_t *nic);
|
|
-
|
|
-int nic_verify_uio_sysfs_name(nic_t *nic);
|
|
-void cnic_get_sysfs_pci_resource_path(nic_t *nic, int resc_no,
|
|
- char *sys_path, size_t size);
|
|
-void nic_close_all();
|
|
-void nic_remove_all();
|
|
-
|
|
-int detemine_initial_uio_events(nic_t *nic, uint32_t *num_of_events);
|
|
-
|
|
-uint32_t calculate_default_netmask(uint32_t ip_addr);
|
|
-
|
|
-void prepare_nic_thread(nic_t *nic);
|
|
-void prepare_library(nic_t *nic);
|
|
-
|
|
-int nic_enable(nic_t *nic);
|
|
-void nic_disable(nic_t *nic, int going_down);
|
|
-
|
|
-void dump_packet_to_log(struct nic_interface *iface,
|
|
- uint8_t *buf, uint16_t buf_len);
|
|
-
|
|
-int determine_file_size_read(const char *filepath);
|
|
-int capture_file(char **raw, uint32_t *raw_size, const char *path);
|
|
-
|
|
-int get_iscsi_transport_handle(nic_t *nic, uint64_t *handle);
|
|
-
|
|
-#endif /* __NIC_UTILS_H__ */
|
|
diff --git a/iscsiuio/src/unix/nic_vlan.c b/iscsiuio/src/unix/nic_vlan.c
|
|
deleted file mode 100644
|
|
index eb33381..0000000
|
|
--- a/iscsiuio/src/unix/nic_vlan.c
|
|
+++ /dev/null
|
|
@@ -1,337 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_vlan.c - uIP user space stack VLAN utilities
|
|
- *
|
|
- */
|
|
-#define _GNU_SOURCE
|
|
-#include <errno.h>
|
|
-#include <fcntl.h>
|
|
-#include <pthread.h>
|
|
-#include <string.h>
|
|
-#include <stdio.h>
|
|
-#include <stdlib.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/stat.h>
|
|
-
|
|
-#include <arpa/inet.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/un.h>
|
|
-
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "nic_vlan.h"
|
|
-
|
|
-/*******************************************************************************
|
|
- * Constants
|
|
- ******************************************************************************/
|
|
-#define PFX "vlan"
|
|
-
|
|
-static const char proc_vlan_config_path[] = "/proc/net/vlan/config";
|
|
-
|
|
-/*******************************************************************************
|
|
- * Resolving Found VLAN's for CNIC
|
|
- ******************************************************************************/
|
|
-int init_vlan_found_handle(struct vlan_found_handle *found_handle,
|
|
- struct vlan_handle *handle)
|
|
-{
|
|
- memset(found_handle, 0, sizeof(*found_handle));
|
|
-
|
|
- found_handle->entries = malloc(found_handle->num_of_entries *
|
|
- sizeof(struct vlan_found_entry));
|
|
- if (found_handle->entries == NULL) {
|
|
- LOG_ERR("Could not allocate space for found entries");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- found_handle->handle = handle;
|
|
- found_handle->num_of_entries = handle->num_of_entries;
|
|
-
|
|
- memset(found_handle->entries, 0, found_handle->num_of_entries *
|
|
- sizeof(struct vlan_found_entry));
|
|
-
|
|
- handle->outstanding_found_handles++;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void release_vlan_found_handle(struct vlan_found_handle *found_handle)
|
|
-{
|
|
- if (found_handle->entries != NULL) {
|
|
- free(found_handle->entries);
|
|
- found_handle->entries = NULL;
|
|
- }
|
|
-
|
|
- found_handle->num_of_entries = 0;
|
|
-
|
|
- found_handle->handle->outstanding_found_handles--;
|
|
-
|
|
- found_handle->handle = NULL;
|
|
-
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * Resolving VLAN's for CNIC
|
|
- ******************************************************************************/
|
|
-/**
|
|
- * init_vlan_handle() - Used to initialize struct ipv4_route_handle so
|
|
- * that is can be used
|
|
- * @param handle - Pointer to struct ipv4_route_handle to initialize
|
|
- * @return 0 on success and <0 on failure
|
|
- */
|
|
-void init_vlan_table(struct vlan_handle *handle)
|
|
-{
|
|
- handle->entries = NULL;
|
|
- handle->num_of_entries = 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * parse_vlan_table() - Given the raw dump of a Linux vlan table, this
|
|
- * function will parse the into entries held by
|
|
- * struct vlan_handle
|
|
- * @param handle - struct vlan_handle used to hold the parsed contents
|
|
- * @param raw - buffer to parse the contents from
|
|
- * @param raw_size - size of the buffer in bytes
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int parse_vlan_table(struct vlan_handle *handle, char *raw, uint32_t raw_size)
|
|
-{
|
|
- FILE *fp;
|
|
- int i;
|
|
- char *token;
|
|
- size_t size;
|
|
- int rc;
|
|
-
|
|
- token = raw;
|
|
-
|
|
- /* determine the number of entries */
|
|
- while (*token != '\0') {
|
|
- if (*token == '\n')
|
|
- handle->num_of_entries++;
|
|
-
|
|
- token++;
|
|
- }
|
|
-
|
|
- /* There are 2 lines which describe the vlan table
|
|
- * This lines need to be skipped with counting */
|
|
- handle->num_of_entries -= 2;
|
|
-
|
|
- LOG_INFO("Number of vlan entries: %d", handle->num_of_entries);
|
|
-
|
|
- size = handle->num_of_entries * sizeof(struct vlan_entry);
|
|
- handle->entries = malloc(size);
|
|
- if (handle->entries == NULL) {
|
|
- LOG_ERR
|
|
- ("Couldn't malloc space to parse vlan table. entires: %d "
|
|
- "size: %d",
|
|
- handle->num_of_entries, size);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- fp = fmemopen(raw, raw_size, "r");
|
|
- if (fp == NULL) {
|
|
- LOG_ERR("Could not open raw dump of vlan table");
|
|
- rc = errno;
|
|
- goto fmemopen_error;
|
|
- }
|
|
-
|
|
- if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
|
|
- LOG_ERR("Empty or missing line, or read error");
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the second line. */
|
|
- LOG_ERR("Empty or missing line, or read error");
|
|
- rc = -EIO;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- i = 0;
|
|
- /* Time to parse the routing table */
|
|
- while (1) {
|
|
- struct vlan_entry *entry = &handle->entries[i];
|
|
- int r;
|
|
-
|
|
- r = fscanf(fp, "%15s |%hu |%15s",
|
|
- entry->vlan_iface_name,
|
|
- &entry->vlan_id, entry->phy_iface_name);
|
|
- if (r != 3) {
|
|
- if (feof(fp)) { /* EOF with no (nonspace) chars read. */
|
|
- break;
|
|
- }
|
|
-
|
|
- LOG_WARN("Parsing error: parsed %d elements", r);
|
|
- break;
|
|
- }
|
|
-
|
|
- i++;
|
|
-
|
|
- LOG_DEBUG("Vlan %d: vlan iface:%s vlan id:%d phys iface:%s",
|
|
- i,
|
|
- entry->vlan_iface_name,
|
|
- entry->vlan_id, entry->phy_iface_name);
|
|
- }
|
|
-
|
|
- fclose(fp);
|
|
-
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- fclose(fp);
|
|
-
|
|
-fmemopen_error:
|
|
- if (handle->entries != NULL)
|
|
- free(handle->entries);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * capture_vlan_table() - This function will snapshot the Linux vlan
|
|
- * routing table for further processing
|
|
- * @param handle - struct vlan_handle used to hold the routing context
|
|
- * @return 0 on success, <0 on failure
|
|
- */
|
|
-int capture_vlan_table(struct vlan_handle *handle)
|
|
-{
|
|
- char *raw = NULL;
|
|
- uint32_t raw_size = 0;
|
|
- int rc;
|
|
-
|
|
- rc = capture_file(&raw, &raw_size, proc_vlan_config_path);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
- rc = parse_vlan_table(handle, raw, raw_size);
|
|
- if (rc != 0)
|
|
- goto error;
|
|
-
|
|
-error:
|
|
- if (raw != NULL)
|
|
- free(raw);
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * release_vlan_table() - This function will free all resources used by
|
|
- * the handle
|
|
- * @param handle - struct vlan_handle used to hold the routing context
|
|
- */
|
|
-void release_vlan_table(struct vlan_handle *handle)
|
|
-{
|
|
- if (handle->entries != NULL) {
|
|
- free(handle->entries);
|
|
- handle->entries = NULL;
|
|
- }
|
|
-
|
|
- handle->num_of_entries = 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * find_phy_using_vlan_interface() - Given the interface name determine VLAN
|
|
- * tag ID to match either the physical or VLAN interface name
|
|
- * @param vlan_iface_name - VLAN interface used to find the physical
|
|
- * interface
|
|
- * @param phy_iface_name - returned value is the physical interface name
|
|
- * @param vlan_id - returned value is the VLAN id
|
|
- * @return 1 is returned if the interface is a VLAN, 0 if the interface is not
|
|
- * <0 is returned if there is an error
|
|
- */
|
|
-int find_phy_using_vlan_interface(struct vlan_handle *handle,
|
|
- char *vlan_iface_name,
|
|
- char **phy_iface_name, uint16_t *vlan_id)
|
|
-{
|
|
- int i, rc = 0;
|
|
-
|
|
- for (i = 0; i < handle->num_of_entries; i++) {
|
|
- struct vlan_entry *entry = &handle->entries[i];
|
|
-
|
|
- /* Compare VLAN interface names to find a match */
|
|
- if (strcmp(entry->vlan_iface_name, vlan_iface_name) == 0) {
|
|
- *phy_iface_name = entry->phy_iface_name;
|
|
- *vlan_id = entry->vlan_id;
|
|
- rc = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-/**
|
|
- * find_vlans_using_phy_interface() - Given the physical interface name this
|
|
- * function will determine the VLAN interface name and VLAN ID
|
|
- * @param iface_name - physical interface used to find the vlan interface
|
|
- * @param vlan_iface_name - returned value is the VLAN interface name
|
|
- * @return The number of VLAN interfaces found
|
|
- */
|
|
-int find_vlans_using_phy_interface(struct vlan_handle *handle,
|
|
- struct vlan_found_handle *found_handle,
|
|
- char *phy_iface_name)
|
|
-{
|
|
- int i, num_found = 0;
|
|
-
|
|
- for (i = 0; i < handle->num_of_entries; i++) {
|
|
- struct vlan_entry *entry = &handle->entries[i];
|
|
-
|
|
- /* Compare interface names to find a match */
|
|
- if (strcmp(entry->phy_iface_name, phy_iface_name) == 0) {
|
|
- found_handle->entries[i].found = VLAN_ENTRY_FOUND;
|
|
- num_found++;
|
|
- }
|
|
- }
|
|
-
|
|
- return num_found;
|
|
-}
|
|
-
|
|
-/**
|
|
- * valid_vlan() - determine if the vlan value which is passed is valid
|
|
- * @param vlan - vlan value to test
|
|
- * @return 0 - not valid, 1 - valid
|
|
- */
|
|
-int valid_vlan(short int vlan)
|
|
-{
|
|
- /* Allow vlan 1 to connect */
|
|
- if (vlan > 0 && vlan < 4095)
|
|
- return 1;
|
|
-
|
|
- return 0;
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/nic_vlan.h b/iscsiuio/src/unix/nic_vlan.h
|
|
deleted file mode 100644
|
|
index 610f721..0000000
|
|
--- a/iscsiuio/src/unix/nic_vlan.h
|
|
+++ /dev/null
|
|
@@ -1,89 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * nic_vlan.h - uIP user space stack VLAN utilities
|
|
- *
|
|
- */
|
|
-#ifndef __NIC_VLAN_H__
|
|
-#define __NIC_VLAN_H__
|
|
-
|
|
-#include <sys/types.h>
|
|
-
|
|
-/* Used to hold entries in the vlan table */
|
|
-struct vlan_entry {
|
|
- char vlan_iface_name[16];
|
|
- char phy_iface_name[16];
|
|
- uint16_t vlan_id;
|
|
-};
|
|
-
|
|
-struct vlan_handle {
|
|
- struct vlan_entry *entries;
|
|
- uint32_t num_of_entries;
|
|
-
|
|
- uint32_t outstanding_found_handles;
|
|
-};
|
|
-
|
|
-struct vlan_found_entry {
|
|
-#define VLAN_ENTRY_FOUND 1
|
|
-#define VLAN_ENTRY_NOT_FOUND 0
|
|
- uint8_t found;
|
|
-};
|
|
-
|
|
-struct vlan_found_handle {
|
|
- struct vlan_handle *handle;
|
|
- uint32_t num_of_entries;
|
|
- struct vlan_found_entry *entries;
|
|
-};
|
|
-
|
|
-/*******************************************************************************
|
|
- * Function Prototypes
|
|
- ******************************************************************************/
|
|
-void init_vlan_table(struct vlan_handle *handle);
|
|
-int capture_vlan_table(struct vlan_handle *handle);
|
|
-void release_vlan_table(struct vlan_handle *handle);
|
|
-
|
|
-int find_phy_using_vlan_interface(struct vlan_handle *handle,
|
|
- char *vlan_iface_name,
|
|
- char **phy_iface_name, uint16_t *vlan_id);
|
|
-int find_vlans_using_phy_interface(struct vlan_handle *handle,
|
|
- struct vlan_found_handle *found_handle,
|
|
- char *phy_iface_name);
|
|
-
|
|
-int init_vlan_found_handle(struct vlan_found_handle *found_handle,
|
|
- struct vlan_handle *handle);
|
|
-void release_vlan_found_handle(struct vlan_found_handle *found_handle);
|
|
-
|
|
-int valid_vlan(short int vlan);
|
|
-#endif /* __NIC_VLAN_H__ */
|
|
diff --git a/iscsiuio/src/unix/options.h b/iscsiuio/src/unix/options.h
|
|
deleted file mode 100644
|
|
index 63b8635..0000000
|
|
--- a/iscsiuio/src/unix/options.h
|
|
+++ /dev/null
|
|
@@ -1,118 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * options.h - CNIC UIO uIP user space stack
|
|
- *
|
|
- */
|
|
-#ifndef __OPTIONS_H__
|
|
-#define __OPTIONS_H__
|
|
-
|
|
-#include <byteswap.h>
|
|
-#include <time.h>
|
|
-#include <sys/types.h>
|
|
-
|
|
-/******************************************************************************
|
|
- * Constants which are tuned at compile time by the user
|
|
- *****************************************************************************/
|
|
-
|
|
-/**
|
|
- * MAX_COUNT_NIC_NL_RESP - This is the maximum number of polls uIP will
|
|
- * try for a kernel response after a PATH_REQ
|
|
- */
|
|
-#define MAX_COUNT_NIC_NL_RESP 128
|
|
-
|
|
-/**
|
|
- * NLM_BUF_DEFAULT_MAX - This is the buffer size allocated for the send/receive
|
|
- * buffers used by the uIP Netlink subsystem. This
|
|
- * value is in bytes.
|
|
- */
|
|
-#define NLM_BUF_DEFAULT_MAX 8192 /* bytes */
|
|
-
|
|
-/******************************************************************************
|
|
- * Non adjustable constants
|
|
- *****************************************************************************/
|
|
-#ifndef ETHERTYPE_IP
|
|
-#define ETHERTYPE_IP 0x0800 /* IP */
|
|
-#endif /* ETHERTYPE_IP */
|
|
-
|
|
-#ifndef ETHERTYPE_IPV6
|
|
-#define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */
|
|
-#endif /* ETHERTYPE_IPV6 */
|
|
-
|
|
-#ifndef ETHERTYPE_ARP
|
|
-#define ETHERTYPE_ARP 0x0806 /* Address resolution */
|
|
-#endif /* ETHERTYPE_ARP */
|
|
-
|
|
-#ifndef ETHERTYPE_VLAN
|
|
-#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tagging */
|
|
-#endif /* ETHERTYPE_VLAN */
|
|
-
|
|
-#define APP_NAME "iscsiuio"
|
|
-/* BUILD_DATE is automatically generated from the Makefile */
|
|
-
|
|
-#define DEBUG_OFF 0x1
|
|
-#define DEBUG_ON 0x2
|
|
-
|
|
-#define INVALID_FD -1
|
|
-#define INVALID_THREAD -1
|
|
-#define INVALID_HOST_NO -1
|
|
-
|
|
-struct options {
|
|
- char debug;
|
|
-
|
|
- /* Time the userspace daemon was started */
|
|
- time_t start_time;
|
|
-};
|
|
-
|
|
-extern int event_loop_stop;
|
|
-extern struct options opt;
|
|
-
|
|
-#ifdef WORDS_BIGENDIAN
|
|
-#define ntohll(x) (x)
|
|
-#define htonll(x) (x)
|
|
-#else
|
|
-#define ntohll(x) bswap_64(x)
|
|
-#define htonll(x) bswap_64(x)
|
|
-#endif
|
|
-
|
|
-# define likely(x) __builtin_expect(!!(x), 1)
|
|
-# define unlikely(x) __builtin_expect(!!(x), 0)
|
|
-
|
|
-/* taken from Linux kernel, include/linux/compiler-gcc.h */
|
|
-/* Optimization barrier */
|
|
-/* The "volatile" is due to gcc bugs */
|
|
-#define barrier() __asm__ __volatile__("": : :"memory")
|
|
-
|
|
-#endif
|
|
diff --git a/iscsiuio/src/unix/packet.c b/iscsiuio/src/unix/packet.c
|
|
deleted file mode 100644
|
|
index 3ce2c6b..0000000
|
|
--- a/iscsiuio/src/unix/packet.c
|
|
+++ /dev/null
|
|
@@ -1,145 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * packet.c - packet management
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <stdio.h>
|
|
-#include <string.h>
|
|
-
|
|
-#include "logger.h"
|
|
-#include "packet.h"
|
|
-#include "nic.h"
|
|
-
|
|
-/**
|
|
- * alloc_packet() - Function used to allocate memory for a packet
|
|
- * @param max_buf_size - max packet size
|
|
- * @param priv_size - size of the assoicated private data
|
|
- * @return NULL if failed, on success return a pointer to the packet
|
|
- */
|
|
-struct packet *alloc_packet(size_t max_buf_size, size_t priv_size)
|
|
-{
|
|
- struct packet *pkt;
|
|
- void *priv;
|
|
-
|
|
- pkt = malloc(max_buf_size + sizeof(struct packet));
|
|
- if (pkt == NULL) {
|
|
- LOG_ERR("Could not allocate any memory for packet");
|
|
- return NULL;
|
|
- }
|
|
- memset(pkt, 0, max_buf_size + sizeof(struct packet));
|
|
-
|
|
- priv = malloc(priv_size);
|
|
- if (priv == NULL) {
|
|
- LOG_ERR("Could not allocate any memory for private structure");
|
|
- goto free_pkt;
|
|
- }
|
|
- memset(priv, 0, priv_size);
|
|
- pkt->max_buf_size = max_buf_size;
|
|
- pkt->priv = priv;
|
|
-
|
|
- return pkt;
|
|
-
|
|
-free_pkt:
|
|
- free(pkt);
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-void free_packet(struct packet *pkt)
|
|
-{
|
|
- if (pkt->priv != NULL)
|
|
- free(pkt->priv);
|
|
-
|
|
- free(pkt);
|
|
-}
|
|
-
|
|
-/**
|
|
- * reset_packet() - This will reset the packet fields to default values
|
|
- * @param pkt - the packet to reset
|
|
- */
|
|
-void reset_packet(packet_t *pkt)
|
|
-{
|
|
- pkt->next = NULL;
|
|
-
|
|
- pkt->flags = 0;
|
|
- pkt->vlan_tag = 0;
|
|
-
|
|
- pkt->buf_size = 0;
|
|
-
|
|
- pkt->data_link_layer = NULL;
|
|
- pkt->network_layer = NULL;
|
|
-}
|
|
-
|
|
-int alloc_free_queue(nic_t *nic, size_t num_of_packets)
|
|
-{
|
|
- int i;
|
|
-
|
|
- pthread_mutex_lock(&nic->free_packet_queue_mutex);
|
|
- for (i = 0; i < num_of_packets; i++) {
|
|
- packet_t *pkt;
|
|
-
|
|
- pkt = alloc_packet(STD_MTU_SIZE, STD_MTU_SIZE);
|
|
- if (pkt == NULL) {
|
|
- goto done;
|
|
- }
|
|
-
|
|
- reset_packet(pkt);
|
|
-
|
|
- pkt->next = nic->free_packet_queue;
|
|
- nic->free_packet_queue = pkt;
|
|
- }
|
|
-
|
|
-done:
|
|
- pthread_mutex_unlock(&nic->free_packet_queue_mutex);
|
|
-
|
|
- return i;
|
|
-}
|
|
-
|
|
-void free_free_queue(nic_t *nic)
|
|
-{
|
|
- packet_t *pkt, *pkt_next;
|
|
-
|
|
- pthread_mutex_lock(&nic->free_packet_queue_mutex);
|
|
- pkt = nic->free_packet_queue;
|
|
- while (pkt) {
|
|
- pkt_next = pkt->next;
|
|
- free_packet(pkt);
|
|
- pkt = pkt_next;
|
|
- }
|
|
- nic->free_packet_queue = NULL;
|
|
- pthread_mutex_unlock(&nic->free_packet_queue_mutex);
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/packet.h b/iscsiuio/src/unix/packet.h
|
|
deleted file mode 100644
|
|
index 19d1db9..0000000
|
|
--- a/iscsiuio/src/unix/packet.h
|
|
+++ /dev/null
|
|
@@ -1,78 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2009-2011, Broadcom Corporation
|
|
- * Copyright (c) 2014, QLogic Corporation
|
|
- *
|
|
- * Written by: Benjamin Li (benli@broadcom.com)
|
|
- *
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * packet.h - packet definitions
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-
|
|
-#ifndef __PACKET_H__
|
|
-#define __PACKET_H__
|
|
-
|
|
-#include "nic.h"
|
|
-
|
|
-#define STD_MTU_SIZE 1500
|
|
-
|
|
-struct nic;
|
|
-struct nic_interface;
|
|
-
|
|
-typedef struct packet {
|
|
- struct packet *next;
|
|
-
|
|
- uint32_t flags;
|
|
-#define VLAN_TAGGED 0x0001
|
|
- uint16_t vlan_tag;
|
|
-
|
|
- size_t max_buf_size;
|
|
- size_t buf_size;
|
|
-
|
|
- uint8_t *data_link_layer;
|
|
- uint8_t *network_layer;
|
|
-
|
|
- struct nic *nic;
|
|
- struct nic_interface *nic_iface;
|
|
-
|
|
- void *priv;
|
|
- uint8_t buf[];
|
|
-} packet_t;
|
|
-
|
|
-/******************************************************************************
|
|
- * Packet Function Declarations
|
|
- *****************************************************************************/
|
|
-int alloc_free_queue(struct nic *, size_t num_of_packets);
|
|
-void free_free_queue(struct nic *);
|
|
-void reset_packet(packet_t *pkt);
|
|
-
|
|
-#endif /* __PACKET_H__ */
|
|
diff --git a/iscsiuio/src/unix/ping.c b/iscsiuio/src/unix/ping.c
|
|
deleted file mode 100644
|
|
index 58a6d14..0000000
|
|
--- a/iscsiuio/src/unix/ping.c
|
|
+++ /dev/null
|
|
@@ -1,518 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2015, QLogic Corporation
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ping.c - Ping implementation for iscsiuio using ICMP/ICMPv6
|
|
- *
|
|
- */
|
|
-#include <errno.h>
|
|
-#include <pthread.h>
|
|
-#include <signal.h>
|
|
-#include <string.h>
|
|
-#include <time.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/socket.h>
|
|
-#include <sys/time.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <netinet/in.h>
|
|
-#include <arpa/inet.h>
|
|
-
|
|
-#include "iscsi_if.h"
|
|
-
|
|
-#include "uip.h"
|
|
-#include "uip_arp.h"
|
|
-#include "uip_eth.h"
|
|
-#include "dhcpc.h"
|
|
-#include "ipv6_ndpc.h"
|
|
-#include "ipv6.h"
|
|
-
|
|
-#include "logger.h"
|
|
-#include "nic.h"
|
|
-#include "nic_utils.h"
|
|
-#include "options.h"
|
|
-#include "packet.h"
|
|
-#include "bnx2.h"
|
|
-#include "bnx2x.h"
|
|
-#include "cnic.h"
|
|
-#include "ping.h"
|
|
-
|
|
-#define PFX "ping "
|
|
-
|
|
-static void fill_payload_data(struct uip_stack *ustack)
|
|
-{
|
|
- if (ustack->uip_slen)
|
|
- memset(ustack->uip_appdata, 'A', ustack->uip_slen);
|
|
-}
|
|
-
|
|
-static int prepare_icmpv4_req_pkt(struct ping_conf *png_c, struct packet *pkt,
|
|
- uip_ip4addr_t *dst_addr)
|
|
-{
|
|
- nic_interface_t *nic_iface = png_c->nic_iface;
|
|
- struct uip_stack *ustack = &nic_iface->ustack;
|
|
- struct uip_ipv4_hdr *ipv4_hdr = NULL;
|
|
- struct uip_icmpv4_hdr *icmpv4_hdr = NULL;
|
|
- u16_t uip_iph_len = 0;
|
|
- u16_t icmpv4_hdr_len = 0;
|
|
- u16_t uip_ip_icmph_len = 0;
|
|
- int mtu = 1500;
|
|
- int rc = 0;
|
|
-
|
|
- uip_iph_len = UIP_IPv4_H_LEN;
|
|
- icmpv4_hdr_len = sizeof(*icmpv4_hdr);
|
|
- uip_ip_icmph_len = uip_iph_len + icmpv4_hdr_len;
|
|
-
|
|
- ipv4_hdr = (struct uip_ipv4_hdr *)ustack->network_layer;
|
|
-
|
|
- icmpv4_hdr = (struct uip_icmpv4_hdr *) (ustack->network_layer +
|
|
- sizeof(struct uip_ipv4_hdr));
|
|
-
|
|
- /* fill IP header */
|
|
- ipv4_hdr->vhl = 0x45;
|
|
- ipv4_hdr->tos = 0;
|
|
- ++ustack->ipid;
|
|
- ipv4_hdr->ipid[0] = ustack->ipid >> 8;
|
|
- ipv4_hdr->ipid[1] = ustack->ipid & 0xff;
|
|
- ipv4_hdr->ipoffset[0] = 0;
|
|
- ipv4_hdr->ipoffset[1] = 0;
|
|
- ipv4_hdr->ttl = UIP_TTL;
|
|
- ipv4_hdr->proto = UIP_PROTO_ICMP;
|
|
- uip_ip4addr_copy(ipv4_hdr->srcipaddr, ustack->hostaddr);
|
|
- uip_ip4addr_copy(ipv4_hdr->destipaddr, dst_addr);
|
|
-
|
|
- LOG_INFO(PFX "src ipaddr: %d.%d.%d.%d",
|
|
- uip_ipaddr1(ipv4_hdr->srcipaddr),
|
|
- uip_ipaddr2(ipv4_hdr->srcipaddr),
|
|
- uip_ipaddr3(ipv4_hdr->srcipaddr),
|
|
- uip_ipaddr4(ipv4_hdr->srcipaddr));
|
|
-
|
|
- LOG_INFO(PFX "dest ipaddr: %d.%d.%d.%d",
|
|
- uip_ipaddr1(ipv4_hdr->destipaddr),
|
|
- uip_ipaddr2(ipv4_hdr->destipaddr),
|
|
- uip_ipaddr3(ipv4_hdr->destipaddr),
|
|
- uip_ipaddr4(ipv4_hdr->destipaddr));
|
|
-
|
|
- /* fill ICMP header */
|
|
- icmpv4_hdr->type = ICMP_ECHO;
|
|
- icmpv4_hdr->icode = 0;
|
|
- icmpv4_hdr->id = getpid() & 0xffff;
|
|
- png_c->id = icmpv4_hdr->id;
|
|
- icmpv4_hdr->seqno = ustack->ipid;
|
|
- png_c->seqno =icmpv4_hdr->seqno;
|
|
-
|
|
- /* appdata and sappdata point to the icmp payload */
|
|
- ustack->uip_appdata = ustack->network_layer + uip_ip_icmph_len;
|
|
- ustack->uip_sappdata = ustack->uip_appdata;
|
|
-
|
|
- if (nic_iface->mtu)
|
|
- mtu = nic_iface->mtu;
|
|
-
|
|
- if ((mtu - uip_ip_icmph_len) > png_c->datalen) {
|
|
- ustack->uip_slen = png_c->datalen;
|
|
- } else {
|
|
- png_c->state = ISCSI_PING_OVERSIZE_PACKET;
|
|
- LOG_ERR(PFX "MTU=%d, payload=%d\n",
|
|
- mtu, png_c->datalen);
|
|
- rc = -EINVAL;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- fill_payload_data(ustack);
|
|
-
|
|
- /* Calculate ICMP checksum. */
|
|
- icmpv4_hdr->icmpchksum = 0;
|
|
- icmpv4_hdr->icmpchksum = ~(uip_chksum((u16_t *)icmpv4_hdr,
|
|
- icmpv4_hdr_len +
|
|
- ustack->uip_slen));
|
|
- if (icmpv4_hdr->icmpchksum == 0)
|
|
- icmpv4_hdr->icmpchksum = 0xffff;
|
|
-
|
|
- /* IPv4 total length = IPv4 HLEN + ICMP HLEN + Payload len */
|
|
- ustack->uip_len = uip_ip_icmph_len + ustack->uip_slen;
|
|
- ipv4_hdr->len[0] = (ustack->uip_len >> 8);
|
|
- ipv4_hdr->len[1] = (ustack->uip_len & 0xff);
|
|
-
|
|
- /* Calculate IP checksum. */
|
|
- ipv4_hdr->ipchksum = 0;
|
|
- ipv4_hdr->ipchksum = ~(uip_ipchksum(ustack));
|
|
- if (ipv4_hdr->ipchksum == 0)
|
|
- ipv4_hdr->ipchksum = 0xffff;
|
|
-
|
|
- ++ustack->stats.ip.sent;
|
|
- /* Return and let the caller do the actual transmission. */
|
|
- ustack->uip_flags = 0;
|
|
-
|
|
-done:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void prepare_icmpv6_req_pkt(struct ping_conf *png_c, struct packet *pkt,
|
|
- uip_ip6addr_t *dst_addr,
|
|
- uip_ip6addr_t *src_addr)
|
|
-{
|
|
- nic_interface_t *nic_iface = png_c->nic_iface;
|
|
- struct uip_stack *ustack = &nic_iface->ustack;
|
|
- struct uip_ipv6_hdr *ipv6_hdr = NULL;
|
|
- uip_icmp_echo_hdr_t *icmp_echo_hdr = NULL;
|
|
- u16_t uip_iph_len = 0;
|
|
- u16_t icmp_echo_hdr_len = 0;
|
|
- u16_t uip_ip_icmph_len = 0;
|
|
- char ipbuf[INET6_ADDRSTRLEN] = {0};
|
|
-
|
|
- uip_iph_len = UIP_IPv6_H_LEN;
|
|
- icmp_echo_hdr_len = sizeof(*icmp_echo_hdr);
|
|
- uip_ip_icmph_len = uip_iph_len + icmp_echo_hdr_len;
|
|
-
|
|
- ipv6_hdr = (struct uip_ipv6_hdr *)ustack->network_layer;
|
|
-
|
|
- icmp_echo_hdr = (uip_icmp_echo_hdr_t *) (ustack->network_layer +
|
|
- sizeof(struct uip_ipv6_hdr));
|
|
-
|
|
- /* fill IPv6 header */
|
|
- ipv6_hdr->vtc = 0x60;
|
|
- ipv6_hdr->tcflow = 0;
|
|
- ipv6_hdr->flow = 0;
|
|
- ipv6_hdr->proto = UIP_PROTO_ICMP6;
|
|
- ipv6_hdr->ttl = UIP_TTL;
|
|
- uip_ip6addr_copy(ipv6_hdr->srcipaddr, src_addr);
|
|
- uip_ip6addr_copy(ipv6_hdr->destipaddr, dst_addr);
|
|
-
|
|
- memset(ipbuf, 0, sizeof(ipbuf));
|
|
- if (inet_ntop(AF_INET6, &ipv6_hdr->srcipaddr, ipbuf, INET6_ADDRSTRLEN))
|
|
- LOG_INFO(PFX "src ipaddr=%s", ipbuf);
|
|
-
|
|
- memset(ipbuf, 0, sizeof(ipbuf));
|
|
- if (inet_ntop(AF_INET6, &ipv6_hdr->destipaddr, ipbuf, INET6_ADDRSTRLEN))
|
|
- LOG_INFO(PFX "dest ipaddr=%s", ipbuf);
|
|
-
|
|
- /* fill ICMP header */
|
|
- icmp_echo_hdr->type = ICMPV6_ECHO_REQ;
|
|
- icmp_echo_hdr->icode = 0;
|
|
- icmp_echo_hdr->id = HOST_TO_NET16(getpid() & 0xffff);
|
|
- png_c->id = icmp_echo_hdr->id;
|
|
- ++ustack->ipid;
|
|
- icmp_echo_hdr->seqno = HOST_TO_NET16(ustack->ipid);
|
|
- png_c->seqno = icmp_echo_hdr->seqno;
|
|
-
|
|
- /* appdata and sappdata point to the icmp payload */
|
|
- ustack->uip_appdata = ustack->network_layer + uip_ip_icmph_len;
|
|
- ustack->uip_sappdata = ustack->uip_appdata;
|
|
- ustack->uip_slen = png_c->datalen;
|
|
-
|
|
- fill_payload_data(ustack);
|
|
-
|
|
- /* Total length = ETH HLEN + IPv6 HLEN + ICMP HLEN + Data len */
|
|
- ustack->uip_len = UIP_LLH_LEN + uip_ip_icmph_len + ustack->uip_slen;
|
|
- /* IPv6 payload len */
|
|
- ipv6_hdr->len = HOST_TO_NET16(icmp_echo_hdr_len + ustack->uip_slen);
|
|
-
|
|
- /* Calculate ICMP checksum. */
|
|
- icmp_echo_hdr->icmpchksum = 0;
|
|
- icmp_echo_hdr->icmpchksum = ~(uip_icmp6chksum(ustack));
|
|
-
|
|
- ++ustack->stats.ip.sent;
|
|
- /* Return and let the caller do the actual transmission. */
|
|
- ustack->uip_flags = 0;
|
|
- return;
|
|
-}
|
|
-
|
|
-static int chk_arp_entry_for_dst_addr(nic_t *nic, nic_interface_t *nic_iface,
|
|
- void *addr)
|
|
-{
|
|
- struct iscsi_path path;
|
|
- uip_ip4addr_t dst_addr4;
|
|
- uip_ip6addr_t dst_addr6;
|
|
-
|
|
- if (nic_iface->protocol == AF_INET) {
|
|
- memcpy(dst_addr4, addr, sizeof(uip_ip4addr_t));
|
|
- memcpy(&path.dst.v4_addr, dst_addr4, sizeof(struct in_addr));
|
|
- path.ip_addr_len = 4;
|
|
- } else {
|
|
- memcpy(dst_addr6, addr, sizeof(uip_ip6addr_t));
|
|
- memcpy(&path.dst.v6_addr, dst_addr6, sizeof(struct in6_addr));
|
|
- path.ip_addr_len = 16;
|
|
- }
|
|
-
|
|
- return cnic_handle_iscsi_path_req(nic, 0, NULL, &path, nic_iface);
|
|
-}
|
|
-
|
|
-static int fill_icmpv6_eth_hdr(struct uip_stack *ustack,
|
|
- uip_ip6addr_t *dst_addr6)
|
|
-{
|
|
- struct uip_eth_hdr *eth;
|
|
- __u8 mac_addr[6];
|
|
- struct ndpc_reqptr req_ptr;
|
|
- int rc = 0;
|
|
- int ret = 0;
|
|
-
|
|
- eth = (struct uip_eth_hdr *)ustack->data_link_layer;
|
|
- memcpy(eth->src.addr, ustack->uip_ethaddr.addr, sizeof(eth->src.addr));
|
|
-
|
|
- memset(mac_addr, 0, sizeof(mac_addr));
|
|
- req_ptr.eth = (void *)mac_addr;
|
|
- req_ptr.ipv6 = (void *)dst_addr6;
|
|
-
|
|
- ret = ndpc_request(ustack, &req_ptr, &rc, CHECK_ARP_TABLE);
|
|
- if (ret) {
|
|
- LOG_DEBUG(PFX "ndpc request failed");
|
|
- rc = ret;
|
|
- } else if (rc) {
|
|
- memcpy(eth->dest.addr, mac_addr, sizeof(eth->dest.addr));
|
|
- LOG_DEBUG(PFX "ipv6 arp entry present");
|
|
- rc = 0;
|
|
- } else {
|
|
- LOG_DEBUG(PFX "ipv6 arp entry not present");
|
|
- rc = -EAGAIN;
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static int determine_src_ipv6_addr(nic_interface_t *nic_iface,
|
|
- uip_ip6addr_t *dst_addr6,
|
|
- uip_ip6addr_t *src_addr6)
|
|
-{
|
|
- struct in6_addr *addr;
|
|
- int rc = 0;
|
|
- int ret = 0;
|
|
-
|
|
- if (nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
|
|
- memcpy(src_addr6, &nic_iface->ustack.hostaddr6,
|
|
- sizeof(uip_ip6addr_t));
|
|
- goto done;
|
|
- }
|
|
-
|
|
- ret = ndpc_request(&nic_iface->ustack, dst_addr6,
|
|
- &rc, CHECK_LINK_LOCAL_ADDR);
|
|
- if (ret) {
|
|
- LOG_DEBUG(PFX "Check LL failed");
|
|
- rc = ret;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if (rc) {
|
|
- LOG_DEBUG(PFX "Use LL");
|
|
- /* Get link local IPv6 address */
|
|
- addr = (struct in6_addr *)&nic_iface->ustack.linklocal6;
|
|
- rc = 0;
|
|
- } else {
|
|
- LOG_DEBUG(PFX "Use Best matched");
|
|
- ret = ndpc_request(&nic_iface->ustack,
|
|
- dst_addr6,
|
|
- &addr, GET_HOST_ADDR);
|
|
- if (ret) {
|
|
- LOG_DEBUG(PFX "Use Best matched failed");
|
|
- rc = ret;
|
|
- goto done;
|
|
- }
|
|
- if (addr == NULL) {
|
|
- LOG_DEBUG(PFX "No Best matched found");
|
|
- rc = -EINVAL;
|
|
- goto done;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Got the best matched src IP address */
|
|
- memcpy(src_addr6, addr, sizeof(struct in6_addr));
|
|
-
|
|
-done:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-void ping_init(struct ping_conf *png_c, void *addr, u16_t type, int datalen)
|
|
-{
|
|
- png_c->dst_addr = addr;
|
|
- png_c->proto = type;
|
|
- png_c->state = PING_INIT_STATE;
|
|
- png_c->datalen = datalen;
|
|
- return;
|
|
-}
|
|
-
|
|
-int do_ping_from_nic_iface(struct ping_conf *png_c)
|
|
-{
|
|
- packet_t *pkt;
|
|
- nic_interface_t *nic_iface = png_c->nic_iface;
|
|
- nic_t *nic = nic_iface->parent;
|
|
- struct uip_stack *ustack = &nic_iface->ustack;
|
|
- uip_ip4addr_t dst_addr4;
|
|
- uip_ip6addr_t dst_addr6;
|
|
- uip_ip6addr_t src_addr6;
|
|
- struct timer ping_timer;
|
|
- int rc = 0;
|
|
-
|
|
- memset(dst_addr4, 0, sizeof(uip_ip4addr_t));
|
|
- memset(dst_addr6, 0, sizeof(uip_ip6addr_t));
|
|
- memset(src_addr6, 0, sizeof(uip_ip6addr_t));
|
|
-
|
|
- if (nic_iface->protocol == AF_INET)
|
|
- memcpy(dst_addr4, png_c->dst_addr, sizeof(uip_ip4addr_t));
|
|
- else
|
|
- memcpy(dst_addr6, png_c->dst_addr, sizeof(uip_ip6addr_t));
|
|
-
|
|
- rc = chk_arp_entry_for_dst_addr(nic, nic_iface, png_c->dst_addr);
|
|
-
|
|
- if (rc && (nic_iface->protocol == AF_INET)) {
|
|
- png_c->state = ISCSI_PING_NO_ARP_RECEIVED;
|
|
- LOG_ERR(PFX "ARP failure for IPv4 dest addr");
|
|
- goto done;
|
|
- } else if ((rc < 1) && (nic_iface->protocol == AF_INET6)) {
|
|
- png_c->state = ISCSI_PING_NO_ARP_RECEIVED;
|
|
- LOG_ERR(PFX "ARP failure for IPv6 dest addr");
|
|
- goto done;
|
|
- } else if (rc < 0) {
|
|
- LOG_ERR(PFX "ARP failure");
|
|
- goto done;
|
|
- }
|
|
-
|
|
- pthread_mutex_lock(&nic->nic_mutex);
|
|
- pkt = get_next_free_packet(nic);
|
|
- if (pkt == NULL) {
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
- LOG_ERR(PFX "Unable to get a free packet buffer");
|
|
- rc = -EIO;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- prepare_ustack(nic, nic_iface, ustack, pkt);
|
|
-
|
|
- if (nic_iface->protocol == AF_INET) {
|
|
- rc = prepare_icmpv4_req_pkt(png_c, pkt, &dst_addr4);
|
|
- if (rc)
|
|
- goto put_pkt;
|
|
-
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len is
|
|
- * set to a value > 0. */
|
|
- if (ustack->uip_len > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
-
|
|
- prepare_ipv4_packet(nic, nic_iface, ustack, pkt);
|
|
-
|
|
- LOG_DEBUG(PFX "Send ICMP echo request");
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- ustack->uip_len = 0;
|
|
- }
|
|
- } else {
|
|
- rc = determine_src_ipv6_addr(nic_iface, &dst_addr6, &src_addr6);
|
|
- if (rc)
|
|
- goto put_pkt;
|
|
-
|
|
- prepare_icmpv6_req_pkt(png_c, pkt, &dst_addr6, &src_addr6);
|
|
-
|
|
- /* If the above function invocation resulted
|
|
- * in data that should be sent out on the
|
|
- * network, the global variable uip_len is
|
|
- * set to a value > 0. */
|
|
- if (ustack->uip_len > 0) {
|
|
- pkt->buf_size = ustack->uip_len;
|
|
-
|
|
- prepare_ipv6_packet(nic, nic_iface, ustack, pkt);
|
|
- rc = fill_icmpv6_eth_hdr(ustack, &dst_addr6);
|
|
- if (rc) {
|
|
- ustack->uip_len = 0;
|
|
- goto put_pkt;
|
|
- }
|
|
-
|
|
- LOG_DEBUG(PFX "Send ICMPv6 echo request");
|
|
- (*nic->ops->write) (nic, nic_iface, pkt);
|
|
- ustack->uip_len = 0;
|
|
- }
|
|
- }
|
|
-
|
|
-put_pkt:
|
|
- put_packet_in_free_queue(pkt, nic);
|
|
- pthread_mutex_unlock(&nic->nic_mutex);
|
|
-
|
|
- if (rc) {
|
|
- LOG_DEBUG(PFX "Ping request not transmitted");
|
|
- goto done;
|
|
- }
|
|
-
|
|
- timer_set(&ping_timer, CLOCK_SECOND * 10);
|
|
-
|
|
- while ((event_loop_stop == 0) &&
|
|
- (nic->flags & NIC_ENABLED) && !(nic->flags & NIC_GOING_DOWN)) {
|
|
-
|
|
- rc = nic_process_intr(nic, 1);
|
|
-
|
|
- while ((rc > 0) && (!(nic->flags & NIC_GOING_DOWN))) {
|
|
- rc = process_packets(nic, NULL, NULL, nic_iface);
|
|
- }
|
|
-
|
|
- if (!rc && (png_c->state == ISCSI_PING_SUCCESS)) {
|
|
- LOG_INFO(PFX "PING successful!");
|
|
- break;
|
|
- }
|
|
-
|
|
- if (timer_expired(&ping_timer)) {
|
|
- png_c->state = ISCSI_PING_TIMEOUT;
|
|
- LOG_ERR(PFX "PING timeout");
|
|
- rc = -EIO;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
-done:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-int process_icmp_packet(uip_icmp_echo_hdr_t *icmp_hdr,
|
|
- struct uip_stack *ustack)
|
|
-{
|
|
- struct ping_conf *png_c = (struct ping_conf *)ustack->ping_conf;
|
|
- int rc = 0;
|
|
-
|
|
- LOG_INFO(PFX "Verify ICMP echo reply");
|
|
-
|
|
- if ((icmp_hdr->type == ICMPV6_ECHO_REPLY &&
|
|
- png_c->proto == AF_INET6) ||
|
|
- (icmp_hdr->type == ICMP_ECHO_REPLY &&
|
|
- png_c->proto == AF_INET)) {
|
|
-
|
|
- if ((icmp_hdr->icode == 0) &&
|
|
- (icmp_hdr->id == png_c->id) &&
|
|
- (icmp_hdr->seqno == png_c->seqno)) {
|
|
- png_c->state = ISCSI_PING_SUCCESS;
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
- } else {
|
|
- rc = 1;
|
|
- }
|
|
-
|
|
- if (rc) {
|
|
- LOG_INFO(PFX "ICMP echo reply verification failed!");
|
|
- } else {
|
|
- LOG_INFO(PFX "ICMP echo reply OK");
|
|
- }
|
|
-
|
|
- return rc;
|
|
-}
|
|
diff --git a/iscsiuio/src/unix/ping.h b/iscsiuio/src/unix/ping.h
|
|
deleted file mode 100644
|
|
index 82ace6f..0000000
|
|
--- a/iscsiuio/src/unix/ping.h
|
|
+++ /dev/null
|
|
@@ -1,73 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2015, QLogic Corporation
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. All advertising materials mentioning features or use of this software
|
|
- * must display the following acknowledgement:
|
|
- * This product includes software developed by Adam Dunkels.
|
|
- * 4. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
- *
|
|
- * ping.h - PING header file
|
|
- *
|
|
- */
|
|
-
|
|
-#ifndef __PING_H__
|
|
-#define __PING_H__
|
|
-
|
|
-#include "nic_nl.h"
|
|
-#include "uip.h"
|
|
-
|
|
-#define ICMP_ECHO_REPLY 0
|
|
-#define ICMP_ECHO 8
|
|
-
|
|
-#define ICMPV6_ECHO_REQ 128
|
|
-#define ICMPV6_ECHO_REPLY 129
|
|
-
|
|
-#define DEF_ICMP_PAYLOAD 32
|
|
-#define DEF_ICMPV6_PAYLOAD 16
|
|
-
|
|
-#define PING_INIT_STATE (-1)
|
|
-
|
|
-struct ping_conf
|
|
-{
|
|
- nic_t *nic;
|
|
- nic_interface_t *nic_iface;
|
|
- void *data;
|
|
- int state;
|
|
- void *dst_addr;
|
|
- u16_t proto;
|
|
- u16_t id;
|
|
- u16_t seqno;
|
|
- u16_t datalen;
|
|
-};
|
|
-
|
|
-void ping_init(struct ping_conf *png_c, void *addr, u16_t type, int datalen);
|
|
-
|
|
-int do_ping_from_nic_iface(struct ping_conf *png_c);
|
|
-
|
|
-int process_icmp_packet(uip_icmp_echo_hdr_t *icmp_hdr,
|
|
- struct uip_stack *ustack);
|
|
-
|
|
-#endif /* __PING_H__ */
|
|
diff --git a/iscsiuio/src/unix/uip-conf.h b/iscsiuio/src/unix/uip-conf.h
|
|
deleted file mode 100644
|
|
index e6e11a5..0000000
|
|
--- a/iscsiuio/src/unix/uip-conf.h
|
|
+++ /dev/null
|
|
@@ -1,160 +0,0 @@
|
|
-/**
|
|
- * \addtogroup uipopt
|
|
- * @{
|
|
- */
|
|
-
|
|
-/**
|
|
- * \name Project-specific configuration options
|
|
- * @{
|
|
- *
|
|
- * uIP has a number of configuration options that can be overridden
|
|
- * for each project. These are kept in a project-specific uip-conf.h
|
|
- * file and all configuration names have the prefix UIP_CONF.
|
|
- */
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2006, Swedish Institute of Computer Science.
|
|
- * All rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, this list of conditions and the following disclaimer.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. Neither the name of the Institute nor the names of its contributors
|
|
- * may be used to endorse or promote products derived from this software
|
|
- * without specific prior written permission.
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
- * SUCH DAMAGE.
|
|
- *
|
|
- * This file is part of the uIP TCP/IP stack
|
|
- *
|
|
- */
|
|
-
|
|
-/**
|
|
- * \file
|
|
- * An example uIP configuration file
|
|
- * \author
|
|
- * Adam Dunkels <adam@sics.se>
|
|
- */
|
|
-
|
|
-#ifndef __UIP_CONF_H__
|
|
-#define __UIP_CONF_H__
|
|
-
|
|
-#include <inttypes.h>
|
|
-
|
|
-/**
|
|
- * 8 bit datatype
|
|
- *
|
|
- * This typedef defines the 8-bit type used throughout uIP.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-typedef uint8_t u8_t;
|
|
-
|
|
-/**
|
|
- * 16 bit datatype
|
|
- *
|
|
- * This typedef defines the 16-bit type used throughout uIP.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-typedef uint16_t u16_t;
|
|
-
|
|
-/**
|
|
- * 32 bit datatype
|
|
- *
|
|
- * This typedef defines the 16-bit type used throughout uIP.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-typedef uint32_t u32_t;
|
|
-
|
|
-/**
|
|
- * Statistics datatype
|
|
- *
|
|
- * This typedef defines the dataype used for keeping statistics in
|
|
- * uIP.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-typedef uint64_t uip_stats_t;
|
|
-
|
|
-/**
|
|
- * Maximum number of TCP connections.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_MAX_CONNECTIONS 40
|
|
-
|
|
-/**
|
|
- * Maximum number of listening TCP ports.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_MAX_LISTENPORTS 40
|
|
-
|
|
-/**
|
|
- * uIP buffer size.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_BUFFER_SIZE 420
|
|
-
|
|
-/**
|
|
- * CPU byte order.
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN
|
|
-
|
|
-/**
|
|
- * Logging on or off
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_LOGGING 1
|
|
-
|
|
-/**
|
|
- * UDP support on or off
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_UDP 1
|
|
-
|
|
-/**
|
|
- * UDP checksums on or off
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_UDP_CHECKSUMS 1
|
|
-
|
|
-/**
|
|
- * uIP statistics on or off
|
|
- *
|
|
- * \hideinitializer
|
|
- */
|
|
-#define UIP_CONF_STATISTICS 1
|
|
-
|
|
-#define UIP_CONF_IPV6 0
|
|
-
|
|
-#define INET_ADDRSTRLEN 16
|
|
-#define INET6_ADDRSTRLEN 46
|
|
-
|
|
-#endif /* __UIP_CONF_H__ */
|
|
-
|
|
-/** @} */
|
|
-/** @} */
|
|
--
|
|
2.34.1
|
|
|