This Technical reference is provided with the InterNiche NicheStack TCP/IP protocol stack sources. The purpose of this document is to provide enough information so that a moderately experienced "C" programmer with a reasonable understanding of TCP/IP protocols can port NicheStack to a new environment.
It is assumed that the InterNiche "Win32" sources are available as a reference. These sources can be compiled and linked to produce a Windows "Console Application" that contains the NicheStack and a simple user interface that allows the user to exercise the functionality of the stack. Depending on what other InterNiche software products have been purchased, this reference port will also include other modules that use the stack to communicate with other IP hosts. Examples of these other modules are an HTTP Server, SNMP MIB-II agent, FTP Server, and Telnet Server. These modules provide an implementation of NicheStack and related servers on a PC in a way that closely approximates the environment of embedded systems.
In this document the term "stack", when used without further qualification, means the NicheStack software and related code as ported to an embedded system. "System" refers to your embedded system. "Sockets" refers to the TCP API developed for UNIX at U.C. Berkeley. "Porting engineer" refers to the engineer who is porting the InterNiche software to an embedded system. A "user" or "end user" refers to the person who ultimately ends up using the product containing the ported InterNiche software. "FCS" is an acronym for "First Customer Ship", the point in the software development cycle when the product is declared ready to ship. A "packet" is a sequence of bytes sent on network hardware, also known as a "frame" or a datagram".
Names of files, C structures and C routines are displayed as follows: c_routine().
Samples of source code from C programs are displayed in these boxes:
/* C source file - the world's 1 millionth hello program. */ main() { printf("hello world.\n"); }
User Commands | |||
timers and task control | |||
stack | |||
Network Interface |
To the left is a simplified diagram of the events which drive a typical embedded networking stack and the responses it makes. An event occurs (e.g. a user enters a command, a packet is received or a timer goes off) and in response a call is made to the stack to handle the event. The stack will in turn make calls to the system: sending network packets, returning data or status information to the user and setting more timers. In an ideal situation, these calls to the system map directly - for example, the stack's external call to send a packet has the exact same syntax as the network interface's exported send call.
In the world of portable stacks the stack designer does not know what multitasking system, user applications or interfaces will be supported in the target system. A "portable" stack is one that's designed with simple, generic interfaces in these areas and a "glue" layer is created which maps this generic interface into the specific interfaces available on the target system. Using the example of sending a packet, the stack would be designed to call a generic send_packet()
routine and the porting engineer would code a "glue" routine to send the packet on the target system's network interface. On a DOS reference platform, for example, different glue routines are required for packet drivers, ODI drivers, SLIP drivers and PPP drivers.
Making a stack portable involves minimizing the number of glue routines and keeping the glue routines simple and therefore easy to implement. The glue routines also need to be well documented. The interfaces to the InterNiche stack have developed through many years of porting to a variety of processors, network media and multitasking systems. Wherever possible we have used standard interfaces (e.g. Sockets, ANSI C library) or included glue routines to illustrate their use.
The bulk of the work in porting a stack is understanding and implementing these glue routines. The InterNiche stack has the following categories of glue routines:
Before beginning a port, the porting engineer should ensure that the necessary resources are available in the target environment. There must be a processor (with some spare CPU power) with some sort of operating system or monitor, some RAM memory and some sort of network interface. The exact amounts of these resources will vary depending on which features are to be implemented, what kind of performance is required and how many simultaneous users are to be supported.
Here is a brief summary of the services NicheStack needs from the system:
There is no easy way to determine the exact memory sizes required, however a rough idea can be obtained by examining the "Win32" executables. The numbers presented in the table below were taken from Microsoft C "map" files for a compile for the Intel 386 processor with Microsoft C/C++ v6.0, using options to optimize code size ("/O1gs /Gs"). Most of the ipport.h_h build options have not been selected, some of which would result in larger, and some in smaller code sizes. These numbers, therefore, represent an untuned "starting point".
These numbers are subject to change, but are current as of 12/10/2004. Please contact InterNiche Support for more up-to-date values.
Bytes | Use |
---|---|
15,193 | TCP code space |
4,307 | IP module code space |
10,644 | PPP code space |
22,627 | IPSec code space |
11,685 | SNMPv1 code space |
5,342 | HTTP Server code space |
These sizes will change as the code is ported to different CPU architectures and compilers.
The most reasonable approach to assessing processing power requirements is to consider similar systems and proceed from there. For embedded agents, the InterNiche Win32 reference port is intended to provide a starting point. Protocols can be tested under load and multiple console applications can be run simultaneously, each with their own IP address.
The stack also requires a few basic services from the target system. These are listed here:
clock tick | A clock tick counter needs to be incremented at regular intervals. See cticks in the Timers and Multitasking section of this document. |
memory access | The standard calloc() and free() library calls are ideal. With the exception of TCP and the DHCP server, these are only called at startup time and can be replaced with a static or partition-based scheme. |
multitasking | The stack needs to obtain CPU cycles to process received packets (and handle time-outs) on a timely basis. Both methods are covered in the Task Control section of this manual. |
The source code that a customer receives when they purchase NicheStack is organized into several directories. This section describes this directory structure and the files contained therein.
Some directories contain code that is relatively target system independent. They contain the implementation of the TCP and IP protocols and the simple user interface. The expectation is that the source code contained in these directories should function with little or no modification on any target system (see exceptions described in the section titled Portable Files vs. Port Dependent Files.
These directories are briefly described below:
tcp | TCP and Sockets source files |
ip | IP and UDP source files |
net | network support |
misclib | user interface, IP address parsing code, other similar extra functions |
Other directories contain code that is relatively target system dependent. They contain code that allows the system independent code to run on a particular class of target systems, effectively providing the "glue layer" for several popular target systems. A few examples of these directories are listed below (this is not a complete list):
ace360 | Code to support the stack on ACE 360 boards. |
armarm | Code to support the stack on ARM's PID development board with SDT tools |
armgh | Code to support the stack on ARM's PID development board with GHS tools |
armintcp | Code to support the stack on ARM's Integrator/CP 946E-S development board |
armpid | Code to support the stack on ARM PID based development board. |
at91eb55 | Code to support the stack on Atmel AT91EB55 development board with ADS tools. |
cs89712 | Code to support the stack on Cirrus Logic's cs89712 ARM7 development board. |
dosmain | Code to support the stack in Intel x86 real mode, embedded DOS. |
evba7 | Code to support the stack on Ashling's EVBA7 (Philips LPC2100) evaluation board using ARM RVD tools. |
gh91eb55 | Code to support the stack on Atmel AT91EB55 development board with GHS tools |
keil167 | Code to support the stack on Keil Software's Net167 development board. |
malta4kc | Code to support the stack on MIPS Malta 4kc development board using GHS tools. |
mcf5235 | Code to run the stack on FreeScale's CF5235 using Cygwin and GCC |
mcf5272 | Code to support the stack on the Motorola ColdFire 5272 development board using GHS tools. |
mcf5485 | Code to run the stack on FreeScale's CF5485 using MetroWerks tools |
mpc860 | Code to support the stack on the Mototola MPC860 based MBX and FADS targets. |
mwcf5282 | Code to support the stack on the Mototola' ColdFire M5282EVB development board using MetroWerks tools. |
net186 | Code to support the stack in AMD Net186 board applications. |
nios2gcc | Code to support the stack running on Altera's Nios-II platform. |
snds300 | Code to support the stack on Samsung SNDS300 development board. |
tx3927 | Code to support the stack on Toshiba JMR-TX3927 (MIPS 3900) based board with GHS Tools. |
vrtxsa86 | Code to support the stack on Intel x86 processors running the VRTXsa RTOS. |
win32 | Code to support the stack on Microsoft Windows. |
If your target system matches the description of one of the above target systems then much of the job of porting the stack will have already been performed. If your target system does not match any of the above target systems then the job of porting the stack may entail more effort, however we want to emphasize that the above list is not complete. Please contact InterNiche to determine whether we have already developed a glue layer for your target system. Documentation describing the contents of these target system directories is contained in a file, readme.txt, found in the target directory.
Other directories will be present when additional InterNiche products, beyond the TCP/IP stack, have been purchased. The contents of these additional directories are the subject of other InterNiche product documentation. Examples of these directories are listed below (this too, is not a complete list of other InterNiche products):
http | HTTP (Hypertext Transport Protocol a.k.a. Web) server |
ipsec | IPSec protocol implementation |
ipv6 | IPv6 protocol implementation |
tftp | TFTP client and server code |
ftp | FTP client and server code |
ppp | PPP (Point to Point Protocol) network interface |
snmp | SNMPv1 (Simple Network Management Protocol) agent |
snmpv3 | SNMPv3 agent. |
dhcpsrv | DHCP (Dynamic Host Configuration Protocol) server |
natrt | NAT (Network Address Translation) router |
tcp | TCP protocol and sockets implementation |
telnet | Telnet server |
rip | RIP (Routing Information Protocol) server |
Some directories do not contain source code per se, but are useful in the process of compiling and linking the source code to produce executable programs.
tools | Contains batch files and programs that are used to build executables for some target systems. |
h | The target system include file directory described in the next section. |
Some aspects of a particular target system cannot be easily localized into a single source code directory. These are represented in include files that are included by source files contained in both target system independent and target system dependent directories. ipport.h_h
, which is discussed in greater detail later, is the most widely included example of files of this type but there are others.
Different versions of these target system include files are appropriate for different target systems. Therefore each target system dependent directory contains a set of these files that is appropriate for that specific target system. For example, the dosmain
directory contains a version of ipport.h_h
that is appropriate for 16 bit real mode DOS targets and the net186
directory contains a different version of ipport.h_h
that is appropriate for Net186 board targets. In order to avoid compilation problems that could be introduced by the presence of multiple include files with the same name in the same source tree, these target system include files, as they exist in the target system directories, are named using the file name suffix .h_h
instead of the conventional .h
.
The makefile in each of these target system directories then copies the .h_h
versions of these files from that target directory to a directory named h
, changing the extension from .h_h
to .h
in the process. Thus when the C compiler encounters a directive to include, for example, ipport.h
in a source file, there is only one instance of ipport.h
in the source tree and therefore the same ipport.h
will be included by each source file that includes it, independent of the include search path that has been specified to the compiler.
This scheme has some ramifications for porting engineers. The principal one being that if, during the course of a port, it is found to be necessary to modify one of these target system include files, the place to make the modification is NOT in the .h
version of the file that resides in the h
directory, but in the .h_h
version of the file that resides in the target system dependent directory. All files that end up in the \h directory should be considered to be transient files like object files. No modifications should be made to them directly.
Modifications made to the .h
include files that reside in the h
directory WILL BE LOST.
For example, if you were porting the stack to an AMD Net186 target system and found it necessary to modify a defined constant in ipport.h
, the file in which to make the change would be /net186/ipport.h_h
, not /h/ipport.h
.
The NicheStack source code files can be categorized according to their degree of portability. "Portable" files are those which should be compiled and used on any target system without modification. "Unportable" or "port dependent" files are those which might need to be modified or replaced for different target systems.
The net
and tcp
directories contain primarily portable files. The exceptions to this are tcpport.c
in the tcp
directory and ipport.c
in the ip directory. In general, files whose names include the string "port" that reside in directories containing mostly portable files are the port dependent files. The misclib
directory contains both portable and port dependent files.
Target system dependent directories contain primarily port dependent files. The likelihood that these port dependent files will need to be modified for a particular target system is related to how much that target system varies from the target system for which the target system directory was created.
We should point out that our classification of whether a particular file is portable or port dependent is very much a judgment call on our part. When we say that a file is portable, what we mean is that we don't think that it will need to be modified during the porting process, but there is always the possibility that the requirements of a particular target system or application will require that a portable file be modified. Likewise, when we say that a file is port dependent, it does not necessarily mean that the file will need to be modified.
Each source code directory in the InterNiche source tree contains a file named makefile
.
The makefile contained in a target system independent directory is used to compile each of the source files in that directory into a corresponding object file and combine those objects into an object library.
The makefile in a target system dependent directory is used to compile each of the source files in that directory into a corresponding object file and then to link the object libraries in the target system independent directories with the objects in the target system dependent directories to produce a program file that will execute on the target system. The degree of portability of each makefile depends on the build environment used by the porting engineer.
Typically, to build a target system executable program, the porting engineer would cd
to the target system dependent directory corresponding to the target system and invoke the make
program. The makefile in that directory then compiles the source files in that directory into objects, invokes the makefiles in the target system independent directories to produce the object libraries, and, finally, links the objects and libraries together to produce the target system executable.
Each makefile includes a file named cflags.mak
which is expected to reside in the top level directory (the directory to which all the other directories in the source tree are subdirectories). cflags.mak
is intended to contain many of the compiler package idiosyncrasies (things like the name of the compiler and linker executables, compiler flags, and file system paths). There are versions of cflags.mak for each supported compiler package. These are named as cflags.xxx
where "xxx
" extension is uniquely named for each supported compiler package.
Thus, if the porting engineer is using one of the supported compiler packages and wanted to build the executable program for a given target system, he would execute the following steps:
cflags.mak
in the top level directory.cd
to the appropriate target system directory.make
command. (Note that with the Microsoft compiler package, the nmake
command should be used).See the file toolnote.doc
for more details on supported compiler packages.
The above steps assume of course that the job of porting the stack to a given target system has already been completed. This porting process is the topic of most of the remainder of this document.
This section contains a detailed list of the files contained in the target system independent directories of the NicheStack source code tree (as described in the previous section, the contents of the target system dependent directories are described in separate documents). The list is ordered by the directories in which the files reside. Within each directory, files are ordered according to whether or not they are portable.
As a general rule, it should not be necessary for the porting engineer to modify the portable files.
If, during the course of a routine port, the porting engineer determines that modifications to portable files appear necessary, they should FIRST discuss the intended modifications with the InterNiche technical support staff.
The ip directory has the full-sized stack IP family protocols (ARP, ICMP, UDP) sources:
et_arp.c | |
icmp.c | |
iface.c | |
ip.c | |
ipdemux.c | |
ipnet.c | |
ipstart.c | |
ip_reasm.c | Optional, needed for IP fragmentation and reassembly |
iproute.c | |
pmtu.c | |
rtbtree.c | |
udp.c | |
ipmc.c | |
ipraw.c |
Port dependent ip directory source file:
ipport.c | intended as the file into which the porting engineer will place the calls to network interface initialization and shutdown routines. |
The net directory has network support software common to both NicheStack and NicheLite. This includes pktalloc, queue, macloop, slip, and dhcp code.
dhcpclnt.c | Optional, needed for DHCP client feature |
dhcputil.c | Optional, needed for DHCP client feature |
dnsclnt.c | |
ifmap.c | |
macloop.c | Optional MAC level loopback driver for testing |
udp_open.c | |
ping.c | Optional, only needed to support user ping command |
pktalloc.c | |
q.c | |
slip.c | |
slipif.c | |
slip.h | Optional, needed for SLIP support |
Port dependent net directory source file:
slipport.h | used to configure support for the Serial Line Internet Protocol |
The h
directory is a system wide include directory. Header files which are used in more than one directory go here. .h
copies of the .h_h
files are copied here from the individual target directory at build time.
app_ping.h | contains structure definitions and function prototypes used by the user interface's ping command |
arp.h | |
c_md5.c | |
bsdsock.h | |
comline.h | Only needed if SLIP or PPP is used |
common.h | |
cu_eng.h | |
eu_engxt.h | |
cu_port.h | |
cu_srv.h | |
genlist.h | |
icmp6.h | |
ifmap.h | |
ip6.h | |
ip6mibs.h | |
md5_gbl.h | |
msring.h | |
dhcpclnt.h | Optional, needed for DHCP client feature |
dns.h | |
ether.h | |
icmp.h | |
in_utils.h | contains miscellaneous structure definitions and function prototypes |
intimers.h | |
ip.h | |
mbuf.h | |
menu.h | contains structures and function prototypes used by the CUI |
memwrap.h | |
minip.h | |
msock.h | |
net.h | |
netbuf.h | |
nptcp.h | |
nptypes.h | |
nvfsio.h | contains structures and function prototypes used by non-volatile storage API |
nvparms.h | contains structure definitions for the data that is stored by various InterNiche applications using the non-volatile storage API |
profiler.h | |
pmtu.h | |
q.h | |
rfc1213_.h | |
smtpalrt.h | |
smtpport.h | |
snmpport.h | |
sockcall.h | |
socket6.h | |
socket.h | |
sockvar.h | |
syslog.h | |
task.h | |
tcp.h | |
tcpapp.h | |
tcpport.h | |
tk_crnos.h | |
tk_ntask.h | |
tk_thrdx.h | |
tk_psos.h | |
tk_vtxsa.h | |
udp.h | |
userpass.h | contains structure definitions that map user names to password that are used by various InterNiche applications which require user authentication |
vfsfiles.h |
The files in the tcp
directory primarily implement the TCP layer of NicheStack. The portable tcp directory source files are listed below:
in_pcb.h | |
protosw.h | |
tcpip.h | |
tcp_fsm.h | |
tcp_seq.h | |
tcp_timr.h | |
tcp_var.h | |
cvar.h | |
in_pcb.c | |
rawsock.c | |
nptcp.c | |
sockcall.c | |
socket.c | |
socket2.c | |
soselect.c | |
tcp_in.c | |
tcp_menu.c | |
tcp_out.c | |
tcp_subr.c | |
tcp_timr.c | |
tcp_usr.c | |
tcp_zio.c | |
tcpsack.c | |
udpsock.c |
The port dependent tcp
directory source files are listed and briefly described below:
tcpport.h | is used to configure various TCP and Sockets layer attributes. Its contents are described in more detail in a later section. |
tcpport.c | contains implementations of the tcp_sleep() and tcp_wakeup() functions which are porting-engineer provided functions that are described later in this document. It also contains the tcpinit() function which is called once during system initialization to initialize the TCP stack. |
The files in the misclib
directory contain code which implements a simple, character oriented user interface (CUI) that is useful for testing and monitoring the stack software. It also contains the implementation of a rudimentary, non-volatile data storage API that can be useful in embedded applications and other miscellaneous functions. The files in the misclib
directory are difficult to classify according to portability, so please take these classifications with a grain of salt.
The portable misclib
directory source files are listed below:
app_ping.c | implements the functionality of the standard, UNIX ping command that is executable as a menu option from the CUI. |
menulib.c | miscellaneous statistics display functions. |
menus.c | functions used by the menuing system of the user interface. |
nextcarg.c | function used for parsing user interface parameters. |
nrmenus.c | contains the definition of the CUI menu structure and many of the functions which implement the menu options. The menu options allow the porting engineer to perform many operations including:
|
nvparms.c | functions which parse the contents of an embedded file system into runtime configuration parameters. |
parseip.c | used for parsing IP address text. |
reshost.c | used by the ping CUI menu option to perform a DNS lookup on a host address. |
tcpcksum.c | performs TCP packet checksum calculation. |
tcp_echo.c | contains implementations of TCP echo client and server CUI menu options. |
udp_echo.c | contains implementations of UDP echo client and server CUI menu options. |
userpass.c | performs user and password maintenance for CUI menu options that demonstrate applications that require user authentication. |
The port dependent misclib directory source files are listed below:
in_utils.c | mostly contains functions which control how the user interface interacts with the user. |
nvfsio.c | includes an implementation of a FLASH file system. |
strilib.c | |
strlib.c | contains implementations of standard C library string manipulation functions for targets which do not have C libraries that contain these functions. |
ttyio.c | implementation of printf() and sprintf() that works in DOS TSRs. |
bsdsock.c | BSD Sockets porting aid. |
ccksum.c | RFC 1071 - C Checksum code. |
cu_srv.c | Test Program for Crypto Engine. |
dhcpsetup.c | Initialization code for DHCP Client. |
genlist.c | Generic List Implementation routines. |
memdev.c | Memory Device for VFS. |
memio.c | Interniche version of ANSI C calloc() and free() library routines. |
memwrap.c | Wrapper checking routines for Heap Management routines. |
msring.c | Ring buffer support routines for NicheLite TCP API. |
netmain.c | Generic multi-tasking startup file for non-superloop builds. |
pcycles.c | Routines to measure processing times for various types of packets. |
profiler.c | Profiler code to profile TCP/IP stack and application modules. |
rawiptst.c | Test program for raw IP Sockets API. |
rfsim.c | RF Network Simulator code to drop packets and add latency. |
rttest.c | Pseudo driver for speed testing routing module. |
soperror.c | perror() like implementation for Interniche Sockets errors. |
syslog.c | SysLog Client Implementation. |
task.c | NicheTask Co-Operative Multitasking Scheduler code. |
tk_crnos.c | Wrapper functions to port TK Macros to µC/OS-II. |
tk_psos.c | Wrapper functions to port TK Macros to PSOS RTOS. |
tk_vtxsa.c | Wrapper functions to port TK Macros to VrtxSA RTOS. |